1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: SingleSelectQueryComposer.cxx,v $
10 * $Revision: 1.28.18.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_dbaccess.hxx"
34 #include "composertools.hxx"
35 #include "core_resource.hrc"
36 #include "core_resource.hxx"
37 #include "dbastrings.hrc"
38 #include "HelperCollections.hxx"
39 #include "SingleSelectQueryComposer.hxx"
41 /** === begin UNO includes === **/
42 #include <com/sun/star/beans/PropertyAttribute.hpp>
43 #include <com/sun/star/container/XChild.hpp>
44 #include <com/sun/star/i18n/XLocaleData.hpp>
45 #include <com/sun/star/lang/DisposedException.hpp>
46 #include <com/sun/star/sdb/BooleanComparisonMode.hpp>
47 #include <com/sun/star/sdb/SQLFilterOperator.hpp>
48 #include <com/sun/star/sdbc/ColumnSearch.hpp>
49 #include <com/sun/star/sdbc/DataType.hpp>
50 #include <com/sun/star/sdbc/XResultSetMetaData.hpp>
51 #include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
52 #include <com/sun/star/uno/XAggregation.hpp>
53 #include <com/sun/star/util/XNumberFormatter.hpp>
54 /** === end UNO includes === **/
56 #include <comphelper/processfactory.hxx>
57 #include <comphelper/sequence.hxx>
58 #include <comphelper/types.hxx>
59 #include <cppuhelper/typeprovider.hxx>
60 #include <rtl/logfile.hxx>
61 #include <svtools/syslocale.hxx>
62 #include <tools/debug.hxx>
63 #include <tools/diagnose_ex.h>
64 #include <unotools/configmgr.hxx>
65 #include <unotools/sharedunocomponent.hxx>
69 using namespace ::dbaccess
;
70 using namespace ::dbtools
;
71 using namespace ::comphelper
;
72 using namespace ::connectivity
;
73 using namespace ::com::sun::star::uno
;
74 using namespace ::com::sun::star::beans
;
75 using namespace ::com::sun::star::sdbc
;
76 using namespace ::com::sun::star::sdb
;
77 using namespace ::com::sun::star::sdbcx
;
78 using namespace ::com::sun::star::container
;
79 using namespace ::com::sun::star::i18n
;
80 using namespace ::com::sun::star::lang
;
81 using namespace ::com::sun::star::script
;
82 using namespace ::com::sun::star::util
;
83 using namespace ::cppu
;
84 using namespace ::osl
;
85 using namespace ::utl
;
88 namespace BooleanComparisonMode
= ::com::sun::star::sdb::BooleanComparisonMode
;
91 #define STR_SELECT ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SELECT "))
92 #define STR_FROM ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" FROM "))
93 #define STR_WHERE ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" WHERE "))
94 #define STR_GROUP_BY ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" GROUP BY "))
95 #define STR_HAVING ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" HAVING "))
96 #define STR_ORDER_BY ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" ORDER BY "))
97 #define STR_AND ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" AND "))
98 #define STR_OR ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" OR "))
99 #define STR_LIKE ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" LIKE "))
100 #define STR_EQUAL ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" = "))
101 #define L_BRACKET ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("("))
102 #define R_BRACKET ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(")"))
103 #define COMMA ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(","))
105 // -------------------------------------------------------------------------
108 // .....................................................................
109 /** parses the given statement, using the given parser, returns a parse node representing
112 If the statement cannot be parsed, an error is thrown.
114 const OSQLParseNode
* parseStatement_throwError( OSQLParser
& _rParser
, const ::rtl::OUString
& _rStatement
, const Reference
< XInterface
>& _rxContext
)
116 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "frank.schoenheit@sun.com", "SingleSelectQueryComposer.cxx::parseStatement_throwError" );
117 ::rtl::OUString aErrorMsg
;
118 const OSQLParseNode
* pNewSqlParseNode
= _rParser
.parseTree( aErrorMsg
, _rStatement
);
119 if ( !pNewSqlParseNode
)
121 ::rtl::OUString
sSQLStateGeneralError( getStandardSQLState( SQL_GENERAL_ERROR
) );
122 SQLException
aError2( aErrorMsg
, _rxContext
, sSQLStateGeneralError
, 1000, Any() );
123 SQLException
aError1( _rStatement
, _rxContext
, sSQLStateGeneralError
, 1000, makeAny( aError2
) );
124 throw SQLException(_rParser
.getContext().getErrorMessage(OParseContext::ERROR_GENERAL
),_rxContext
,sSQLStateGeneralError
,1000,makeAny(aError1
));
126 return pNewSqlParseNode
;
129 // .....................................................................
130 /** checks whether the given parse node describes a valid single select statement, throws
133 void checkForSingleSelect_throwError( const OSQLParseNode
* pStatementNode
, OSQLParseTreeIterator
& _rIterator
,
134 const Reference
< XInterface
>& _rxContext
, const ::rtl::OUString
& _rOriginatingCommand
)
136 const OSQLParseNode
* pOldNode
= _rIterator
.getParseTree();
138 // determine the statement type
139 _rIterator
.setParseTree( pStatementNode
);
140 _rIterator
.traverseAll();
141 bool bIsSingleSelect
= ( _rIterator
.getStatementType() == SQL_STATEMENT_SELECT
);
143 // throw the error, if necessary
144 if ( !bIsSingleSelect
|| SQL_ISRULE( pStatementNode
, union_statement
) ) // #i4229# OJ
146 // restore the old node before throwing the exception
147 _rIterator
.setParseTree( pOldNode
);
148 // and now really ...
149 SQLException
aError1( _rOriginatingCommand
, _rxContext
, getStandardSQLState( SQL_GENERAL_ERROR
), 1000, Any() );
150 throw SQLException( DBACORE_RESSTRING( RID_STR_ONLY_QUERY
), _rxContext
,
151 getStandardSQLState( SQL_GENERAL_ERROR
), 1000, makeAny( aError1
) );
157 // .....................................................................
158 /** combines parseStatement_throwError and checkForSingleSelect_throwError
160 void parseAndCheck_throwError( OSQLParser
& _rParser
, const ::rtl::OUString
& _rStatement
,
161 OSQLParseTreeIterator
& _rIterator
, const Reference
< XInterface
>& _rxContext
)
163 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "frank.schoenheit@sun.com", "SingleSelectQueryComposer.cxx::parseAndCheck_throwError" );
164 const OSQLParseNode
* pNode
= parseStatement_throwError( _rParser
, _rStatement
, _rxContext
);
165 checkForSingleSelect_throwError( pNode
, _rIterator
, _rxContext
, _rStatement
);
168 // .....................................................................
169 /** transforms a parse node describing a complete statement into a pure select
170 statement, without any filter/order/groupby/having clauses
172 ::rtl::OUString
getPureSelectStatement( const OSQLParseNode
* _pRootNode
, Reference
< XConnection
> _rxConnection
)
174 ::rtl::OUString sSQL
= STR_SELECT
;
175 _pRootNode
->getChild(1)->parseNodeToStr( sSQL
, _rxConnection
);
176 _pRootNode
->getChild(2)->parseNodeToStr( sSQL
, _rxConnection
);
178 _pRootNode
->getChild(3)->getChild(0)->getChild(1)->parseNodeToStr( sSQL
, _rxConnection
);
182 /** resets an SQL iterator, including deletion of the parse tree, and disposal if desired
184 void resetIterator( OSQLParseTreeIterator
& _rIterator
, bool _bDispose
)
186 const OSQLParseNode
* pSqlParseNode
= _rIterator
.getParseTree();
187 _rIterator
.setParseTree(NULL
);
188 delete pSqlParseNode
;
190 _rIterator
.dispose();
194 DBG_NAME(OSingleSelectQueryComposer
)
195 // -------------------------------------------------------------------------
196 OSingleSelectQueryComposer::OSingleSelectQueryComposer(const Reference
< XNameAccess
>& _rxTables
,
197 const Reference
< XConnection
>& _xConnection
,
198 const ::comphelper::ComponentContext
& _rContext
)
199 :OSubComponent(m_aMutex
,_xConnection
)
200 ,OPropertyContainer(m_aBHelper
)
201 ,m_aSqlParser( _rContext
.getLegacyServiceFactory() )
202 ,m_aSqlIterator( _xConnection
, _rxTables
, m_aSqlParser
, NULL
)
203 ,m_aAdditiveIterator( _xConnection
, _rxTables
, m_aSqlParser
, NULL
)
204 ,m_aElementaryParts( (size_t)SQLPartCount
)
205 ,m_xConnection(_xConnection
)
206 ,m_xMetaData(_xConnection
->getMetaData())
207 ,m_xConnectionTables( _rxTables
)
208 ,m_aContext( _rContext
)
210 ,m_nBoolCompareMode( BooleanComparisonMode::EQUAL_INTEGER
)
212 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::OSingleSelectQueryComposer" );
213 DBG_CTOR(OSingleSelectQueryComposer
,NULL
);
215 if ( !m_aContext
.is() || !m_xConnection
.is() || !m_xConnectionTables
.is() )
216 throw IllegalArgumentException();
218 registerProperty(PROPERTY_ORIGINAL
,PROPERTY_ID_ORIGINAL
,PropertyAttribute::BOUND
|PropertyAttribute::READONLY
,&m_sOrignal
,::getCppuType(&m_sOrignal
));
220 m_aCurrentColumns
.resize(4);
222 m_aLocale
= SvtSysLocale().GetLocaleData().getLocale();
223 m_xNumberFormatsSupplier
= dbtools::getNumberFormats( m_xConnection
, sal_True
, m_aContext
.getLegacyServiceFactory() );
224 Reference
< XLocaleData
> xLocaleData
;
225 m_aContext
.createComponent( "com.sun.star.i18n.LocaleData", xLocaleData
);
226 LocaleDataItem aData
= xLocaleData
->getLocaleItem(m_aLocale
);
227 m_sDecimalSep
= aData
.decimalSeparator
;
228 OSL_ENSURE(m_sDecimalSep
.getLength() == 1,"OSingleSelectQueryComposer::OSingleSelectQueryComposer decimal separator is not 1 length");
231 Reference
< XChild
> xChild(_xConnection
, UNO_QUERY
);
234 Reference
< XPropertySet
> xProp(xChild
->getParent(),UNO_QUERY
);
237 Sequence
< PropertyValue
> aInfo
;
238 xProp
->getPropertyValue(PROPERTY_INFO
) >>= aInfo
;
239 const PropertyValue
* pBegin
= aInfo
.getConstArray();
240 const PropertyValue
* pEnd
= pBegin
+ aInfo
.getLength();
241 for (; pBegin
!= pEnd
; ++pBegin
)
243 if ( pBegin
->Name
== static_cast <rtl::OUString
> (PROPERTY_BOOLEANCOMPARISONMODE
) )
245 OSL_VERIFY( pBegin
->Value
>>= m_nBoolCompareMode
);
255 // -------------------------------------------------------------------------
256 OSingleSelectQueryComposer::~OSingleSelectQueryComposer()
258 DBG_DTOR(OSingleSelectQueryComposer
,NULL
);
259 ::std::vector
<OPrivateColumns
*>::iterator aColIter
= m_aColumnsCollection
.begin();
260 ::std::vector
<OPrivateColumns
*>::iterator aEnd
= m_aColumnsCollection
.end();
261 for(;aColIter
!= aEnd
;++aColIter
)
264 ::std::vector
<OPrivateTables
*>::iterator aTabIter
= m_aTablesCollection
.begin();
265 ::std::vector
<OPrivateTables
*>::iterator aTabEnd
= m_aTablesCollection
.end();
266 for(;aTabIter
!= aTabEnd
;++aTabIter
)
269 // -------------------------------------------------------------------------
271 void SAL_CALL
OSingleSelectQueryComposer::disposing(void)
273 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::disposing" );
274 OSubComponent::disposing();
276 MutexGuard
aGuard(m_aMutex
);
278 resetIterator( m_aSqlIterator
, true );
279 resetIterator( m_aAdditiveIterator
, true );
281 m_xConnectionTables
= NULL
;
282 m_xConnection
= NULL
;
284 clearCurrentCollections();
286 IMPLEMENT_FORWARD_XINTERFACE3(OSingleSelectQueryComposer
,OSubComponent
,OSingleSelectQueryComposer_BASE
,OPropertyContainer
)
287 IMPLEMENT_SERVICE_INFO1(OSingleSelectQueryComposer
,"org.openoffice.comp.dba.OSingleSelectQueryComposer",SERVICE_NAME_SINGLESELECTQUERYCOMPOSER
)
288 IMPLEMENT_TYPEPROVIDER3(OSingleSelectQueryComposer
,OSubComponent
,OSingleSelectQueryComposer_BASE
,OPropertyContainer
)
289 IMPLEMENT_PROPERTYCONTAINER_DEFAULTS(OSingleSelectQueryComposer
)
291 // -------------------------------------------------------------------------
292 // com::sun::star::lang::XUnoTunnel
293 sal_Int64 SAL_CALL
OSingleSelectQueryComposer::getSomething( const Sequence
< sal_Int8
>& rId
) throw(RuntimeException
)
295 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getSomething" );
296 if (rId
.getLength() == 16 && 0 == rtl_compareMemory(getImplementationId().getConstArray(), rId
.getConstArray(), 16 ) )
297 return reinterpret_cast<sal_Int64
>(this);
302 // -------------------------------------------------------------------------
303 // XSingleSelectQueryAnalyzer
304 ::rtl::OUString SAL_CALL
OSingleSelectQueryComposer::getQuery( ) throw(RuntimeException
)
306 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getQuery" );
307 ::connectivity::checkDisposed(OSubComponent::rBHelper
.bDisposed
);
308 ::osl::MutexGuard
aGuard( m_aMutex
);
310 TGetParseNode
F_tmp(&OSQLParseTreeIterator::getParseTree
);
311 return getStatementPart(F_tmp
,m_aSqlIterator
);
314 // -------------------------------------------------------------------------
315 void SAL_CALL
OSingleSelectQueryComposer::setQuery( const ::rtl::OUString
& command
) throw(SQLException
, RuntimeException
)
317 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "frank.schoenheit@sun.com", "OSingleSelectQueryComposer::setQuery" );
318 ::connectivity::checkDisposed(OSubComponent::rBHelper
.bDisposed
);
320 ::osl::MutexGuard
aGuard( m_aMutex
);
321 // first clear the tables and columns
322 clearCurrentCollections();
323 // now set the new one
324 setQuery_Impl(command
);
325 m_sOrignal
= command
;
327 // reset the additive iterator to the same statement
328 parseAndCheck_throwError( m_aSqlParser
, m_sOrignal
, m_aAdditiveIterator
, *this );
330 // we have no "elementary" parts anymore (means filter/groupby/having/order clauses)
331 for ( SQLPart eLoopParts
= Where
; eLoopParts
!= SQLPartCount
; incSQLPart( eLoopParts
) )
332 m_aElementaryParts
[ eLoopParts
] = ::rtl::OUString();
334 // -----------------------------------------------------------------------------
335 void OSingleSelectQueryComposer::setQuery_Impl( const ::rtl::OUString
& command
)
337 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "frank.schoenheit@sun.com", "OSingleSelectQueryComposer::setQuery_Impl" );
339 parseAndCheck_throwError( m_aSqlParser
, command
, m_aSqlIterator
, *this );
341 // strip it from all clauses, to have the pure SELECT statement
342 m_aPureSelectSQL
= getPureSelectStatement( m_aSqlIterator
.getParseTree(), m_xConnection
);
344 // update columns and tables
345 // why? Shouldn't this be done on request only?
346 // otherwise nothing is working anymore :-)
350 // -----------------------------------------------------------------------------
351 Sequence
< Sequence
< PropertyValue
> > SAL_CALL
OSingleSelectQueryComposer::getStructuredHavingClause( ) throw (RuntimeException
)
353 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getStructuredHavingClause" );
354 TGetParseNode
F_tmp(&OSQLParseTreeIterator::getSimpleHavingTree
);
355 return getStructuredCondition(F_tmp
);
357 // -------------------------------------------------------------------------
358 Sequence
< Sequence
< PropertyValue
> > SAL_CALL
OSingleSelectQueryComposer::getStructuredFilter( ) throw(RuntimeException
)
360 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getStructuredFilter" );
361 TGetParseNode
F_tmp(&OSQLParseTreeIterator::getSimpleWhereTree
);
362 return getStructuredCondition(F_tmp
);
364 // -----------------------------------------------------------------------------
365 void SAL_CALL
OSingleSelectQueryComposer::appendHavingClauseByColumn( const Reference
< XPropertySet
>& column
, sal_Bool andCriteria
) throw (SQLException
, RuntimeException
)
367 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::appendHavingClauseByColumn" );
368 ::std::mem_fun1_t
<bool,OSingleSelectQueryComposer
,::rtl::OUString
> F_tmp(&OSingleSelectQueryComposer::implSetHavingClause
);
369 setConditionByColumn(column
,andCriteria
,F_tmp
);
371 // -----------------------------------------------------------------------------
372 void SAL_CALL
OSingleSelectQueryComposer::appendFilterByColumn( const Reference
< XPropertySet
>& column
, sal_Bool andCriteria
) throw(SQLException
, RuntimeException
)
374 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::appendFilterByColumn" );
375 ::std::mem_fun1_t
<bool,OSingleSelectQueryComposer
,::rtl::OUString
> F_tmp(&OSingleSelectQueryComposer::implSetFilter
);
376 setConditionByColumn(column
,andCriteria
,F_tmp
);
378 // -----------------------------------------------------------------------------
379 ::rtl::OUString
OSingleSelectQueryComposer::impl_getColumnName_throw(const Reference
< XPropertySet
>& column
)
381 ::connectivity::checkDisposed(OSubComponent::rBHelper
.bDisposed
);
385 || !m_aCurrentColumns
[SelectColumns
]
386 || !column
->getPropertySetInfo()->hasPropertyByName(PROPERTY_NAME
)
389 String
sError(DBACORE_RESSTRING(RID_STR_COLUMN_UNKNOWN_PROP
));
390 sError
.SearchAndReplaceAscii("%value", ::rtl::OUString(PROPERTY_NAME
));
391 SQLException
aErr(sError
,*this,SQLSTATE_GENERAL
,1000,Any() );
392 throw SQLException(DBACORE_RESSTRING(RID_STR_COLUMN_NOT_VALID
),*this,SQLSTATE_GENERAL
,1000,makeAny(aErr
) );
395 ::rtl::OUString aName
,aNewName
;
396 column
->getPropertyValue(PROPERTY_NAME
) >>= aName
;
398 if ( !m_xMetaData
->supportsOrderByUnrelated() && m_aCurrentColumns
[SelectColumns
] && !m_aCurrentColumns
[SelectColumns
]->hasByName(aName
))
400 String
sError(DBACORE_RESSTRING(RID_STR_COLUMN_MUST_VISIBLE
));
401 sError
.SearchAndReplaceAscii("%name", aName
);
402 throw SQLException(sError
,*this,SQLSTATE_GENERAL
,1000,Any() );
406 // select ohne where und order by aufbauen
407 ::rtl::OUString aQuote
= m_xMetaData
->getIdentifierQuoteString();
408 if ( m_aCurrentColumns
[SelectColumns
]->hasByName(aName
) )
410 Reference
<XPropertySet
> xColumn
;
411 m_aCurrentColumns
[SelectColumns
]->getByName(aName
) >>= xColumn
;
412 OSL_ENSURE(xColumn
->getPropertySetInfo()->hasPropertyByName(PROPERTY_REALNAME
),"Property REALNAME not available!");
413 OSL_ENSURE(xColumn
->getPropertySetInfo()->hasPropertyByName(PROPERTY_TABLENAME
),"Property TABLENAME not available!");
414 OSL_ENSURE(xColumn
->getPropertySetInfo()->hasPropertyByName(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Function"))),"Property FUNCTION not available!");
416 ::rtl::OUString sRealName
,sTableName
;
417 xColumn
->getPropertyValue(PROPERTY_REALNAME
) >>= sRealName
;
418 xColumn
->getPropertyValue(PROPERTY_TABLENAME
) >>= sTableName
;
419 sal_Bool bFunction
= sal_False
;
420 xColumn
->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Function"))) >>= bFunction
;
421 if ( sRealName
== aName
)
427 if(sTableName
.indexOf('.',0) != -1)
429 ::rtl::OUString aCatlog
,aSchema
,aTable
;
430 ::dbtools::qualifiedNameComponents(m_xMetaData
,sTableName
,aCatlog
,aSchema
,aTable
,::dbtools::eInDataManipulation
);
431 sTableName
= ::dbtools::composeTableName( m_xMetaData
, aCatlog
, aSchema
, aTable
, sal_True
, ::dbtools::eInDataManipulation
);
434 sTableName
= ::dbtools::quoteName(aQuote
,sTableName
);
436 aNewName
= sTableName
;
437 aNewName
+= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("."));
438 aNewName
+= ::dbtools::quoteName(aQuote
,sRealName
);
442 aNewName
= ::dbtools::quoteName(aQuote
,aName
);
445 aNewName
= getTableAlias(column
) + ::dbtools::quoteName(aQuote
,aName
);
448 // -------------------------------------------------------------------------
449 void SAL_CALL
OSingleSelectQueryComposer::appendOrderByColumn( const Reference
< XPropertySet
>& column
, sal_Bool ascending
) throw(SQLException
, RuntimeException
)
451 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::appendOrderByColumn" );
452 ::osl::MutexGuard
aGuard( m_aMutex
);
453 ::rtl::OUString
sColumnName( impl_getColumnName_throw(column
) );
454 ::rtl::OUString sOrder
= getOrder();
455 if ( (sOrder
.getLength() != 0) && sColumnName
.getLength() )
457 sOrder
+= sColumnName
;
458 if ( !ascending
&& sColumnName
.getLength() )
459 sOrder
+= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" DESC "));
464 // -------------------------------------------------------------------------
465 void SAL_CALL
OSingleSelectQueryComposer::appendGroupByColumn( const Reference
< XPropertySet
>& column
) throw(SQLException
, RuntimeException
)
467 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::appendGroupByColumn" );
468 ::osl::MutexGuard
aGuard( m_aMutex
);
469 ::rtl::OUString
sColumnName( impl_getColumnName_throw(column
) );
470 OrderCreator aComposer
;
471 aComposer
.append( getGroup() );
472 aComposer
.append( sColumnName
);
473 setGroup( aComposer
.getComposedAndClear() );
475 // -------------------------------------------------------------------------
476 ::rtl::OUString
OSingleSelectQueryComposer::composeStatementFromParts( const ::std::vector
< ::rtl::OUString
>& _rParts
)
478 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::composeStatementFromParts" );
479 DBG_ASSERT( _rParts
.size() == (size_t)SQLPartCount
, "OSingleSelectQueryComposer::composeStatementFromParts: invalid parts array!" );
481 ::rtl::OUStringBuffer
aSql( m_aPureSelectSQL
);
482 for ( SQLPart eLoopParts
= Where
; eLoopParts
!= SQLPartCount
; incSQLPart( eLoopParts
) )
483 if ( _rParts
[ eLoopParts
].getLength() )
485 aSql
.append( getKeyword( eLoopParts
) );
486 aSql
.append( _rParts
[ eLoopParts
] );
489 return aSql
.makeStringAndClear();
492 // -------------------------------------------------------------------------
493 ::rtl::OUString SAL_CALL
OSingleSelectQueryComposer::getElementaryQuery() throw (::com::sun::star::uno::RuntimeException
)
495 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getElementaryQuery" );
496 return composeStatementFromParts( m_aElementaryParts
);
499 // -------------------------------------------------------------------------
500 void SAL_CALL
OSingleSelectQueryComposer::setElementaryQuery( const ::rtl::OUString
& _rElementary
) throw (::com::sun::star::sdbc::SQLException
, ::com::sun::star::uno::RuntimeException
)
502 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "frank.schoenheit@sun.com", "OSingleSelectQueryComposer::setElementaryQuery" );
503 ::connectivity::checkDisposed(OSubComponent::rBHelper
.bDisposed
);
504 ::osl::MutexGuard
aGuard( m_aMutex
);
506 // remember the 4 current "additive" clauses
507 ::std::vector
< ::rtl::OUString
> aAdditiveClauses( SQLPartCount
);
508 for ( SQLPart eLoopParts
= Where
; eLoopParts
!= SQLPartCount
; incSQLPart( eLoopParts
) )
509 aAdditiveClauses
[ eLoopParts
] = getSQLPart( eLoopParts
, m_aAdditiveIterator
, sal_False
);
511 // clear the tables and columns
512 clearCurrentCollections();
513 // set and parse the new query
514 setQuery_Impl( _rElementary
);
516 // get the 4 elementary parts of the statement
517 for ( SQLPart eLoopParts
= Where
; eLoopParts
!= SQLPartCount
; incSQLPart( eLoopParts
) )
518 m_aElementaryParts
[ eLoopParts
] = getSQLPart( eLoopParts
, m_aSqlIterator
, sal_False
);
520 // reset the the AdditiveIterator: m_aPureSelectSQL may have changed
523 parseAndCheck_throwError( m_aSqlParser
, composeStatementFromParts( aAdditiveClauses
), m_aAdditiveIterator
, *this );
525 catch( const Exception
& e
)
528 DBG_ERROR( "OSingleSelectQueryComposer::setElementaryQuery: there should be no error anymore for the additive statement!" );
529 // every part of the additive statement should have passed other tests already, and should not
530 // be able to cause any errors ... me thinks
534 // -------------------------------------------------------------------------
537 ::rtl::OUString
getComposedClause( const ::rtl::OUString _rElementaryClause
, const ::rtl::OUString _rAdditionalClause
,
538 TokenComposer
& _rComposer
, const ::rtl::OUString _rKeyword
)
541 _rComposer
.append( _rElementaryClause
);
542 _rComposer
.append( _rAdditionalClause
);
543 ::rtl::OUString sComposed
= _rComposer
.getComposedAndClear();
544 if ( sComposed
.getLength() )
545 sComposed
= _rKeyword
+ sComposed
;
550 // -------------------------------------------------------------------------
551 void OSingleSelectQueryComposer::setSingleAdditiveClause( SQLPart _ePart
, const ::rtl::OUString
& _rClause
)
553 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setSingleAdditiveClause" );
554 ::connectivity::checkDisposed(OSubComponent::rBHelper
.bDisposed
);
555 ::osl::MutexGuard
aGuard( m_aMutex
);
557 // if nothing is changed, do nothing
558 if ( getSQLPart( _ePart
, m_aAdditiveIterator
, sal_False
) == _rClause
)
561 // collect the 4 single parts as they're currently set
562 ::std::vector
< ::rtl::OUString
> aClauses
;
563 aClauses
.reserve( (size_t)SQLPartCount
);
564 for ( SQLPart eLoopParts
= Where
; eLoopParts
!= SQLPartCount
; incSQLPart( eLoopParts
) )
565 aClauses
.push_back( getSQLPart( eLoopParts
, m_aSqlIterator
, sal_True
) );
567 // overwrite the one part in question here
568 ::std::auto_ptr
< TokenComposer
> pComposer
;
569 if ( ( _ePart
== Where
) || ( _ePart
== Having
) )
570 pComposer
.reset( new FilterCreator
);
572 pComposer
.reset( new OrderCreator
);
573 aClauses
[ _ePart
] = getComposedClause( m_aElementaryParts
[ _ePart
], _rClause
,
574 *pComposer
, getKeyword( _ePart
) );
576 // construct the complete statement
577 ::rtl::OUStringBuffer
aSql(m_aPureSelectSQL
);
578 for ( SQLPart eLoopParts
= Where
; eLoopParts
!= SQLPartCount
; incSQLPart( eLoopParts
) )
579 aSql
.append(aClauses
[ eLoopParts
]);
582 setQuery_Impl(aSql
.makeStringAndClear());
584 // clear column collections which (might) have changed
585 clearColumns( ParameterColumns
);
586 if ( _ePart
== Order
)
587 clearColumns( OrderColumns
);
588 if ( _ePart
== Group
)
589 clearColumns( GroupByColumns
);
591 // also, since the "additive filter" change, we need to rebuild our "additive" statement
592 aSql
= m_aPureSelectSQL
;
593 // again, first get all the old additive parts
594 for ( SQLPart eLoopParts
= Where
; eLoopParts
!= SQLPartCount
; incSQLPart( eLoopParts
) )
595 aClauses
[ eLoopParts
] = getSQLPart( eLoopParts
, m_aAdditiveIterator
, sal_True
);
596 // then overwrite the one in question
597 aClauses
[ _ePart
] = getComposedClause( ::rtl::OUString(), _rClause
, *pComposer
, getKeyword( _ePart
) );
598 // and parse it, so that m_aAdditiveIterator is up to date
599 for ( SQLPart eLoopParts
= Where
; eLoopParts
!= SQLPartCount
; incSQLPart( eLoopParts
) )
600 aSql
.append(aClauses
[ eLoopParts
]);
603 parseAndCheck_throwError( m_aSqlParser
, aSql
.makeStringAndClear(), m_aAdditiveIterator
, *this );
605 catch( const Exception
& e
)
608 DBG_ERROR( "OSingleSelectQueryComposer::setSingleAdditiveClause: there should be no error anymore for the additive statement!" );
609 // every part of the additive statement should have passed other tests already, and should not
610 // be able to cause any errors ... me thinks
614 // -------------------------------------------------------------------------
615 void SAL_CALL
OSingleSelectQueryComposer::setFilter( const ::rtl::OUString
& filter
) throw(SQLException
, RuntimeException
)
617 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setFilter" );
618 setSingleAdditiveClause( Where
, filter
);
621 // -------------------------------------------------------------------------
622 void SAL_CALL
OSingleSelectQueryComposer::setOrder( const ::rtl::OUString
& order
) throw(SQLException
, RuntimeException
)
624 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setOrder" );
625 setSingleAdditiveClause( Order
, order
);
627 // -----------------------------------------------------------------------------
628 void SAL_CALL
OSingleSelectQueryComposer::setGroup( const ::rtl::OUString
& group
) throw (SQLException
, RuntimeException
)
630 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setGroup" );
631 setSingleAdditiveClause( Group
, group
);
633 // -------------------------------------------------------------------------
634 void SAL_CALL
OSingleSelectQueryComposer::setHavingClause( const ::rtl::OUString
& filter
) throw(SQLException
, RuntimeException
)
636 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setHavingClause" );
637 setSingleAdditiveClause( Having
, filter
);
640 // -------------------------------------------------------------------------
642 Reference
< XNameAccess
> SAL_CALL
OSingleSelectQueryComposer::getTables( ) throw(RuntimeException
)
644 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getTables" );
645 ::connectivity::checkDisposed(OSubComponent::rBHelper
.bDisposed
);
647 ::osl::MutexGuard
aGuard( m_aMutex
);
650 const OSQLTables
& aTables
= m_aSqlIterator
.getTables();
651 ::std::vector
< ::rtl::OUString
> aNames
;
652 OSQLTables::const_iterator aEnd
= aTables
.end();
653 for(OSQLTables::const_iterator aIter
= aTables
.begin(); aIter
!= aEnd
;++aIter
)
654 aNames
.push_back(aIter
->first
);
656 m_pTables
= new OPrivateTables(aTables
,m_xMetaData
->supportsMixedCaseQuotedIdentifiers(),*this,m_aMutex
,aNames
);
661 // -------------------------------------------------------------------------
663 Reference
< XNameAccess
> SAL_CALL
OSingleSelectQueryComposer::getColumns( ) throw(RuntimeException
)
665 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getColumns" );
666 ::connectivity::checkDisposed(OSubComponent::rBHelper
.bDisposed
);
667 ::osl::MutexGuard
aGuard( m_aMutex
);
668 if ( !!m_aCurrentColumns
[SelectColumns
] )
669 return m_aCurrentColumns
[SelectColumns
];
671 ::std::vector
< ::rtl::OUString
> aNames
;
672 ::vos::ORef
< OSQLColumns
> aSelectColumns
;
673 sal_Bool bCase
= sal_True
;
679 SharedUNOComponent
< XStatement
, DisposableComponent
> xStatement
;
680 SharedUNOComponent
< XPreparedStatement
, DisposableComponent
> xPreparedStatement
;
682 bCase
= m_xMetaData
->supportsMixedCaseQuotedIdentifiers();
683 aSelectColumns
= m_aSqlIterator
.getSelectColumns();
685 ::rtl::OUStringBuffer aSQL
;
686 aSQL
.append( m_aPureSelectSQL
);
687 aSQL
.append( STR_WHERE
);
689 // preserve the original WHERE clause
690 // #i102234# / 2009-06-02 / frank.schoenheit@sun.com
691 ::rtl::OUString sOriginalWhereClause
= getSQLPart( Where
, m_aSqlIterator
, sal_False
);
692 if ( sOriginalWhereClause
.getLength() )
694 aSQL
.appendAscii( " ( 0 = 1 ) AND ( " );
695 aSQL
.append( sOriginalWhereClause
);
696 aSQL
.appendAscii( " ) " );
700 aSQL
.appendAscii( " ( 0 = 1 ) " );
703 ::rtl::OUString sGroupBy
= getSQLPart( Group
, m_aSqlIterator
, sal_True
);
704 if ( sGroupBy
.getLength() )
705 aSQL
.append( sGroupBy
);
707 ::rtl::OUString
sSQL( aSQL
.makeStringAndClear() );
708 // normalize the statement so that it doesn't contain any application-level features anymore
709 ::rtl::OUString sError
;
710 const ::std::auto_ptr
< OSQLParseNode
> pStatementTree( m_aSqlParser
.parseTree( sError
, sSQL
, false ) );
711 DBG_ASSERT( pStatementTree
.get(), "OSingleSelectQueryComposer::getColumns: could not parse the column retrieval statement!" );
712 if ( pStatementTree
.get() )
713 if ( !pStatementTree
->parseNodeToExecutableStatement( sSQL
, m_xConnection
, m_aSqlParser
, NULL
) )
716 Reference
< XResultSetMetaData
> xResultSetMeta
;
717 Reference
< XResultSetMetaDataSupplier
> xResMetaDataSup
;
720 xPreparedStatement
.set( m_xConnection
->prepareStatement( sSQL
), UNO_QUERY_THROW
);
721 xResMetaDataSup
.set( xPreparedStatement
, UNO_QUERY_THROW
);
722 xResultSetMeta
.set( xResMetaDataSup
->getMetaData(), UNO_QUERY_THROW
);
724 catch( const Exception
& ) { }
726 if ( !xResultSetMeta
.is() )
728 xStatement
.reset( Reference
< XStatement
>( m_xConnection
->createStatement(), UNO_QUERY_THROW
) );
729 Reference
< XPropertySet
> xStatementProps( xStatement
, UNO_QUERY_THROW
);
730 try { xStatementProps
->setPropertyValue( PROPERTY_ESCAPE_PROCESSING
, makeAny( sal_False
) ); }
731 catch ( const Exception
& ) { DBG_UNHANDLED_EXCEPTION(); }
732 xResMetaDataSup
.set( xStatement
->executeQuery( sSQL
), UNO_QUERY_THROW
);
733 xResultSetMeta
.set( xResMetaDataSup
->getMetaData(), UNO_QUERY_THROW
);
736 if ( aSelectColumns
->get().empty() )
738 // This is a valid case. If we can syntactically parse the query, but not semantically
739 // (e.g. because it is based on a table we do not know), then there will be no SelectColumns
740 aSelectColumns
= ::connectivity::parse::OParseColumn::createColumnsForResultSet( xResultSetMeta
, m_xMetaData
);
744 const ::comphelper::UStringMixEqual
aCaseCompare( bCase
);
745 const ::comphelper::TStringMixEqualFunctor
aCaseCompareFunctor( bCase
);
746 typedef ::std::set
< size_t > SizeTSet
;
747 SizeTSet aUsedSelectColumns
;
749 sal_Int32 nCount
= xResultSetMeta
->getColumnCount();
750 OSL_ENSURE( (size_t) nCount
== aSelectColumns
->get().size(), "OSingleSelectQueryComposer::getColumns: inconsistent column counts, this might result in wrong columns!" );
751 for(sal_Int32 i
=1;i
<=nCount
;++i
)
753 ::rtl::OUString sName
= xResultSetMeta
->getColumnName(i
);
754 sal_Bool bFound
= sal_False
;
755 OSQLColumns::Vector::const_iterator aFind
= ::connectivity::find(aSelectColumns
->get().begin(),aSelectColumns
->get().end(),sName
,aCaseCompare
);
756 size_t nFoundSelectColumnPos
= aFind
- aSelectColumns
->get().begin();
757 if ( aFind
!= aSelectColumns
->get().end() )
759 if ( aUsedSelectColumns
.find( nFoundSelectColumnPos
) != aUsedSelectColumns
.end() )
760 { // we found a column name which exists twice
761 // so we start after the first found
764 aFind
= ::connectivity::findRealName(++aFind
,aSelectColumns
->get().end(),sName
,aCaseCompare
);
765 nFoundSelectColumnPos
= aFind
- aSelectColumns
->get().begin();
767 while ( ( aUsedSelectColumns
.find( nFoundSelectColumnPos
) != aUsedSelectColumns
.end() )
768 && ( aFind
!= aSelectColumns
->get().end() )
771 if ( aFind
!= aSelectColumns
->get().end() )
773 (*aFind
)->getPropertyValue(PROPERTY_NAME
) >>= sName
;
774 aUsedSelectColumns
.insert( nFoundSelectColumnPos
);
775 aNames
.push_back(sName
);
783 OSQLColumns::Vector::const_iterator aRealFind
= ::connectivity::findRealName(
784 aSelectColumns
->get().begin(), aSelectColumns
->get().end(), sName
, aCaseCompare
);
786 if ( i
> static_cast< sal_Int32
>( aSelectColumns
->get().size() ) )
788 aSelectColumns
->get().push_back(
789 ::connectivity::parse::OParseColumn::createColumnForResultSet( xResultSetMeta
, m_xMetaData
, i
)
791 OSL_ENSURE( aSelectColumns
->get().size() == (size_t)i
, "OSingleSelectQueryComposer::getColumns: inconsistency!" );
793 else if ( aRealFind
== aSelectColumns
->get().end() )
795 // we can now only look if we found it under the realname propertery
796 // here we have to make the assumption that the position is correct
797 OSQLColumns::Vector::iterator aFind2
= aSelectColumns
->get().begin() + i
-1;
798 Reference
<XPropertySet
> xProp(*aFind2
,UNO_QUERY
);
799 if ( !xProp
.is() || !xProp
->getPropertySetInfo()->hasPropertyByName( PROPERTY_REALNAME
) )
802 ::connectivity::parse::OParseColumn
* pColumn
= new ::connectivity::parse::OParseColumn(xProp
,bCase
);
803 pColumn
->setFunction(::comphelper::getBOOL(xProp
->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Function")))));
804 pColumn
->setAggregateFunction(::comphelper::getBOOL(xProp
->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AggregateFunction")))));
806 ::rtl::OUString sRealName
;
807 xProp
->getPropertyValue(PROPERTY_REALNAME
) >>= sRealName
;
808 ::std::vector
< ::rtl::OUString
>::iterator aFindName
;
809 if ( !sName
.getLength() )
810 xProp
->getPropertyValue(PROPERTY_NAME
) >>= sName
;
813 aFindName
= ::std::find_if(aNames
.begin(),aNames
.end(),::std::bind2nd(aCaseCompareFunctor
,sName
));
815 while ( aFindName
!= aNames
.end() )
817 sName
+= ::rtl::OUString::valueOf(++j
);
818 aFindName
= ::std::find_if(aNames
.begin(),aNames
.end(),::std::bind2nd(aCaseCompareFunctor
,sName
));
821 pColumn
->setName(sName
);
822 pColumn
->setRealName(sRealName
);
823 pColumn
->setTableName(::comphelper::getString(xProp
->getPropertyValue(PROPERTY_TABLENAME
)));
825 (aSelectColumns
->get())[i
-1] = pColumn
;
830 aUsedSelectColumns
.insert( (size_t)(i
- 1) );
831 aNames
.push_back( sName
);
834 catch(const Exception
&)
840 if ( aNames
.empty() )
841 m_aCurrentColumns
[ SelectColumns
] = OPrivateColumns::createWithIntrinsicNames( aSelectColumns
, bCase
, *this, m_aMutex
);
843 m_aCurrentColumns
[ SelectColumns
] = new OPrivateColumns( aSelectColumns
, bCase
, *this, m_aMutex
, aNames
);
845 return m_aCurrentColumns
[SelectColumns
];
847 // -------------------------------------------------------------------------
848 sal_Bool
OSingleSelectQueryComposer::setORCriteria(OSQLParseNode
* pCondition
, OSQLParseTreeIterator
& _rIterator
,
849 ::std::vector
< ::std::vector
< PropertyValue
> >& rFilters
, const Reference
< ::com::sun::star::util::XNumberFormatter
> & xFormatter
) const
851 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setORCriteria" );
852 // Runde Klammern um den Ausdruck
853 if (pCondition
->count() == 3 &&
854 SQL_ISPUNCTUATION(pCondition
->getChild(0),"(") &&
855 SQL_ISPUNCTUATION(pCondition
->getChild(2),")"))
857 return setORCriteria(pCondition
->getChild(1), _rIterator
, rFilters
, xFormatter
);
860 // a searchcondition can only look like this: search_condition SQL_TOKEN_OR boolean_term
861 else if (SQL_ISRULE(pCondition
,search_condition
))
863 sal_Bool bResult
= sal_True
;
864 for (int i
= 0; bResult
&& i
< 3; i
+=2)
866 // Ist das erste Element wieder eine OR-Verknuepfung?
867 // Dann rekursiv absteigen ...
868 //if (!i && SQL_ISRULE(pCondition->getChild(i),search_condition))
869 if (SQL_ISRULE(pCondition
->getChild(i
),search_condition
))
870 bResult
= setORCriteria(pCondition
->getChild(i
), _rIterator
, rFilters
, xFormatter
);
873 rFilters
.push_back( ::std::vector
< PropertyValue
>());
874 bResult
= setANDCriteria(pCondition
->getChild(i
), _rIterator
, rFilters
[rFilters
.size() - 1], xFormatter
);
881 rFilters
.push_back(::std::vector
< PropertyValue
>());
882 return setANDCriteria(pCondition
, _rIterator
, rFilters
[rFilters
.size() - 1], xFormatter
);
886 //--------------------------------------------------------------------------------------------------
887 sal_Bool
OSingleSelectQueryComposer::setANDCriteria( OSQLParseNode
* pCondition
,
888 OSQLParseTreeIterator
& _rIterator
, ::std::vector
< PropertyValue
>& rFilter
, const Reference
< XNumberFormatter
> & xFormatter
) const
890 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setANDCriteria" );
892 if (SQL_ISRULE(pCondition
,boolean_primary
))
894 // this should not occur
895 DBG_ERROR("boolean_primary in And-Criteria");
898 // Das erste Element ist (wieder) eine AND-Verknuepfung
899 else if ( SQL_ISRULE(pCondition
,boolean_term
) && pCondition
->count() == 3 )
901 return setANDCriteria(pCondition
->getChild(0), _rIterator
, rFilter
, xFormatter
) &&
902 setANDCriteria(pCondition
->getChild(2), _rIterator
, rFilter
, xFormatter
);
904 else if (SQL_ISRULE(pCondition
, comparison_predicate
))
906 return setComparsionPredicate(pCondition
,_rIterator
,rFilter
,xFormatter
);
908 else if (SQL_ISRULE(pCondition
,like_predicate
) ||
909 SQL_ISRULE(pCondition
,test_for_null
) ||
910 SQL_ISRULE(pCondition
,in_predicate
) ||
911 SQL_ISRULE(pCondition
,all_or_any_predicate
) ||
912 SQL_ISRULE(pCondition
,between_predicate
))
914 if (SQL_ISRULE(pCondition
->getChild(0), column_ref
))
917 ::rtl::OUString aValue
;
918 ::rtl::OUString aColumnName
;
921 // pCondition->parseNodeToStr(aValue,m_xMetaData, xFormatter, m_aLocale,static_cast<sal_Char>(m_sDecimalSep.toChar()));
922 pCondition
->parseNodeToStr( aValue
, m_xConnection
, NULL
);
923 // pCondition->getChild(0)->parseNodeToStr(aColumnName,m_xMetaData, xFormatter, m_aLocale,static_cast<sal_Char>(m_sDecimalSep.toChar()));
924 pCondition
->getChild(0)->parseNodeToStr( aColumnName
, m_xConnection
, NULL
);
926 // don't display the column name
927 aValue
= aValue
.copy(aColumnName
.getLength());
928 aValue
= aValue
.trim();
930 aItem
.Name
= getColumnName(pCondition
->getChild(0),_rIterator
);
931 aItem
.Value
<<= aValue
;
932 aItem
.Handle
= 0; // just to know that this is not one the known ones
933 if (SQL_ISRULE(pCondition
,like_predicate
))
935 if (pCondition
->count() == 5)
936 aItem
.Handle
= SQLFilterOperator::NOT_LIKE
;
938 aItem
.Handle
= SQLFilterOperator::LIKE
;
940 else if (SQL_ISRULE(pCondition
,test_for_null
))
942 if (SQL_ISTOKEN(pCondition
->getChild(2),NOT
) )
943 aItem
.Handle
= SQLFilterOperator::NOT_SQLNULL
;
945 aItem
.Handle
= SQLFilterOperator::SQLNULL
;
947 else if (SQL_ISRULE(pCondition
,in_predicate
))
949 OSL_ENSURE( false, "OSingleSelectQueryComposer::setANDCriteria: in_predicate not implemented!" );
951 else if (SQL_ISRULE(pCondition
,all_or_any_predicate
))
953 OSL_ENSURE( false, "OSingleSelectQueryComposer::setANDCriteria: all_or_any_predicate not implemented!" );
955 else if (SQL_ISRULE(pCondition
,between_predicate
))
957 OSL_ENSURE( false, "OSingleSelectQueryComposer::setANDCriteria: between_predicate not implemented!" );
960 rFilter
.push_back(aItem
);
965 else if (SQL_ISRULE(pCondition
,existence_test
) ||
966 SQL_ISRULE(pCondition
,unique_test
))
968 // this couldn't be handled here, too complex
969 // as we need a field name
977 // -----------------------------------------------------------------------------
978 sal_Int32
OSingleSelectQueryComposer::getPredicateType(OSQLParseNode
* _pPredicate
) const
980 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getPredicateType" );
981 sal_Int32 nPredicate
= SQLFilterOperator::EQUAL
;
982 switch (_pPredicate
->getNodeType())
985 nPredicate
= SQLFilterOperator::EQUAL
;
987 case SQL_NODE_NOTEQUAL
:
988 nPredicate
= SQLFilterOperator::NOT_EQUAL
;
991 nPredicate
= SQLFilterOperator::LESS
;
993 case SQL_NODE_LESSEQ
:
994 nPredicate
= SQLFilterOperator::LESS_EQUAL
;
997 nPredicate
= SQLFilterOperator::GREATER
;
999 case SQL_NODE_GREATEQ
:
1000 nPredicate
= SQLFilterOperator::GREATER_EQUAL
;
1003 OSL_ENSURE(0,"Wrong NodeType!");
1007 //------------------------------------------------------------------------------
1008 sal_Bool
OSingleSelectQueryComposer::setComparsionPredicate(OSQLParseNode
* pCondition
, OSQLParseTreeIterator
& _rIterator
,
1009 ::std::vector
< PropertyValue
>& rFilter
, const Reference
< ::com::sun::star::util::XNumberFormatter
> & xFormatter
) const
1011 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setComparsionPredicate" );
1012 DBG_ASSERT(SQL_ISRULE(pCondition
, comparison_predicate
),"setComparsionPredicate: pCondition ist kein ComparsionPredicate");
1013 if (SQL_ISRULE(pCondition
->getChild(0), column_ref
) ||
1014 SQL_ISRULE(pCondition
->getChild(pCondition
->count()-1), column_ref
))
1016 PropertyValue aItem
;
1017 ::rtl::OUString aValue
;
1019 if (SQL_ISRULE(pCondition
->getChild(0), column_ref
))
1024 aItem
.Handle
= getPredicateType(pCondition
->getChild(i
));
1025 // don't display the equal
1026 if (pCondition
->getChild(i
)->getNodeType() == SQL_NODE_EQUAL
)
1030 for (;i
< pCondition
->count();i
++)
1031 pCondition
->getChild(i
)->parseNodeToPredicateStr(
1032 aValue
, m_xConnection
, xFormatter
, m_aLocale
, static_cast<sal_Char
>(m_sDecimalSep
.toChar() ) );
1034 else if (SQL_ISRULE(pCondition
->getChild(pCondition
->count()-1), column_ref
))
1036 nPos
= pCondition
->count()-1;
1038 sal_Int32 i
= pCondition
->count() - 2;
1039 switch (pCondition
->getChild(i
)->getNodeType())
1041 case SQL_NODE_EQUAL
:
1042 // don't display the equal
1044 aItem
.Handle
= SQLFilterOperator::EQUAL
;
1046 case SQL_NODE_NOTEQUAL
:
1048 aItem
.Handle
= SQLFilterOperator::NOT_EQUAL
;
1051 // take the opposite as we change the order
1053 aValue
= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(">="));
1054 aItem
.Handle
= SQLFilterOperator::GREATER_EQUAL
;
1056 case SQL_NODE_LESSEQ
:
1057 // take the opposite as we change the order
1059 aValue
= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(">"));
1060 aItem
.Handle
= SQLFilterOperator::GREATER
;
1062 case SQL_NODE_GREAT
:
1063 // take the opposite as we change the order
1065 aValue
= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("<="));
1066 aItem
.Handle
= SQLFilterOperator::LESS_EQUAL
;
1068 case SQL_NODE_GREATEQ
:
1069 // take the opposite as we change the order
1071 aValue
= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("<"));
1072 aItem
.Handle
= SQLFilterOperator::LESS
;
1080 pCondition
->getChild(i
)->parseNodeToPredicateStr(
1081 aValue
, m_xConnection
, xFormatter
, m_aLocale
, static_cast<sal_Char
>( m_sDecimalSep
.toChar() ) );
1086 aItem
.Name
= getColumnName(pCondition
->getChild(nPos
),_rIterator
);
1087 aItem
.Value
<<= aValue
;
1088 rFilter
.push_back(aItem
);
1090 else if (SQL_ISRULE(pCondition
->getChild(0), set_fct_spec
) ||
1091 SQL_ISRULE(pCondition
->getChild(0), general_set_fct
))
1093 PropertyValue aItem
;
1094 ::rtl::OUString aValue
;
1095 ::rtl::OUString aColumnName
;
1097 pCondition
->parseNodeToPredicateStr(aValue
, m_xConnection
, xFormatter
, m_aLocale
, static_cast<sal_Char
>( m_sDecimalSep
.toChar() ) );
1098 pCondition
->getChild(0)->parseNodeToPredicateStr( aColumnName
, m_xConnection
, xFormatter
, m_aLocale
, static_cast<sal_Char
>( m_sDecimalSep
.toChar() ) );
1100 // don't display the column name
1101 aValue
= aValue
.copy(aColumnName
.getLength());
1104 aItem
.Name
= UniString(getColumnName(pCondition
->getChild(0),_rIterator
));
1105 aItem
.Value
<<= aValue
;
1106 aItem
.Handle
= pCondition
->getNodeType();
1107 rFilter
.push_back(aItem
);
1109 else // kann sich nur um einen Expr. Ausdruck handeln
1111 PropertyValue aItem
;
1112 ::rtl::OUString aName
, aValue
;
1114 OSQLParseNode
*pLhs
= pCondition
->getChild(0);
1115 OSQLParseNode
*pRhs
= pCondition
->getChild(2);
1119 for (i
=0;i
< pLhs
->count();i
++)
1120 pCondition
->getChild(i
)->parseNodeToPredicateStr( aName
, m_xConnection
, xFormatter
, m_aLocale
, static_cast<sal_Char
>( m_sDecimalSep
.toChar() ) );
1123 aItem
.Handle
= pCondition
->getChild(1)->getNodeType();
1124 aValue
= pCondition
->getChild(1)->getTokenValue();
1125 for(i
=0;i
< pRhs
->count();i
++)
1126 pCondition
->getChild(i
)->parseNodeToPredicateStr(aValue
, m_xConnection
, xFormatter
, m_aLocale
, static_cast<sal_Char
>( m_sDecimalSep
.toChar() ) );
1129 aItem
.Value
<<= aValue
;
1130 rFilter
.push_back(aItem
);
1134 // functions for analysing SQL
1135 //--------------------------------------------------------------------------------------------------
1136 ::rtl::OUString
OSingleSelectQueryComposer::getColumnName( ::connectivity::OSQLParseNode
* pColumnRef
, OSQLParseTreeIterator
& _rIterator
) const
1138 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getColumnName" );
1139 ::rtl::OUString aTableRange
, aColumnName
;
1140 _rIterator
.getColumnRange(pColumnRef
,aColumnName
,aTableRange
);
1143 //------------------------------------------------------------------------------
1144 ::rtl::OUString SAL_CALL
OSingleSelectQueryComposer::getFilter( ) throw(RuntimeException
)
1146 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getFilter" );
1147 ::connectivity::checkDisposed(OSubComponent::rBHelper
.bDisposed
);
1148 ::osl::MutexGuard
aGuard( m_aMutex
);
1149 return getSQLPart(Where
,m_aAdditiveIterator
,sal_False
);
1151 // -------------------------------------------------------------------------
1152 ::rtl::OUString SAL_CALL
OSingleSelectQueryComposer::getOrder( ) throw(RuntimeException
)
1154 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getOrder" );
1155 ::connectivity::checkDisposed(OSubComponent::rBHelper
.bDisposed
);
1156 ::osl::MutexGuard
aGuard( m_aMutex
);
1157 return getSQLPart(Order
,m_aAdditiveIterator
,sal_False
);
1159 // -------------------------------------------------------------------------
1160 ::rtl::OUString SAL_CALL
OSingleSelectQueryComposer::getGroup( ) throw (RuntimeException
)
1162 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getGroup" );
1163 ::connectivity::checkDisposed(OSubComponent::rBHelper
.bDisposed
);
1164 ::osl::MutexGuard
aGuard( m_aMutex
);
1165 return getSQLPart(Group
,m_aAdditiveIterator
,sal_False
);
1167 // -----------------------------------------------------------------------------
1168 ::rtl::OUString
OSingleSelectQueryComposer::getHavingClause() throw (RuntimeException
)
1170 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getHavingClause" );
1171 ::connectivity::checkDisposed(OSubComponent::rBHelper
.bDisposed
);
1172 ::osl::MutexGuard
aGuard( m_aMutex
);
1173 return getSQLPart(Having
,m_aAdditiveIterator
,sal_False
);
1175 // -----------------------------------------------------------------------------
1176 ::rtl::OUString
OSingleSelectQueryComposer::getTableAlias(const Reference
< XPropertySet
>& column
) const
1178 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getTableAlias" );
1179 ::rtl::OUString sReturn
;
1180 if(m_pTables
&& m_pTables
->getCount() > 1)
1182 ::rtl::OUString aCatalog
,aSchema
,aTable
,aComposedName
,aColumnName
;
1183 column
->getPropertyValue(PROPERTY_CATALOGNAME
) >>= aCatalog
;
1184 column
->getPropertyValue(PROPERTY_SCHEMANAME
) >>= aSchema
;
1185 column
->getPropertyValue(PROPERTY_TABLENAME
) >>= aTable
;
1186 column
->getPropertyValue(PROPERTY_NAME
) >>= aColumnName
;
1188 Sequence
< ::rtl::OUString
> aNames(m_pTables
->getElementNames());
1189 const ::rtl::OUString
* pBegin
= aNames
.getConstArray();
1190 const ::rtl::OUString
* pEnd
= pBegin
+ aNames
.getLength();
1192 if(!aTable
.getLength())
1193 { // we don't found a table name, now we must search every table for this column
1194 for(;pBegin
!= pEnd
;++pBegin
)
1196 Reference
<XColumnsSupplier
> xColumnsSupp
;
1197 m_pTables
->getByName(*pBegin
) >>= xColumnsSupp
;
1199 if(xColumnsSupp
.is() && xColumnsSupp
->getColumns()->hasByName(aColumnName
))
1201 // Reference<XPropertySet> xTableProp(xColumnsSupp,UNO_QUERY);
1202 // xTableProp->getPropertyValue(PROPERTY_CATALOGNAME) >>= aCatalog;
1203 // xTableProp->getPropertyValue(PROPERTY_SCHEMANAME) >>= aSchema;
1204 // xTableProp->getPropertyValue(PROPERTY_NAME) >>= aTable;
1212 aComposedName
= ::dbtools::composeTableName( m_xMetaData
, aCatalog
, aSchema
, aTable
, sal_False
, ::dbtools::eInDataManipulation
);
1214 // first check if this is the table we want to or has it a tablealias
1216 if(!m_pTables
->hasByName(aComposedName
))
1218 ::comphelper::UStringMixLess
aTmp(m_aAdditiveIterator
.getTables().key_comp());
1219 ::comphelper::UStringMixEqual
aComp(static_cast< ::comphelper::UStringMixLess
*>(&aTmp
)->isCaseSensitive());
1220 for(;pBegin
!= pEnd
;++pBegin
)
1222 Reference
<XPropertySet
> xTableProp
;
1223 m_pTables
->getByName(*pBegin
) >>= xTableProp
;
1224 OSL_ENSURE(xTableProp
.is(),"Table isn't a propertyset!");
1227 ::rtl::OUString aCatalog2
,aSchema2
,aTable2
;
1228 xTableProp
->getPropertyValue(PROPERTY_CATALOGNAME
) >>= aCatalog2
;
1229 xTableProp
->getPropertyValue(PROPERTY_SCHEMANAME
) >>= aSchema2
;
1230 xTableProp
->getPropertyValue(PROPERTY_NAME
) >>= aTable2
;
1231 if(aComp(aCatalog
,aCatalog2
) && aComp(aSchema
,aSchema2
) && aComp(aTable
,aTable2
))
1233 aCatalog
= aCatalog2
;
1244 sReturn
= ::dbtools::composeTableName( m_xMetaData
, aCatalog
, aSchema
, aTable
, sal_True
, ::dbtools::eInDataManipulation
);
1245 sReturn
+= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("."));
1250 // -----------------------------------------------------------------------------
1251 Reference
< XIndexAccess
> SAL_CALL
OSingleSelectQueryComposer::getParameters( ) throw(RuntimeException
)
1253 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getParameters" );
1254 // now set the Parameters
1255 if ( !m_aCurrentColumns
[ParameterColumns
] )
1257 ::vos::ORef
< OSQLColumns
> aCols
= m_aSqlIterator
.getParameters();
1258 ::std::vector
< ::rtl::OUString
> aNames
;
1259 OSQLColumns::Vector::const_iterator aEnd
= aCols
->get().end();
1260 for(OSQLColumns::Vector::const_iterator aIter
= aCols
->get().begin(); aIter
!= aEnd
;++aIter
)
1261 aNames
.push_back(getString((*aIter
)->getPropertyValue(PROPERTY_NAME
)));
1262 m_aCurrentColumns
[ParameterColumns
] = new OPrivateColumns(aCols
,m_xMetaData
->supportsMixedCaseQuotedIdentifiers(),*this,m_aMutex
,aNames
,sal_True
);
1265 return m_aCurrentColumns
[ParameterColumns
];
1267 // -----------------------------------------------------------------------------
1268 void OSingleSelectQueryComposer::clearColumns( const EColumnType _eType
)
1270 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::clearColumns" );
1271 OPrivateColumns
* pColumns
= m_aCurrentColumns
[ _eType
];
1272 if ( pColumns
!= NULL
)
1274 pColumns
->disposing();
1275 m_aColumnsCollection
.push_back( pColumns
);
1276 m_aCurrentColumns
[ _eType
] = NULL
;
1279 // -----------------------------------------------------------------------------
1280 void OSingleSelectQueryComposer::clearCurrentCollections()
1282 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::clearCurrentCollections" );
1283 ::std::vector
<OPrivateColumns
*>::iterator aIter
= m_aCurrentColumns
.begin();
1284 ::std::vector
<OPrivateColumns
*>::iterator aEnd
= m_aCurrentColumns
.end();
1285 for (;aIter
!= aEnd
;++aIter
)
1289 (*aIter
)->disposing();
1290 m_aColumnsCollection
.push_back(*aIter
);
1297 m_pTables
->disposing();
1298 m_aTablesCollection
.push_back(m_pTables
);
1302 // -----------------------------------------------------------------------------
1303 Reference
< XIndexAccess
> OSingleSelectQueryComposer::setCurrentColumns( EColumnType _eType
,
1304 const ::vos::ORef
< OSQLColumns
>& _rCols
)
1306 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setCurrentColumns" );
1307 ::connectivity::checkDisposed(OSubComponent::rBHelper
.bDisposed
);
1309 ::osl::MutexGuard
aGuard( m_aMutex
);
1310 // now set the group columns
1311 if ( !m_aCurrentColumns
[_eType
] )
1313 ::std::vector
< ::rtl::OUString
> aNames
;
1314 OSQLColumns::Vector::const_iterator aEnd
= _rCols
->get().end();
1315 for(OSQLColumns::Vector::const_iterator aIter
= _rCols
->get().begin(); aIter
!= aEnd
;++aIter
)
1316 aNames
.push_back(getString((*aIter
)->getPropertyValue(PROPERTY_NAME
)));
1317 m_aCurrentColumns
[_eType
] = new OPrivateColumns(_rCols
,m_xMetaData
->supportsMixedCaseQuotedIdentifiers(),*this,m_aMutex
,aNames
,sal_True
);
1320 return m_aCurrentColumns
[_eType
];
1322 // -----------------------------------------------------------------------------
1323 Reference
< XIndexAccess
> SAL_CALL
OSingleSelectQueryComposer::getGroupColumns( ) throw(RuntimeException
)
1325 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getGroupColumns" );
1326 return setCurrentColumns( GroupByColumns
, m_aAdditiveIterator
.getGroupColumns() );
1328 // -------------------------------------------------------------------------
1329 Reference
< XIndexAccess
> SAL_CALL
OSingleSelectQueryComposer::getOrderColumns( ) throw(RuntimeException
)
1331 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getOrderColumns" );
1332 return setCurrentColumns( OrderColumns
, m_aAdditiveIterator
.getOrderColumns() );
1334 // -----------------------------------------------------------------------------
1335 ::rtl::OUString SAL_CALL
OSingleSelectQueryComposer::getQueryWithSubstitution( ) throw (SQLException
, RuntimeException
)
1337 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getQueryWithSubstitution" );
1338 ::osl::MutexGuard
aGuard( m_aMutex
);
1339 ::connectivity::checkDisposed(OSubComponent::rBHelper
.bDisposed
);
1341 ::rtl::OUString
sSqlStatement( getQuery() );
1343 const OSQLParseNode
* pStatementNode
= m_aSqlIterator
.getParseTree();
1344 if ( pStatementNode
)
1346 SQLException aError
;
1347 if ( !pStatementNode
->parseNodeToExecutableStatement( sSqlStatement
, m_xConnection
, m_aSqlParser
, &aError
) )
1348 throw SQLException( aError
);
1351 return sSqlStatement
;
1353 // -----------------------------------------------------------------------------
1354 ::rtl::OUString
OSingleSelectQueryComposer::getStatementPart( TGetParseNode
& _aGetFunctor
, OSQLParseTreeIterator
& _rIterator
)
1356 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getStatementPart" );
1357 ::rtl::OUString sResult
;
1359 const OSQLParseNode
* pNode
= _aGetFunctor( &_rIterator
);
1361 pNode
->parseNodeToStr( sResult
, m_xConnection
);
1365 // -----------------------------------------------------------------------------
1368 ::rtl::OUString
lcl_getCondition(const Sequence
< Sequence
< PropertyValue
> >& filter
)
1370 ::rtl::OUStringBuffer sRet
;
1371 const Sequence
< PropertyValue
>* pOrIter
= filter
.getConstArray();
1372 const Sequence
< PropertyValue
>* pOrEnd
= pOrIter
+ filter
.getLength();
1373 while ( pOrIter
!= pOrEnd
)
1375 if ( pOrIter
->getLength() )
1377 sRet
.append(L_BRACKET
);
1378 const PropertyValue
* pAndIter
= pOrIter
->getConstArray();
1379 const PropertyValue
* pAndEnd
= pAndIter
+ pOrIter
->getLength();
1380 while ( pAndIter
!= pAndEnd
)
1382 sRet
.append(pAndIter
->Name
);
1383 ::rtl::OUString sValue
;
1384 pAndIter
->Value
>>= sValue
;
1385 switch( pAndIter
->Handle
)
1387 case SQLFilterOperator::EQUAL
:
1388 sRet
.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" = ")));
1389 sRet
.append(sValue
);
1391 case SQLFilterOperator::NOT_EQUAL
:
1392 sRet
.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" <> ")));
1393 sRet
.append(sValue
);
1395 case SQLFilterOperator::LESS
:
1396 sRet
.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" < ")));
1397 sRet
.append(sValue
);
1399 case SQLFilterOperator::GREATER
:
1400 sRet
.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" > ")));
1401 sRet
.append(sValue
);
1403 case SQLFilterOperator::LESS_EQUAL
:
1404 sRet
.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" <= ")));
1405 sRet
.append(sValue
);
1407 case SQLFilterOperator::GREATER_EQUAL
:
1408 sRet
.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" >= ")));
1409 sRet
.append(sValue
);
1411 case SQLFilterOperator::LIKE
:
1412 sRet
.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" LIKE ")));
1413 sRet
.append(sValue
);
1415 case SQLFilterOperator::NOT_LIKE
:
1416 sRet
.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" NOT LIKE ")));
1417 sRet
.append(sValue
);
1419 case SQLFilterOperator::SQLNULL
:
1420 sRet
.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" IS NULL")) );
1422 case SQLFilterOperator::NOT_SQLNULL
:
1423 sRet
.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" IS NOT NULL")) );
1426 throw IllegalArgumentException();
1429 if ( pAndIter
!= pAndEnd
)
1430 sRet
.append(STR_AND
);
1432 sRet
.append(R_BRACKET
);
1435 if ( pOrIter
!= pOrEnd
&& sRet
.getLength() )
1436 sRet
.append(STR_OR
);
1438 return sRet
.makeStringAndClear();
1441 // -----------------------------------------------------------------------------
1442 void SAL_CALL
OSingleSelectQueryComposer::setStructuredFilter( const Sequence
< Sequence
< PropertyValue
> >& filter
) throw (SQLException
, ::com::sun::star::lang::IllegalArgumentException
, RuntimeException
)
1444 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setStructuredFilter" );
1445 setFilter(lcl_getCondition(filter
));
1447 // -----------------------------------------------------------------------------
1448 void SAL_CALL
OSingleSelectQueryComposer::setStructuredHavingClause( const Sequence
< Sequence
< PropertyValue
> >& filter
) throw (SQLException
, RuntimeException
)
1450 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setStructuredHavingClause" );
1451 setHavingClause(lcl_getCondition(filter
));
1453 // -----------------------------------------------------------------------------
1454 void OSingleSelectQueryComposer::setConditionByColumn( const Reference
< XPropertySet
>& column
, sal_Bool andCriteria
,::std::mem_fun1_t
<bool,OSingleSelectQueryComposer
,::rtl::OUString
>& _aSetFunctor
)
1456 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setConditionByColumn" );
1457 ::connectivity::checkDisposed(OSubComponent::rBHelper
.bDisposed
);
1460 || !column
->getPropertySetInfo()->hasPropertyByName(PROPERTY_VALUE
)
1461 || !column
->getPropertySetInfo()->hasPropertyByName(PROPERTY_NAME
)
1462 || !column
->getPropertySetInfo()->hasPropertyByName(PROPERTY_TYPE
))
1463 throw SQLException(DBACORE_RESSTRING(RID_STR_COLUMN_NOT_VALID
),*this,SQLSTATE_GENERAL
,1000,Any() );
1465 sal_Int32 nType
= 0;
1466 column
->getPropertyValue(PROPERTY_TYPE
) >>= nType
;
1467 sal_Int32 nSearchable
= dbtools::getSearchColumnFlag(m_xConnection
,nType
);
1468 if(nSearchable
== ColumnSearch::NONE
)
1469 throw SQLException(DBACORE_RESSTRING(RID_STR_COLUMN_NOT_SEARCHABLE
),*this,SQLSTATE_GENERAL
,1000,Any() );
1471 ::osl::MutexGuard
aGuard( m_aMutex
);
1473 ::rtl::OUString aName
;
1474 column
->getPropertyValue(PROPERTY_NAME
) >>= aName
;
1477 column
->getPropertyValue(PROPERTY_VALUE
) >>= aValue
;
1479 ::rtl::OUStringBuffer aSQL
;
1480 const ::rtl::OUString aQuote
= m_xMetaData
->getIdentifierQuoteString();
1483 if ( m_aCurrentColumns
[SelectColumns
] && m_aCurrentColumns
[SelectColumns
]->hasByName(aName
) )
1485 Reference
<XPropertySet
> xColumn
;
1486 m_aCurrentColumns
[SelectColumns
]->getByName(aName
) >>= xColumn
;
1487 OSL_ENSURE(xColumn
->getPropertySetInfo()->hasPropertyByName(PROPERTY_REALNAME
),"Property REALNAME not available!");
1488 OSL_ENSURE(xColumn
->getPropertySetInfo()->hasPropertyByName(PROPERTY_TABLENAME
),"Property TABLENAME not available!");
1489 OSL_ENSURE(xColumn
->getPropertySetInfo()->hasPropertyByName(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AggregateFunction"))),"Property AggregateFunctionnot available!");
1491 ::rtl::OUString sRealName
,sTableName
;
1492 xColumn
->getPropertyValue(PROPERTY_REALNAME
) >>= sRealName
;
1493 xColumn
->getPropertyValue(PROPERTY_TABLENAME
) >>= sTableName
;
1494 if(sTableName
.indexOf('.',0) != -1)
1496 ::rtl::OUString aCatlog
,aSchema
,aTable
;
1497 ::dbtools::qualifiedNameComponents(m_xMetaData
,sTableName
,aCatlog
,aSchema
,aTable
,::dbtools::eInDataManipulation
);
1498 sTableName
= ::dbtools::composeTableName( m_xMetaData
, aCatlog
, aSchema
, aTable
, sal_True
, ::dbtools::eInDataManipulation
);
1501 sTableName
= ::dbtools::quoteName(aQuote
,sTableName
);
1503 if ( !::comphelper::getBOOL(xColumn
->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Function")))) )
1506 aSQL
.appendAscii( "." );
1507 aSQL
.append( ::dbtools::quoteName( aQuote
, sRealName
) );
1515 aSQL
= getTableAlias( column
);
1516 aSQL
.append( ::dbtools::quoteName( aQuote
, aName
) );
1519 if ( aValue
.hasValue() )
1521 if( !m_xTypeConverter
.is() )
1522 m_aContext
.createComponent( "com.sun.star.script.Converter", m_xTypeConverter
);
1523 OSL_ENSURE(m_xTypeConverter
.is(),"NO typeconverter!");
1527 case DataType::VARCHAR
:
1528 case DataType::CHAR
:
1529 case DataType::LONGVARCHAR
:
1530 aSQL
.append( STR_LIKE
);
1531 aSQL
.append( DBTypeConversion::toSQLString( nType
, aValue
, sal_True
, m_xTypeConverter
) );
1533 case DataType::VARBINARY
:
1534 case DataType::BINARY
:
1535 case DataType::LONGVARBINARY
:
1537 Sequence
<sal_Int8
> aSeq
;
1540 if(nSearchable
== ColumnSearch::CHAR
)
1542 aSQL
.append( STR_LIKE
);
1543 aSQL
.appendAscii( "\'" );
1546 aSQL
.append( STR_EQUAL
);
1547 aSQL
.appendAscii( "0x" );
1548 const sal_Int8
* pBegin
= aSeq
.getConstArray();
1549 const sal_Int8
* pEnd
= pBegin
+ aSeq
.getLength();
1550 for(;pBegin
!= pEnd
;++pBegin
)
1552 aSQL
.append( (sal_Int32
)*pBegin
, 16 ).getStr();
1554 if(nSearchable
== ColumnSearch::CHAR
)
1555 aSQL
.appendAscii( "\'" );
1558 throw SQLException(DBACORE_RESSTRING(RID_STR_NOT_SEQUENCE_INT8
),*this,SQLSTATE_GENERAL
,1000,Any() );
1562 case DataType::BOOLEAN
:
1564 sal_Bool bValue
= sal_False
;
1565 m_xTypeConverter
->convertToSimpleType(aValue
, TypeClass_BOOLEAN
) >>= bValue
;
1567 ::rtl::OUString sColumnExp
= aSQL
.makeStringAndClear();
1568 getBoleanComparisonPredicate( sColumnExp
, bValue
, m_nBoolCompareMode
, aSQL
);
1572 aSQL
.append( STR_EQUAL
);
1573 aSQL
.append( DBTypeConversion::toSQLString( nType
, aValue
, sal_True
, m_xTypeConverter
) );
1578 aSQL
.appendAscii( " IS NULL" ) ;
1581 // select ohne where und order by aufbauen
1582 ::rtl::OUString sFilter
= getFilter();
1584 if ( sFilter
.getLength() && aSQL
.getLength() )
1586 ::rtl::OUString
sTemp(L_BRACKET
);
1589 sTemp
+= andCriteria
? STR_AND
: STR_OR
;
1592 sFilter
+= aSQL
.makeStringAndClear();
1594 // add the filter and the sort order
1595 _aSetFunctor(this,sFilter
);
1597 // -----------------------------------------------------------------------------
1598 Sequence
< Sequence
< PropertyValue
> > OSingleSelectQueryComposer::getStructuredCondition( TGetParseNode
& _aGetFunctor
)
1600 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getStructuredCondition" );
1601 ::connectivity::checkDisposed(OSubComponent::rBHelper
.bDisposed
);
1603 MutexGuard
aGuard(m_aMutex
);
1605 Sequence
< Sequence
< PropertyValue
> > aFilterSeq
;
1606 ::rtl::OUString sFilter
= getStatementPart( _aGetFunctor
, m_aAdditiveIterator
);
1608 if ( sFilter
.getLength() != 0 )
1610 ::rtl::OUString
aSql(m_aPureSelectSQL
);
1611 // build a temporary parse node
1612 const OSQLParseNode
* pTempNode
= m_aAdditiveIterator
.getParseTree();
1617 ::rtl::OUString aErrorMsg
;
1618 ::std::auto_ptr
<OSQLParseNode
> pSqlParseNode( m_aSqlParser
.parseTree(aErrorMsg
,aSql
));
1619 if ( pSqlParseNode
.get() )
1621 m_aAdditiveIterator
.setParseTree(pSqlParseNode
.get());
1622 // normalize the filter
1623 OSQLParseNode
* pWhereNode
= const_cast<OSQLParseNode
*>(m_aAdditiveIterator
.getWhereTree());
1625 OSQLParseNode
* pCondition
= pWhereNode
->getChild(1);
1626 #if OSL_DEBUG_LEVEL > 0
1627 ::rtl::OUString sCondition
;
1628 pCondition
->parseNodeToStr( sCondition
, m_xConnection
);
1630 OSQLParseNode::negateSearchCondition(pCondition
);
1632 pCondition
= pWhereNode
->getChild(1);
1633 #if OSL_DEBUG_LEVEL > 0
1634 sCondition
= ::rtl::OUString();
1635 pCondition
->parseNodeToStr( sCondition
, m_xConnection
);
1637 OSQLParseNode::disjunctiveNormalForm(pCondition
);
1639 pCondition
= pWhereNode
->getChild(1);
1640 #if OSL_DEBUG_LEVEL > 0
1641 sCondition
= ::rtl::OUString();
1642 pCondition
->parseNodeToStr( sCondition
, m_xConnection
);
1644 OSQLParseNode::absorptions(pCondition
);
1646 pCondition
= pWhereNode
->getChild(1);
1647 #if OSL_DEBUG_LEVEL > 0
1648 sCondition
= ::rtl::OUString();
1649 pCondition
->parseNodeToStr( sCondition
, m_xConnection
);
1653 ::std::vector
< ::std::vector
< PropertyValue
> > aFilters
;
1654 Reference
< XNumberFormatter
> xFormatter
;
1655 m_aContext
.createComponent( "com.sun.star.util.NumberFormatter", xFormatter
);
1656 xFormatter
->attachNumberFormatsSupplier( m_xNumberFormatsSupplier
);
1658 if (setORCriteria(pCondition
, m_aAdditiveIterator
, aFilters
, xFormatter
))
1660 aFilterSeq
.realloc(aFilters
.size());
1661 Sequence
<PropertyValue
>* pFilters
= aFilterSeq
.getArray();
1662 ::std::vector
< ::std::vector
< PropertyValue
> >::const_iterator aEnd
= aFilters
.end();
1663 ::std::vector
< ::std::vector
< PropertyValue
> >::const_iterator i
= aFilters
.begin();
1664 for ( ; i
!= aEnd
; ++i
)
1666 const ::std::vector
< PropertyValue
>& rProperties
= *i
;
1667 pFilters
->realloc(rProperties
.size());
1668 PropertyValue
* pFilter
= pFilters
->getArray();
1669 ::std::vector
< PropertyValue
>::const_iterator j
= rProperties
.begin();
1670 ::std::vector
< PropertyValue
>::const_iterator aEnd2
= rProperties
.end();
1671 for ( ; j
!= aEnd2
; ++j
)
1681 m_aAdditiveIterator
.setParseTree(pTempNode
);
1686 // -----------------------------------------------------------------------------
1687 ::rtl::OUString
OSingleSelectQueryComposer::getKeyword( SQLPart _ePart
) const
1689 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getKeyword" );
1690 ::rtl::OUString sKeyword
;
1694 OSL_ENSURE( 0, "OSingleSelectQueryComposer::getKeyWord: Invalid enum value!" );
1695 // no break, fallback to WHERE
1697 sKeyword
= STR_WHERE
;
1700 sKeyword
= STR_GROUP_BY
;
1703 sKeyword
= STR_HAVING
;
1706 sKeyword
= STR_ORDER_BY
;
1712 // -----------------------------------------------------------------------------
1713 ::rtl::OUString
OSingleSelectQueryComposer::getSQLPart( SQLPart _ePart
, OSQLParseTreeIterator
& _rIterator
, sal_Bool _bWithKeyword
)
1715 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getSQLPart" );
1716 TGetParseNode
F_tmp(&OSQLParseTreeIterator::getSimpleWhereTree
);
1717 ::rtl::OUString
sKeyword( getKeyword( _ePart
) );
1721 F_tmp
= TGetParseNode(&OSQLParseTreeIterator::getSimpleWhereTree
);
1724 F_tmp
= TGetParseNode (&OSQLParseTreeIterator::getSimpleGroupByTree
);
1727 F_tmp
= TGetParseNode(&OSQLParseTreeIterator::getSimpleHavingTree
);
1730 F_tmp
= TGetParseNode(&OSQLParseTreeIterator::getSimpleOrderTree
);
1733 OSL_ENSURE(0,"Invalid enum value!");
1736 ::rtl::OUString sRet
= getStatementPart( F_tmp
, _rIterator
);
1737 if ( _bWithKeyword
&& sRet
.getLength() )
1738 sRet
= sKeyword
+ sRet
;
1741 // -----------------------------------------------------------------------------