1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_dbaccess.hxx"
31 #include "composertools.hxx"
32 #include "core_resource.hrc"
33 #include "core_resource.hxx"
34 #include "dbastrings.hrc"
35 #include "HelperCollections.hxx"
36 #include "SingleSelectQueryComposer.hxx"
37 #include "sdbcoretools.hxx"
39 /** === begin UNO includes === **/
40 #include <com/sun/star/beans/PropertyAttribute.hpp>
41 #include <com/sun/star/container/XChild.hpp>
42 #include <com/sun/star/i18n/XLocaleData.hpp>
43 #include <com/sun/star/lang/DisposedException.hpp>
44 #include <com/sun/star/sdb/BooleanComparisonMode.hpp>
45 #include <com/sun/star/sdb/SQLFilterOperator.hpp>
46 #include <com/sun/star/sdb/XQueriesSupplier.hpp>
47 #include <com/sun/star/sdb/CommandType.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/sdbc/XParameters.hpp>
53 #include <com/sun/star/uno/XAggregation.hpp>
54 #include <com/sun/star/util/XNumberFormatter.hpp>
55 /** === end UNO includes === **/
57 #include <comphelper/processfactory.hxx>
58 #include <comphelper/sequence.hxx>
59 #include <comphelper/types.hxx>
60 #include <cppuhelper/typeprovider.hxx>
61 #include <rtl/logfile.hxx>
62 #include <unotools/syslocale.hxx>
63 #include <tools/debug.hxx>
64 #include <tools/diagnose_ex.h>
65 #include <unotools/configmgr.hxx>
66 #include <unotools/sharedunocomponent.hxx>
70 using namespace ::dbaccess
;
71 using namespace ::dbtools
;
72 using namespace ::comphelper
;
73 using namespace ::connectivity
;
74 using namespace ::com::sun::star::uno
;
75 using namespace ::com::sun::star::beans
;
76 using namespace ::com::sun::star::sdbc
;
77 using namespace ::com::sun::star::sdb
;
78 using namespace ::com::sun::star::sdbcx
;
79 using namespace ::com::sun::star::container
;
80 using namespace ::com::sun::star::i18n
;
81 using namespace ::com::sun::star::lang
;
82 using namespace ::com::sun::star::script
;
83 using namespace ::com::sun::star::util
;
84 using namespace ::cppu
;
85 using namespace ::osl
;
86 using namespace ::utl
;
89 namespace BooleanComparisonMode
= ::com::sun::star::sdb::BooleanComparisonMode
;
92 #define STR_SELECT ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SELECT "))
93 #define STR_FROM ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" FROM "))
94 #define STR_WHERE ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" WHERE "))
95 #define STR_GROUP_BY ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" GROUP BY "))
96 #define STR_HAVING ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" HAVING "))
97 #define STR_ORDER_BY ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" ORDER BY "))
98 #define STR_AND ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" AND "))
99 #define STR_OR ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" OR "))
100 #define STR_LIKE ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" LIKE "))
101 #define STR_EQUAL ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" = "))
102 #define L_BRACKET ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("("))
103 #define R_BRACKET ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(")"))
104 #define COMMA ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(","))
106 // -------------------------------------------------------------------------
109 // .....................................................................
110 /** parses the given statement, using the given parser, returns a parse node representing
113 If the statement cannot be parsed, an error is thrown.
115 const OSQLParseNode
* parseStatement_throwError( OSQLParser
& _rParser
, const ::rtl::OUString
& _rStatement
, const Reference
< XInterface
>& _rxContext
)
117 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "frank.schoenheit@sun.com", "SingleSelectQueryComposer.cxx::parseStatement_throwError" );
118 ::rtl::OUString aErrorMsg
;
119 const OSQLParseNode
* pNewSqlParseNode
= _rParser
.parseTree( aErrorMsg
, _rStatement
);
120 if ( !pNewSqlParseNode
)
122 ::rtl::OUString
sSQLStateGeneralError( getStandardSQLState( SQL_GENERAL_ERROR
) );
123 SQLException
aError2( aErrorMsg
, _rxContext
, sSQLStateGeneralError
, 1000, Any() );
124 SQLException
aError1( _rStatement
, _rxContext
, sSQLStateGeneralError
, 1000, makeAny( aError2
) );
125 throw SQLException(_rParser
.getContext().getErrorMessage(OParseContext::ERROR_GENERAL
),_rxContext
,sSQLStateGeneralError
,1000,makeAny(aError1
));
127 return pNewSqlParseNode
;
130 // .....................................................................
131 /** checks whether the given parse node describes a valid single select statement, throws
134 void checkForSingleSelect_throwError( const OSQLParseNode
* pStatementNode
, OSQLParseTreeIterator
& _rIterator
,
135 const Reference
< XInterface
>& _rxContext
, const ::rtl::OUString
& _rOriginatingCommand
)
137 const OSQLParseNode
* pOldNode
= _rIterator
.getParseTree();
139 // determine the statement type
140 _rIterator
.setParseTree( pStatementNode
);
141 _rIterator
.traverseAll();
142 bool bIsSingleSelect
= ( _rIterator
.getStatementType() == SQL_STATEMENT_SELECT
);
144 // throw the error, if necessary
145 if ( !bIsSingleSelect
|| SQL_ISRULE( pStatementNode
, union_statement
) ) // #i4229# OJ
147 // restore the old node before throwing the exception
148 _rIterator
.setParseTree( pOldNode
);
149 // and now really ...
150 SQLException
aError1( _rOriginatingCommand
, _rxContext
, getStandardSQLState( SQL_GENERAL_ERROR
), 1000, Any() );
151 throw SQLException( DBACORE_RESSTRING( RID_STR_ONLY_QUERY
), _rxContext
,
152 getStandardSQLState( SQL_GENERAL_ERROR
), 1000, makeAny( aError1
) );
158 // .....................................................................
159 /** combines parseStatement_throwError and checkForSingleSelect_throwError
161 void parseAndCheck_throwError( OSQLParser
& _rParser
, const ::rtl::OUString
& _rStatement
,
162 OSQLParseTreeIterator
& _rIterator
, const Reference
< XInterface
>& _rxContext
)
164 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "frank.schoenheit@sun.com", "SingleSelectQueryComposer.cxx::parseAndCheck_throwError" );
165 const OSQLParseNode
* pNode
= parseStatement_throwError( _rParser
, _rStatement
, _rxContext
);
166 checkForSingleSelect_throwError( pNode
, _rIterator
, _rxContext
, _rStatement
);
169 // .....................................................................
170 /** transforms a parse node describing a complete statement into a pure select
171 statement, without any filter/order/groupby/having clauses
173 ::rtl::OUString
getPureSelectStatement( const OSQLParseNode
* _pRootNode
, Reference
< XConnection
> _rxConnection
)
175 ::rtl::OUString sSQL
= STR_SELECT
;
176 _pRootNode
->getChild(1)->parseNodeToStr( sSQL
, _rxConnection
);
177 _pRootNode
->getChild(2)->parseNodeToStr( sSQL
, _rxConnection
);
179 _pRootNode
->getChild(3)->getChild(0)->getChild(1)->parseNodeToStr( sSQL
, _rxConnection
);
183 /** resets an SQL iterator, including deletion of the parse tree, and disposal if desired
185 void resetIterator( OSQLParseTreeIterator
& _rIterator
, bool _bDispose
)
187 const OSQLParseNode
* pSqlParseNode
= _rIterator
.getParseTree();
188 _rIterator
.setParseTree(NULL
);
189 delete pSqlParseNode
;
191 _rIterator
.dispose();
193 void lcl_addFilterCriteria_throw(sal_Int32 i_nFilterOperator
,const ::rtl::OUString
& i_sValue
,::rtl::OUStringBuffer
& o_sRet
)
195 switch( i_nFilterOperator
)
197 case SQLFilterOperator::EQUAL
:
198 o_sRet
.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" = ")));
199 o_sRet
.append(i_sValue
);
201 case SQLFilterOperator::NOT_EQUAL
:
202 o_sRet
.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" <> ")));
203 o_sRet
.append(i_sValue
);
205 case SQLFilterOperator::LESS
:
206 o_sRet
.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" < ")));
207 o_sRet
.append(i_sValue
);
209 case SQLFilterOperator::GREATER
:
210 o_sRet
.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" > ")));
211 o_sRet
.append(i_sValue
);
213 case SQLFilterOperator::LESS_EQUAL
:
214 o_sRet
.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" <= ")));
215 o_sRet
.append(i_sValue
);
217 case SQLFilterOperator::GREATER_EQUAL
:
218 o_sRet
.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" >= ")));
219 o_sRet
.append(i_sValue
);
221 case SQLFilterOperator::LIKE
:
222 o_sRet
.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" LIKE ")));
223 o_sRet
.append(i_sValue
);
225 case SQLFilterOperator::NOT_LIKE
:
226 o_sRet
.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" NOT LIKE ")));
227 o_sRet
.append(i_sValue
);
229 case SQLFilterOperator::SQLNULL
:
230 o_sRet
.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" IS NULL")) );
232 case SQLFilterOperator::NOT_SQLNULL
:
233 o_sRet
.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" IS NOT NULL")) );
236 throw SQLException();
242 DBG_NAME(OSingleSelectQueryComposer
)
243 // -------------------------------------------------------------------------
244 OSingleSelectQueryComposer::OSingleSelectQueryComposer(const Reference
< XNameAccess
>& _rxTables
,
245 const Reference
< XConnection
>& _xConnection
,
246 const ::comphelper::ComponentContext
& _rContext
)
247 :OSubComponent(m_aMutex
,_xConnection
)
248 ,OPropertyContainer(m_aBHelper
)
249 ,m_aSqlParser( _rContext
.getLegacyServiceFactory() )
250 ,m_aSqlIterator( _xConnection
, _rxTables
, m_aSqlParser
, NULL
)
251 ,m_aAdditiveIterator( _xConnection
, _rxTables
, m_aSqlParser
, NULL
)
252 ,m_aElementaryParts( (size_t)SQLPartCount
)
253 ,m_xConnection(_xConnection
)
254 ,m_xMetaData(_xConnection
->getMetaData())
255 ,m_xConnectionTables( _rxTables
)
256 ,m_aContext( _rContext
)
258 ,m_nBoolCompareMode( BooleanComparisonMode::EQUAL_INTEGER
)
259 ,m_nCommandType(CommandType::COMMAND
)
261 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::OSingleSelectQueryComposer" );
262 DBG_CTOR(OSingleSelectQueryComposer
,NULL
);
264 if ( !m_aContext
.is() || !m_xConnection
.is() || !m_xConnectionTables
.is() )
265 throw IllegalArgumentException();
267 registerProperty(PROPERTY_ORIGINAL
,PROPERTY_ID_ORIGINAL
,PropertyAttribute::BOUND
|PropertyAttribute::READONLY
,&m_sOrignal
,::getCppuType(&m_sOrignal
));
269 m_aCurrentColumns
.resize(4);
271 m_aLocale
= SvtSysLocale().GetLocaleData().getLocale();
272 m_xNumberFormatsSupplier
= dbtools::getNumberFormats( m_xConnection
, sal_True
, m_aContext
.getLegacyServiceFactory() );
273 Reference
< XLocaleData
> xLocaleData
;
274 m_aContext
.createComponent( "com.sun.star.i18n.LocaleData", xLocaleData
);
275 LocaleDataItem aData
= xLocaleData
->getLocaleItem(m_aLocale
);
276 m_sDecimalSep
= aData
.decimalSeparator
;
277 OSL_ENSURE(m_sDecimalSep
.getLength() == 1,"OSingleSelectQueryComposer::OSingleSelectQueryComposer decimal separator is not 1 length");
281 Reference
<XInterface
> xDs
= dbaccess::getDataSource(_xConnection
);
282 if ( dbtools::getDataSourceSetting(xDs
,static_cast <rtl::OUString
> (PROPERTY_BOOLEANCOMPARISONMODE
),aValue
) )
284 OSL_VERIFY( aValue
>>= m_nBoolCompareMode
);
286 Reference
< XQueriesSupplier
> xQueriesAccess(m_xConnection
, UNO_QUERY
);
287 if (xQueriesAccess
.is())
288 m_xConnectionQueries
= xQueriesAccess
->getQueries();
294 // -------------------------------------------------------------------------
295 OSingleSelectQueryComposer::~OSingleSelectQueryComposer()
297 DBG_DTOR(OSingleSelectQueryComposer
,NULL
);
298 ::std::vector
<OPrivateColumns
*>::iterator aColIter
= m_aColumnsCollection
.begin();
299 ::std::vector
<OPrivateColumns
*>::iterator aEnd
= m_aColumnsCollection
.end();
300 for(;aColIter
!= aEnd
;++aColIter
)
303 ::std::vector
<OPrivateTables
*>::iterator aTabIter
= m_aTablesCollection
.begin();
304 ::std::vector
<OPrivateTables
*>::iterator aTabEnd
= m_aTablesCollection
.end();
305 for(;aTabIter
!= aTabEnd
;++aTabIter
)
308 // -------------------------------------------------------------------------
310 void SAL_CALL
OSingleSelectQueryComposer::disposing(void)
312 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::disposing" );
313 OSubComponent::disposing();
315 MutexGuard
aGuard(m_aMutex
);
317 resetIterator( m_aSqlIterator
, true );
318 resetIterator( m_aAdditiveIterator
, true );
320 m_xConnectionTables
= NULL
;
321 m_xConnection
= NULL
;
323 clearCurrentCollections();
325 IMPLEMENT_FORWARD_XINTERFACE3(OSingleSelectQueryComposer
,OSubComponent
,OSingleSelectQueryComposer_BASE
,OPropertyContainer
)
326 IMPLEMENT_SERVICE_INFO1(OSingleSelectQueryComposer
,"org.openoffice.comp.dba.OSingleSelectQueryComposer",SERVICE_NAME_SINGLESELECTQUERYCOMPOSER
)
327 IMPLEMENT_TYPEPROVIDER3(OSingleSelectQueryComposer
,OSubComponent
,OSingleSelectQueryComposer_BASE
,OPropertyContainer
)
328 IMPLEMENT_PROPERTYCONTAINER_DEFAULTS(OSingleSelectQueryComposer
)
330 // -------------------------------------------------------------------------
331 // com::sun::star::lang::XUnoTunnel
332 sal_Int64 SAL_CALL
OSingleSelectQueryComposer::getSomething( const Sequence
< sal_Int8
>& rId
) throw(RuntimeException
)
334 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getSomething" );
335 if (rId
.getLength() == 16 && 0 == rtl_compareMemory(getImplementationId().getConstArray(), rId
.getConstArray(), 16 ) )
336 return reinterpret_cast<sal_Int64
>(this);
341 // -------------------------------------------------------------------------
342 // XSingleSelectQueryAnalyzer
343 ::rtl::OUString SAL_CALL
OSingleSelectQueryComposer::getQuery( ) throw(RuntimeException
)
345 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getQuery" );
346 ::connectivity::checkDisposed(OSubComponent::rBHelper
.bDisposed
);
347 ::osl::MutexGuard
aGuard( m_aMutex
);
349 TGetParseNode
F_tmp(&OSQLParseTreeIterator::getParseTree
);
350 return getStatementPart(F_tmp
,m_aSqlIterator
);
353 // -------------------------------------------------------------------------
354 void SAL_CALL
OSingleSelectQueryComposer::setQuery( const ::rtl::OUString
& command
) throw(SQLException
, RuntimeException
)
356 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "frank.schoenheit@sun.com", "OSingleSelectQueryComposer::setQuery" );
357 ::connectivity::checkDisposed(OSubComponent::rBHelper
.bDisposed
);
359 ::osl::MutexGuard
aGuard( m_aMutex
);
360 m_nCommandType
= CommandType::COMMAND
;
361 // first clear the tables and columns
362 clearCurrentCollections();
363 // now set the new one
364 setQuery_Impl(command
);
365 m_sOrignal
= command
;
367 // reset the additive iterator to the same statement
368 parseAndCheck_throwError( m_aSqlParser
, m_sOrignal
, m_aAdditiveIterator
, *this );
370 // we have no "elementary" parts anymore (means filter/groupby/having/order clauses)
371 for ( SQLPart eLoopParts
= Where
; eLoopParts
!= SQLPartCount
; incSQLPart( eLoopParts
) )
372 m_aElementaryParts
[ eLoopParts
] = ::rtl::OUString();
374 // -------------------------------------------------------------------------
375 void SAL_CALL
OSingleSelectQueryComposer::setCommand( const ::rtl::OUString
& Command
,sal_Int32 _nCommandType
) throw(SQLException
, RuntimeException
)
377 ::rtl::OUStringBuffer sSQL
;
378 switch(_nCommandType
)
380 case CommandType::COMMAND
:
381 setElementaryQuery(Command
);
383 case CommandType::TABLE
:
384 if ( m_xConnectionTables
->hasByName(Command
) )
386 sSQL
.appendAscii("SELECT * FROM ");
387 Reference
< XPropertySet
> xTable
;
390 m_xConnectionTables
->getByName( Command
) >>= xTable
;
392 catch(const WrappedTargetException
& e
)
395 if ( e
.TargetException
>>= e2
)
400 DBG_UNHANDLED_EXCEPTION();
403 sSQL
.append(dbtools::composeTableNameForSelect(m_xConnection
,xTable
));
407 String
sMessage( DBACORE_RESSTRING( RID_STR_TABLE_DOES_NOT_EXIST
) );
408 sMessage
.SearchAndReplaceAscii( "$table$", Command
);
409 throwGenericSQLException(sMessage
,*this);
412 case CommandType::QUERY
:
413 if ( m_xConnectionQueries
->hasByName(Command
) )
416 Reference
<XPropertySet
> xQuery(m_xConnectionQueries
->getByName(Command
),UNO_QUERY
);
417 ::rtl::OUString sCommand
;
418 xQuery
->getPropertyValue(PROPERTY_COMMAND
) >>= sCommand
;
419 sSQL
.append(sCommand
);
423 String
sMessage( DBACORE_RESSTRING( RID_STR_QUERY_DOES_NOT_EXIST
) );
424 sMessage
.SearchAndReplaceAscii( "$table$", Command
);
425 throwGenericSQLException(sMessage
,*this);
432 ::connectivity::checkDisposed(OSubComponent::rBHelper
.bDisposed
);
434 ::osl::MutexGuard
aGuard( m_aMutex
);
435 m_nCommandType
= _nCommandType
;
436 m_sCommand
= Command
;
437 // first clear the tables and columns
438 clearCurrentCollections();
439 // now set the new one
440 ::rtl::OUString sCommand
= sSQL
.makeStringAndClear();
441 setElementaryQuery(sCommand
);
442 m_sOrignal
= sCommand
;
444 // reset the additive iterator to the same statement
445 parseAndCheck_throwError( m_aSqlParser, m_sOrignal, m_aAdditiveIterator, *this );
447 // we have no "elementary" parts anymore (means filter/groupby/having/order clauses)
448 for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
449 m_aElementaryParts[ eLoopParts ] = ::rtl::OUString();
452 // -----------------------------------------------------------------------------
453 void OSingleSelectQueryComposer::setQuery_Impl( const ::rtl::OUString
& command
)
455 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "frank.schoenheit@sun.com", "OSingleSelectQueryComposer::setQuery_Impl" );
457 parseAndCheck_throwError( m_aSqlParser
, command
, m_aSqlIterator
, *this );
459 // strip it from all clauses, to have the pure SELECT statement
460 m_aPureSelectSQL
= getPureSelectStatement( m_aSqlIterator
.getParseTree(), m_xConnection
);
462 // update columns and tables
463 // why? Shouldn't this be done on request only?
464 // otherwise nothing is working anymore :-)
468 // -----------------------------------------------------------------------------
469 Sequence
< Sequence
< PropertyValue
> > SAL_CALL
OSingleSelectQueryComposer::getStructuredHavingClause( ) throw (RuntimeException
)
471 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getStructuredHavingClause" );
472 TGetParseNode
F_tmp(&OSQLParseTreeIterator::getSimpleHavingTree
);
473 return getStructuredCondition(F_tmp
);
475 // -------------------------------------------------------------------------
476 Sequence
< Sequence
< PropertyValue
> > SAL_CALL
OSingleSelectQueryComposer::getStructuredFilter( ) throw(RuntimeException
)
478 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getStructuredFilter" );
479 TGetParseNode
F_tmp(&OSQLParseTreeIterator::getSimpleWhereTree
);
480 return getStructuredCondition(F_tmp
);
482 // -----------------------------------------------------------------------------
483 void SAL_CALL
OSingleSelectQueryComposer::appendHavingClauseByColumn( const Reference
< XPropertySet
>& column
, sal_Bool andCriteria
,sal_Int32 filterOperator
) throw (SQLException
, RuntimeException
)
485 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::appendHavingClauseByColumn" );
486 ::std::mem_fun1_t
<bool,OSingleSelectQueryComposer
,::rtl::OUString
> F_tmp(&OSingleSelectQueryComposer::implSetHavingClause
);
487 setConditionByColumn(column
,andCriteria
,F_tmp
,filterOperator
);
489 // -----------------------------------------------------------------------------
490 void SAL_CALL
OSingleSelectQueryComposer::appendFilterByColumn( const Reference
< XPropertySet
>& column
, sal_Bool andCriteria
,sal_Int32 filterOperator
) throw(SQLException
, RuntimeException
)
492 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::appendFilterByColumn" );
493 ::std::mem_fun1_t
<bool,OSingleSelectQueryComposer
,::rtl::OUString
> F_tmp(&OSingleSelectQueryComposer::implSetFilter
);
494 setConditionByColumn(column
,andCriteria
,F_tmp
,filterOperator
);
496 // -----------------------------------------------------------------------------
497 ::rtl::OUString
OSingleSelectQueryComposer::impl_getColumnName_throw(const Reference
< XPropertySet
>& column
)
499 ::connectivity::checkDisposed(OSubComponent::rBHelper
.bDisposed
);
503 || !m_aCurrentColumns
[SelectColumns
]
504 || !column
->getPropertySetInfo()->hasPropertyByName(PROPERTY_NAME
)
507 String
sError(DBACORE_RESSTRING(RID_STR_COLUMN_UNKNOWN_PROP
));
508 sError
.SearchAndReplaceAscii("%value", ::rtl::OUString(PROPERTY_NAME
));
509 SQLException
aErr(sError
,*this,SQLSTATE_GENERAL
,1000,Any() );
510 throw SQLException(DBACORE_RESSTRING(RID_STR_COLUMN_NOT_VALID
),*this,SQLSTATE_GENERAL
,1000,makeAny(aErr
) );
513 ::rtl::OUString aName
,aNewName
;
514 column
->getPropertyValue(PROPERTY_NAME
) >>= aName
;
516 if ( !m_xMetaData
->supportsOrderByUnrelated() && m_aCurrentColumns
[SelectColumns
] && !m_aCurrentColumns
[SelectColumns
]->hasByName(aName
))
518 String
sError(DBACORE_RESSTRING(RID_STR_COLUMN_MUST_VISIBLE
));
519 sError
.SearchAndReplaceAscii("%name", aName
);
520 throw SQLException(sError
,*this,SQLSTATE_GENERAL
,1000,Any() );
524 // select ohne where und order by aufbauen
525 ::rtl::OUString aQuote
= m_xMetaData
->getIdentifierQuoteString();
526 if ( m_aCurrentColumns
[SelectColumns
]->hasByName(aName
) )
528 Reference
<XPropertySet
> xColumn
;
529 m_aCurrentColumns
[SelectColumns
]->getByName(aName
) >>= xColumn
;
530 OSL_ENSURE(xColumn
->getPropertySetInfo()->hasPropertyByName(PROPERTY_REALNAME
),"Property REALNAME not available!");
531 OSL_ENSURE(xColumn
->getPropertySetInfo()->hasPropertyByName(PROPERTY_TABLENAME
),"Property TABLENAME not available!");
532 OSL_ENSURE(xColumn
->getPropertySetInfo()->hasPropertyByName(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Function"))),"Property FUNCTION not available!");
534 ::rtl::OUString sRealName
,sTableName
;
535 xColumn
->getPropertyValue(PROPERTY_REALNAME
) >>= sRealName
;
536 xColumn
->getPropertyValue(PROPERTY_TABLENAME
) >>= sTableName
;
537 sal_Bool bFunction
= sal_False
;
538 xColumn
->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Function"))) >>= bFunction
;
539 if ( sRealName
== aName
)
545 if(sTableName
.indexOf('.',0) != -1)
547 ::rtl::OUString aCatlog
,aSchema
,aTable
;
548 ::dbtools::qualifiedNameComponents(m_xMetaData
,sTableName
,aCatlog
,aSchema
,aTable
,::dbtools::eInDataManipulation
);
549 sTableName
= ::dbtools::composeTableName( m_xMetaData
, aCatlog
, aSchema
, aTable
, sal_True
, ::dbtools::eInDataManipulation
);
552 sTableName
= ::dbtools::quoteName(aQuote
,sTableName
);
554 aNewName
= sTableName
;
555 aNewName
+= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("."));
556 aNewName
+= ::dbtools::quoteName(aQuote
,sRealName
);
560 aNewName
= ::dbtools::quoteName(aQuote
,aName
);
563 aNewName
= getTableAlias(column
) + ::dbtools::quoteName(aQuote
,aName
);
566 // -------------------------------------------------------------------------
567 void SAL_CALL
OSingleSelectQueryComposer::appendOrderByColumn( const Reference
< XPropertySet
>& column
, sal_Bool ascending
) throw(SQLException
, RuntimeException
)
569 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::appendOrderByColumn" );
570 ::osl::MutexGuard
aGuard( m_aMutex
);
571 ::rtl::OUString
sColumnName( impl_getColumnName_throw(column
) );
572 ::rtl::OUString sOrder
= getOrder();
573 if ( (sOrder
.getLength() != 0) && sColumnName
.getLength() )
575 sOrder
+= sColumnName
;
576 if ( !ascending
&& sColumnName
.getLength() )
577 sOrder
+= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" DESC "));
582 // -------------------------------------------------------------------------
583 void SAL_CALL
OSingleSelectQueryComposer::appendGroupByColumn( const Reference
< XPropertySet
>& column
) throw(SQLException
, RuntimeException
)
585 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::appendGroupByColumn" );
586 ::osl::MutexGuard
aGuard( m_aMutex
);
587 ::rtl::OUString
sColumnName( impl_getColumnName_throw(column
) );
588 OrderCreator aComposer
;
589 aComposer
.append( getGroup() );
590 aComposer
.append( sColumnName
);
591 setGroup( aComposer
.getComposedAndClear() );
593 // -------------------------------------------------------------------------
594 ::rtl::OUString
OSingleSelectQueryComposer::composeStatementFromParts( const ::std::vector
< ::rtl::OUString
>& _rParts
)
596 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::composeStatementFromParts" );
597 DBG_ASSERT( _rParts
.size() == (size_t)SQLPartCount
, "OSingleSelectQueryComposer::composeStatementFromParts: invalid parts array!" );
599 ::rtl::OUStringBuffer
aSql( m_aPureSelectSQL
);
600 for ( SQLPart eLoopParts
= Where
; eLoopParts
!= SQLPartCount
; incSQLPart( eLoopParts
) )
601 if ( _rParts
[ eLoopParts
].getLength() )
603 aSql
.append( getKeyword( eLoopParts
) );
604 aSql
.append( _rParts
[ eLoopParts
] );
607 return aSql
.makeStringAndClear();
610 // -------------------------------------------------------------------------
611 ::rtl::OUString SAL_CALL
OSingleSelectQueryComposer::getElementaryQuery() throw (::com::sun::star::uno::RuntimeException
)
613 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getElementaryQuery" );
614 return composeStatementFromParts( m_aElementaryParts
);
617 // -------------------------------------------------------------------------
618 void SAL_CALL
OSingleSelectQueryComposer::setElementaryQuery( const ::rtl::OUString
& _rElementary
) throw (::com::sun::star::sdbc::SQLException
, ::com::sun::star::uno::RuntimeException
)
620 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "frank.schoenheit@sun.com", "OSingleSelectQueryComposer::setElementaryQuery" );
621 ::connectivity::checkDisposed(OSubComponent::rBHelper
.bDisposed
);
622 ::osl::MutexGuard
aGuard( m_aMutex
);
624 // remember the 4 current "additive" clauses
625 ::std::vector
< ::rtl::OUString
> aAdditiveClauses( SQLPartCount
);
626 for ( SQLPart eLoopParts
= Where
; eLoopParts
!= SQLPartCount
; incSQLPart( eLoopParts
) )
627 aAdditiveClauses
[ eLoopParts
] = getSQLPart( eLoopParts
, m_aAdditiveIterator
, sal_False
);
629 // clear the tables and columns
630 clearCurrentCollections();
631 // set and parse the new query
632 setQuery_Impl( _rElementary
);
634 // get the 4 elementary parts of the statement
635 for ( SQLPart eLoopParts
= Where
; eLoopParts
!= SQLPartCount
; incSQLPart( eLoopParts
) )
636 m_aElementaryParts
[ eLoopParts
] = getSQLPart( eLoopParts
, m_aSqlIterator
, sal_False
);
638 // reset the the AdditiveIterator: m_aPureSelectSQL may have changed
641 parseAndCheck_throwError( m_aSqlParser
, composeStatementFromParts( aAdditiveClauses
), m_aAdditiveIterator
, *this );
643 catch( const Exception
& e
)
646 DBG_ERROR( "OSingleSelectQueryComposer::setElementaryQuery: there should be no error anymore for the additive statement!" );
647 // every part of the additive statement should have passed other tests already, and should not
648 // be able to cause any errors ... me thinks
652 // -------------------------------------------------------------------------
655 ::rtl::OUString
getComposedClause( const ::rtl::OUString _rElementaryClause
, const ::rtl::OUString _rAdditionalClause
,
656 TokenComposer
& _rComposer
, const ::rtl::OUString _rKeyword
)
659 _rComposer
.append( _rElementaryClause
);
660 _rComposer
.append( _rAdditionalClause
);
661 ::rtl::OUString sComposed
= _rComposer
.getComposedAndClear();
662 if ( sComposed
.getLength() )
663 sComposed
= _rKeyword
+ sComposed
;
668 // -------------------------------------------------------------------------
669 void OSingleSelectQueryComposer::setSingleAdditiveClause( SQLPart _ePart
, const ::rtl::OUString
& _rClause
)
671 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setSingleAdditiveClause" );
672 ::connectivity::checkDisposed(OSubComponent::rBHelper
.bDisposed
);
673 ::osl::MutexGuard
aGuard( m_aMutex
);
675 // if nothing is changed, do nothing
676 if ( getSQLPart( _ePart
, m_aAdditiveIterator
, sal_False
) == _rClause
)
679 // collect the 4 single parts as they're currently set
680 ::std::vector
< ::rtl::OUString
> aClauses
;
681 aClauses
.reserve( (size_t)SQLPartCount
);
682 for ( SQLPart eLoopParts
= Where
; eLoopParts
!= SQLPartCount
; incSQLPart( eLoopParts
) )
683 aClauses
.push_back( getSQLPart( eLoopParts
, m_aSqlIterator
, sal_True
) );
685 // overwrite the one part in question here
686 ::std::auto_ptr
< TokenComposer
> pComposer
;
687 if ( ( _ePart
== Where
) || ( _ePart
== Having
) )
688 pComposer
.reset( new FilterCreator
);
690 pComposer
.reset( new OrderCreator
);
691 aClauses
[ _ePart
] = getComposedClause( m_aElementaryParts
[ _ePart
], _rClause
,
692 *pComposer
, getKeyword( _ePart
) );
694 // construct the complete statement
695 ::rtl::OUStringBuffer
aSql(m_aPureSelectSQL
);
696 for ( SQLPart eLoopParts
= Where
; eLoopParts
!= SQLPartCount
; incSQLPart( eLoopParts
) )
697 aSql
.append(aClauses
[ eLoopParts
]);
700 setQuery_Impl(aSql
.makeStringAndClear());
702 // clear column collections which (might) have changed
703 clearColumns( ParameterColumns
);
704 if ( _ePart
== Order
)
705 clearColumns( OrderColumns
);
706 if ( _ePart
== Group
)
707 clearColumns( GroupByColumns
);
709 // also, since the "additive filter" change, we need to rebuild our "additive" statement
710 aSql
= m_aPureSelectSQL
;
711 // again, first get all the old additive parts
712 for ( SQLPart eLoopParts
= Where
; eLoopParts
!= SQLPartCount
; incSQLPart( eLoopParts
) )
713 aClauses
[ eLoopParts
] = getSQLPart( eLoopParts
, m_aAdditiveIterator
, sal_True
);
714 // then overwrite the one in question
715 aClauses
[ _ePart
] = getComposedClause( ::rtl::OUString(), _rClause
, *pComposer
, getKeyword( _ePart
) );
716 // and parse it, so that m_aAdditiveIterator is up to date
717 for ( SQLPart eLoopParts
= Where
; eLoopParts
!= SQLPartCount
; incSQLPart( eLoopParts
) )
718 aSql
.append(aClauses
[ eLoopParts
]);
721 parseAndCheck_throwError( m_aSqlParser
, aSql
.makeStringAndClear(), m_aAdditiveIterator
, *this );
723 catch( const Exception
& e
)
726 DBG_ERROR( "OSingleSelectQueryComposer::setSingleAdditiveClause: there should be no error anymore for the additive statement!" );
727 // every part of the additive statement should have passed other tests already, and should not
728 // be able to cause any errors ... me thinks
732 // -------------------------------------------------------------------------
733 void SAL_CALL
OSingleSelectQueryComposer::setFilter( const ::rtl::OUString
& filter
) throw(SQLException
, RuntimeException
)
735 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setFilter" );
736 setSingleAdditiveClause( Where
, filter
);
739 // -------------------------------------------------------------------------
740 void SAL_CALL
OSingleSelectQueryComposer::setOrder( const ::rtl::OUString
& order
) throw(SQLException
, RuntimeException
)
742 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setOrder" );
743 setSingleAdditiveClause( Order
, order
);
745 // -----------------------------------------------------------------------------
746 void SAL_CALL
OSingleSelectQueryComposer::setGroup( const ::rtl::OUString
& group
) throw (SQLException
, RuntimeException
)
748 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setGroup" );
749 setSingleAdditiveClause( Group
, group
);
751 // -------------------------------------------------------------------------
752 void SAL_CALL
OSingleSelectQueryComposer::setHavingClause( const ::rtl::OUString
& filter
) throw(SQLException
, RuntimeException
)
754 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setHavingClause" );
755 setSingleAdditiveClause( Having
, filter
);
758 // -------------------------------------------------------------------------
760 Reference
< XNameAccess
> SAL_CALL
OSingleSelectQueryComposer::getTables( ) throw(RuntimeException
)
762 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getTables" );
763 ::connectivity::checkDisposed(OSubComponent::rBHelper
.bDisposed
);
765 ::osl::MutexGuard
aGuard( m_aMutex
);
768 const OSQLTables
& aTables
= m_aSqlIterator
.getTables();
769 ::std::vector
< ::rtl::OUString
> aNames
;
770 OSQLTables::const_iterator aEnd
= aTables
.end();
771 for(OSQLTables::const_iterator aIter
= aTables
.begin(); aIter
!= aEnd
;++aIter
)
772 aNames
.push_back(aIter
->first
);
774 m_pTables
= new OPrivateTables(aTables
,m_xMetaData
->supportsMixedCaseQuotedIdentifiers(),*this,m_aMutex
,aNames
);
779 // -------------------------------------------------------------------------
781 Reference
< XNameAccess
> SAL_CALL
OSingleSelectQueryComposer::getColumns( ) throw(RuntimeException
)
783 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getColumns" );
784 ::connectivity::checkDisposed(OSubComponent::rBHelper
.bDisposed
);
785 ::osl::MutexGuard
aGuard( m_aMutex
);
786 if ( !!m_aCurrentColumns
[SelectColumns
] )
787 return m_aCurrentColumns
[SelectColumns
];
789 ::std::vector
< ::rtl::OUString
> aNames
;
790 ::vos::ORef
< OSQLColumns
> aSelectColumns
;
791 sal_Bool bCase
= sal_True
;
792 Reference
< XNameAccess
> xQueryColumns
;
793 if ( m_nCommandType
== CommandType::QUERY
)
795 Reference
<XColumnsSupplier
> xSup(m_xConnectionQueries
->getByName(m_sCommand
),UNO_QUERY
);
797 xQueryColumns
= xSup
->getColumns();
804 SharedUNOComponent
< XStatement
, DisposableComponent
> xStatement
;
805 SharedUNOComponent
< XPreparedStatement
, DisposableComponent
> xPreparedStatement
;
807 bCase
= m_xMetaData
->supportsMixedCaseQuotedIdentifiers();
808 aSelectColumns
= m_aSqlIterator
.getSelectColumns();
810 ::rtl::OUStringBuffer aSQL
;
811 aSQL
.append( m_aPureSelectSQL
);
812 aSQL
.append( STR_WHERE
);
814 // preserve the original WHERE clause
815 // #i102234# / 2009-06-02 / frank.schoenheit@sun.com
816 ::rtl::OUString sOriginalWhereClause
= getSQLPart( Where
, m_aSqlIterator
, sal_False
);
817 if ( sOriginalWhereClause
.getLength() )
819 aSQL
.appendAscii( " ( 0 = 1 ) AND ( " );
820 aSQL
.append( sOriginalWhereClause
);
821 aSQL
.appendAscii( " ) " );
825 aSQL
.appendAscii( " ( 0 = 1 ) " );
828 ::rtl::OUString sGroupBy
= getSQLPart( Group
, m_aSqlIterator
, sal_True
);
829 if ( sGroupBy
.getLength() )
830 aSQL
.append( sGroupBy
);
832 ::rtl::OUString
sSQL( aSQL
.makeStringAndClear() );
833 // normalize the statement so that it doesn't contain any application-level features anymore
834 ::rtl::OUString sError
;
835 const ::std::auto_ptr
< OSQLParseNode
> pStatementTree( m_aSqlParser
.parseTree( sError
, sSQL
, false ) );
836 DBG_ASSERT( pStatementTree
.get(), "OSingleSelectQueryComposer::getColumns: could not parse the column retrieval statement!" );
837 if ( pStatementTree
.get() )
838 if ( !pStatementTree
->parseNodeToExecutableStatement( sSQL
, m_xConnection
, m_aSqlParser
, NULL
) )
841 Reference
< XResultSetMetaData
> xResultSetMeta
;
842 Reference
< XResultSetMetaDataSupplier
> xResMetaDataSup
;
845 xPreparedStatement
.set( m_xConnection
->prepareStatement( sSQL
), UNO_QUERY_THROW
);
846 xResMetaDataSup
.set( xPreparedStatement
, UNO_QUERY_THROW
);
847 xResultSetMeta
.set( xResMetaDataSup
->getMetaData(), UNO_QUERY_THROW
);
849 catch( const Exception
& ) { }
853 if ( !xResultSetMeta
.is() )
855 xStatement
.reset( Reference
< XStatement
>( m_xConnection
->createStatement(), UNO_QUERY_THROW
) );
856 Reference
< XPropertySet
> xStatementProps( xStatement
, UNO_QUERY_THROW
);
857 try { xStatementProps
->setPropertyValue( PROPERTY_ESCAPE_PROCESSING
, makeAny( sal_False
) ); }
858 catch ( const Exception
& ) { DBG_UNHANDLED_EXCEPTION(); }
859 xResMetaDataSup
.set( xStatement
->executeQuery( sSQL
), UNO_QUERY_THROW
);
860 xResultSetMeta
.set( xResMetaDataSup
->getMetaData(), UNO_QUERY_THROW
);
863 catch( const Exception
& )
865 //@see issue http://qa.openoffice.org/issues/show_bug.cgi?id=110111
866 // access returns a different order of column names when executing select * from
867 // and asking the columns from the metadata.
868 Reference
< XParameters
> xParameters( xPreparedStatement
, UNO_QUERY_THROW
);
869 Reference
< XIndexAccess
> xPara
= getParameters();
870 for(sal_Int32 i
= 1;i
<= xPara
->getCount();++i
)
871 xParameters
->setNull(i
,DataType::VARCHAR
);
872 xResMetaDataSup
.set(xPreparedStatement
->executeQuery(), UNO_QUERY_THROW
);
873 xResultSetMeta
.set( xResMetaDataSup
->getMetaData(), UNO_QUERY_THROW
);
876 if ( aSelectColumns
->get().empty() )
878 // This is a valid case. If we can syntactically parse the query, but not semantically
879 // (e.g. because it is based on a table we do not know), then there will be no SelectColumns
880 aSelectColumns
= ::connectivity::parse::OParseColumn::createColumnsForResultSet( xResultSetMeta
, m_xMetaData
,xQueryColumns
);
884 const ::comphelper::UStringMixEqual
aCaseCompare( bCase
);
885 const ::comphelper::TStringMixEqualFunctor
aCaseCompareFunctor( bCase
);
886 typedef ::std::set
< size_t > SizeTSet
;
887 SizeTSet aUsedSelectColumns
;
888 ::connectivity::parse::OParseColumn::StringMap aColumnNames
;
890 sal_Int32 nCount
= xResultSetMeta
->getColumnCount();
891 OSL_ENSURE( (size_t) nCount
== aSelectColumns
->get().size(), "OSingleSelectQueryComposer::getColumns: inconsistent column counts, this might result in wrong columns!" );
892 for(sal_Int32 i
=1;i
<=nCount
;++i
)
894 ::rtl::OUString sColumnName
= xResultSetMeta
->getColumnName(i
);
895 ::rtl::OUString sColumnLabel
;
896 if ( xQueryColumns
.is() && xQueryColumns
->hasByName(sColumnName
) )
898 Reference
<XPropertySet
> xQueryColumn(xQueryColumns
->getByName(sColumnName
),UNO_QUERY_THROW
);
899 xQueryColumn
->getPropertyValue(PROPERTY_LABEL
) >>= sColumnLabel
;
902 sColumnLabel
= xResultSetMeta
->getColumnLabel(i
);
903 sal_Bool bFound
= sal_False
;
904 OSQLColumns::Vector::const_iterator aFind
= ::connectivity::find(aSelectColumns
->get().begin(),aSelectColumns
->get().end(),sColumnLabel
,aCaseCompare
);
905 size_t nFoundSelectColumnPos
= aFind
- aSelectColumns
->get().begin();
906 if ( aFind
!= aSelectColumns
->get().end() )
908 if ( aUsedSelectColumns
.find( nFoundSelectColumnPos
) != aUsedSelectColumns
.end() )
909 { // we found a column name which exists twice
910 // so we start after the first found
913 aFind
= ::connectivity::findRealName(++aFind
,aSelectColumns
->get().end(),sColumnName
,aCaseCompare
);
914 nFoundSelectColumnPos
= aFind
- aSelectColumns
->get().begin();
916 while ( ( aUsedSelectColumns
.find( nFoundSelectColumnPos
) != aUsedSelectColumns
.end() )
917 && ( aFind
!= aSelectColumns
->get().end() )
920 if ( aFind
!= aSelectColumns
->get().end() )
922 (*aFind
)->getPropertyValue(PROPERTY_NAME
) >>= sColumnName
;
923 aUsedSelectColumns
.insert( nFoundSelectColumnPos
);
924 aNames
.push_back(sColumnName
);
932 OSQLColumns::Vector::const_iterator aRealFind
= ::connectivity::findRealName(
933 aSelectColumns
->get().begin(), aSelectColumns
->get().end(), sColumnName
, aCaseCompare
);
935 if ( i
> static_cast< sal_Int32
>( aSelectColumns
->get().size() ) )
937 aSelectColumns
->get().push_back(
938 ::connectivity::parse::OParseColumn::createColumnForResultSet( xResultSetMeta
, m_xMetaData
, i
,aColumnNames
)
940 OSL_ENSURE( aSelectColumns
->get().size() == (size_t)i
, "OSingleSelectQueryComposer::getColumns: inconsistency!" );
942 else if ( aRealFind
== aSelectColumns
->get().end() )
944 // we can now only look if we found it under the realname propertery
945 // here we have to make the assumption that the position is correct
946 OSQLColumns::Vector::iterator aFind2
= aSelectColumns
->get().begin() + i
-1;
947 Reference
<XPropertySet
> xProp(*aFind2
,UNO_QUERY
);
948 if ( !xProp
.is() || !xProp
->getPropertySetInfo()->hasPropertyByName( PROPERTY_REALNAME
) )
951 ::connectivity::parse::OParseColumn
* pColumn
= new ::connectivity::parse::OParseColumn(xProp
,bCase
);
952 pColumn
->setFunction(::comphelper::getBOOL(xProp
->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Function")))));
953 pColumn
->setAggregateFunction(::comphelper::getBOOL(xProp
->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AggregateFunction")))));
955 ::rtl::OUString sRealName
;
956 xProp
->getPropertyValue(PROPERTY_REALNAME
) >>= sRealName
;
957 ::std::vector
< ::rtl::OUString
>::iterator aFindName
;
958 if ( !sColumnName
.getLength() )
959 xProp
->getPropertyValue(PROPERTY_NAME
) >>= sColumnName
;
962 aFindName
= ::std::find_if(aNames
.begin(),aNames
.end(),::std::bind2nd(aCaseCompareFunctor
,sColumnName
));
964 while ( aFindName
!= aNames
.end() )
966 sColumnName
+= ::rtl::OUString::valueOf(++j
);
967 aFindName
= ::std::find_if(aNames
.begin(),aNames
.end(),::std::bind2nd(aCaseCompareFunctor
,sColumnName
));
970 pColumn
->setName(sColumnName
);
971 pColumn
->setRealName(sRealName
);
972 pColumn
->setTableName(::comphelper::getString(xProp
->getPropertyValue(PROPERTY_TABLENAME
)));
974 (aSelectColumns
->get())[i
-1] = pColumn
;
979 aUsedSelectColumns
.insert( (size_t)(i
- 1) );
980 aNames
.push_back( sColumnName
);
983 catch(const Exception
&)
989 if ( aNames
.empty() )
990 m_aCurrentColumns
[ SelectColumns
] = OPrivateColumns::createWithIntrinsicNames( aSelectColumns
, bCase
, *this, m_aMutex
);
992 m_aCurrentColumns
[ SelectColumns
] = new OPrivateColumns( aSelectColumns
, bCase
, *this, m_aMutex
, aNames
);
994 return m_aCurrentColumns
[SelectColumns
];
996 // -------------------------------------------------------------------------
997 sal_Bool
OSingleSelectQueryComposer::setORCriteria(OSQLParseNode
* pCondition
, OSQLParseTreeIterator
& _rIterator
,
998 ::std::vector
< ::std::vector
< PropertyValue
> >& rFilters
, const Reference
< ::com::sun::star::util::XNumberFormatter
> & xFormatter
) const
1000 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setORCriteria" );
1001 // Runde Klammern um den Ausdruck
1002 if (pCondition
->count() == 3 &&
1003 SQL_ISPUNCTUATION(pCondition
->getChild(0),"(") &&
1004 SQL_ISPUNCTUATION(pCondition
->getChild(2),")"))
1006 return setORCriteria(pCondition
->getChild(1), _rIterator
, rFilters
, xFormatter
);
1008 // oder Verknuepfung
1009 // a searchcondition can only look like this: search_condition SQL_TOKEN_OR boolean_term
1010 else if (SQL_ISRULE(pCondition
,search_condition
))
1012 sal_Bool bResult
= sal_True
;
1013 for (int i
= 0; bResult
&& i
< 3; i
+=2)
1015 // Ist das erste Element wieder eine OR-Verknuepfung?
1016 // Dann rekursiv absteigen ...
1017 //if (!i && SQL_ISRULE(pCondition->getChild(i),search_condition))
1018 if (SQL_ISRULE(pCondition
->getChild(i
),search_condition
))
1019 bResult
= setORCriteria(pCondition
->getChild(i
), _rIterator
, rFilters
, xFormatter
);
1022 rFilters
.push_back( ::std::vector
< PropertyValue
>());
1023 bResult
= setANDCriteria(pCondition
->getChild(i
), _rIterator
, rFilters
[rFilters
.size() - 1], xFormatter
);
1030 rFilters
.push_back(::std::vector
< PropertyValue
>());
1031 return setANDCriteria(pCondition
, _rIterator
, rFilters
[rFilters
.size() - 1], xFormatter
);
1035 //--------------------------------------------------------------------------------------------------
1036 sal_Bool
OSingleSelectQueryComposer::setANDCriteria( OSQLParseNode
* pCondition
,
1037 OSQLParseTreeIterator
& _rIterator
, ::std::vector
< PropertyValue
>& rFilter
, const Reference
< XNumberFormatter
> & xFormatter
) const
1039 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setANDCriteria" );
1041 if (SQL_ISRULE(pCondition
,boolean_primary
))
1043 // this should not occur
1044 DBG_ERROR("boolean_primary in And-Criteria");
1047 // Das erste Element ist (wieder) eine AND-Verknuepfung
1048 else if ( SQL_ISRULE(pCondition
,boolean_term
) && pCondition
->count() == 3 )
1050 return setANDCriteria(pCondition
->getChild(0), _rIterator
, rFilter
, xFormatter
) &&
1051 setANDCriteria(pCondition
->getChild(2), _rIterator
, rFilter
, xFormatter
);
1053 else if (SQL_ISRULE(pCondition
, comparison_predicate
))
1055 return setComparsionPredicate(pCondition
,_rIterator
,rFilter
,xFormatter
);
1057 else if (SQL_ISRULE(pCondition
,like_predicate
) ||
1058 SQL_ISRULE(pCondition
,test_for_null
) ||
1059 SQL_ISRULE(pCondition
,in_predicate
) ||
1060 SQL_ISRULE(pCondition
,all_or_any_predicate
) ||
1061 SQL_ISRULE(pCondition
,between_predicate
))
1063 if (SQL_ISRULE(pCondition
->getChild(0), column_ref
))
1065 PropertyValue aItem
;
1066 ::rtl::OUString aValue
;
1067 ::rtl::OUString aColumnName
;
1070 // pCondition->parseNodeToStr(aValue,m_xMetaData, xFormatter, m_aLocale,static_cast<sal_Char>(m_sDecimalSep.toChar()));
1071 pCondition
->parseNodeToStr( aValue
, m_xConnection
, NULL
);
1072 // pCondition->getChild(0)->parseNodeToStr(aColumnName,m_xMetaData, xFormatter, m_aLocale,static_cast<sal_Char>(m_sDecimalSep.toChar()));
1073 pCondition
->getChild(0)->parseNodeToStr( aColumnName
, m_xConnection
, NULL
);
1075 // don't display the column name
1076 aValue
= aValue
.copy(aColumnName
.getLength());
1077 aValue
= aValue
.trim();
1079 aItem
.Name
= getColumnName(pCondition
->getChild(0),_rIterator
);
1080 aItem
.Value
<<= aValue
;
1081 aItem
.Handle
= 0; // just to know that this is not one the known ones
1082 if ( SQL_ISRULE(pCondition
,like_predicate
) )
1084 if ( SQL_ISTOKEN(pCondition
->getChild(1)->getChild(0),NOT
) )
1085 aItem
.Handle
= SQLFilterOperator::NOT_LIKE
;
1087 aItem
.Handle
= SQLFilterOperator::LIKE
;
1089 else if (SQL_ISRULE(pCondition
,test_for_null
))
1091 if (SQL_ISTOKEN(pCondition
->getChild(1)->getChild(1),NOT
) )
1092 aItem
.Handle
= SQLFilterOperator::NOT_SQLNULL
;
1094 aItem
.Handle
= SQLFilterOperator::SQLNULL
;
1096 else if (SQL_ISRULE(pCondition
,in_predicate
))
1098 OSL_ENSURE( false, "OSingleSelectQueryComposer::setANDCriteria: in_predicate not implemented!" );
1100 else if (SQL_ISRULE(pCondition
,all_or_any_predicate
))
1102 OSL_ENSURE( false, "OSingleSelectQueryComposer::setANDCriteria: all_or_any_predicate not implemented!" );
1104 else if (SQL_ISRULE(pCondition
,between_predicate
))
1106 OSL_ENSURE( false, "OSingleSelectQueryComposer::setANDCriteria: between_predicate not implemented!" );
1109 rFilter
.push_back(aItem
);
1114 else if (SQL_ISRULE(pCondition
,existence_test
) ||
1115 SQL_ISRULE(pCondition
,unique_test
))
1117 // this couldn't be handled here, too complex
1118 // as we need a field name
1126 // -----------------------------------------------------------------------------
1127 sal_Int32
OSingleSelectQueryComposer::getPredicateType(OSQLParseNode
* _pPredicate
) const
1129 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getPredicateType" );
1130 sal_Int32 nPredicate
= SQLFilterOperator::EQUAL
;
1131 switch (_pPredicate
->getNodeType())
1133 case SQL_NODE_EQUAL
:
1134 nPredicate
= SQLFilterOperator::EQUAL
;
1136 case SQL_NODE_NOTEQUAL
:
1137 nPredicate
= SQLFilterOperator::NOT_EQUAL
;
1140 nPredicate
= SQLFilterOperator::LESS
;
1142 case SQL_NODE_LESSEQ
:
1143 nPredicate
= SQLFilterOperator::LESS_EQUAL
;
1145 case SQL_NODE_GREAT
:
1146 nPredicate
= SQLFilterOperator::GREATER
;
1148 case SQL_NODE_GREATEQ
:
1149 nPredicate
= SQLFilterOperator::GREATER_EQUAL
;
1152 OSL_ENSURE(0,"Wrong NodeType!");
1156 //------------------------------------------------------------------------------
1157 sal_Bool
OSingleSelectQueryComposer::setComparsionPredicate(OSQLParseNode
* pCondition
, OSQLParseTreeIterator
& _rIterator
,
1158 ::std::vector
< PropertyValue
>& rFilter
, const Reference
< ::com::sun::star::util::XNumberFormatter
> & xFormatter
) const
1160 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setComparsionPredicate" );
1161 DBG_ASSERT(SQL_ISRULE(pCondition
, comparison_predicate
),"setComparsionPredicate: pCondition ist kein ComparsionPredicate");
1162 if (SQL_ISRULE(pCondition
->getChild(0), column_ref
) ||
1163 SQL_ISRULE(pCondition
->getChild(pCondition
->count()-1), column_ref
))
1165 PropertyValue aItem
;
1166 ::rtl::OUString aValue
;
1168 if (SQL_ISRULE(pCondition
->getChild(0), column_ref
))
1173 aItem
.Handle
= getPredicateType(pCondition
->getChild(i
));
1174 // don't display the equal
1175 if (pCondition
->getChild(i
)->getNodeType() == SQL_NODE_EQUAL
)
1179 for (;i
< pCondition
->count();i
++)
1180 pCondition
->getChild(i
)->parseNodeToPredicateStr(
1181 aValue
, m_xConnection
, xFormatter
, m_aLocale
, static_cast<sal_Char
>(m_sDecimalSep
.toChar() ) );
1183 else if (SQL_ISRULE(pCondition
->getChild(pCondition
->count()-1), column_ref
))
1185 nPos
= pCondition
->count()-1;
1187 sal_Int32 i
= pCondition
->count() - 2;
1188 switch (pCondition
->getChild(i
)->getNodeType())
1190 case SQL_NODE_EQUAL
:
1191 // don't display the equal
1193 aItem
.Handle
= SQLFilterOperator::EQUAL
;
1195 case SQL_NODE_NOTEQUAL
:
1197 aItem
.Handle
= SQLFilterOperator::NOT_EQUAL
;
1200 // take the opposite as we change the order
1202 aValue
= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(">="));
1203 aItem
.Handle
= SQLFilterOperator::GREATER_EQUAL
;
1205 case SQL_NODE_LESSEQ
:
1206 // take the opposite as we change the order
1208 aValue
= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(">"));
1209 aItem
.Handle
= SQLFilterOperator::GREATER
;
1211 case SQL_NODE_GREAT
:
1212 // take the opposite as we change the order
1214 aValue
= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("<="));
1215 aItem
.Handle
= SQLFilterOperator::LESS_EQUAL
;
1217 case SQL_NODE_GREATEQ
:
1218 // take the opposite as we change the order
1220 aValue
= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("<"));
1221 aItem
.Handle
= SQLFilterOperator::LESS
;
1229 pCondition
->getChild(i
)->parseNodeToPredicateStr(
1230 aValue
, m_xConnection
, xFormatter
, m_aLocale
, static_cast<sal_Char
>( m_sDecimalSep
.toChar() ) );
1235 aItem
.Name
= getColumnName(pCondition
->getChild(nPos
),_rIterator
);
1236 aItem
.Value
<<= aValue
;
1237 rFilter
.push_back(aItem
);
1239 else if (SQL_ISRULE(pCondition
->getChild(0), set_fct_spec
) ||
1240 SQL_ISRULE(pCondition
->getChild(0), general_set_fct
))
1242 PropertyValue aItem
;
1243 ::rtl::OUString aValue
;
1244 ::rtl::OUString aColumnName
;
1246 pCondition
->parseNodeToPredicateStr(aValue
, m_xConnection
, xFormatter
, m_aLocale
, static_cast<sal_Char
>( m_sDecimalSep
.toChar() ) );
1247 pCondition
->getChild(0)->parseNodeToPredicateStr( aColumnName
, m_xConnection
, xFormatter
, m_aLocale
, static_cast<sal_Char
>( m_sDecimalSep
.toChar() ) );
1249 // don't display the column name
1250 aValue
= aValue
.copy(aColumnName
.getLength());
1253 aItem
.Name
= getColumnName(pCondition
->getChild(0),_rIterator
);
1254 aItem
.Value
<<= aValue
;
1255 aItem
.Handle
= pCondition
->getNodeType();
1256 rFilter
.push_back(aItem
);
1258 else // kann sich nur um einen Expr. Ausdruck handeln
1260 PropertyValue aItem
;
1261 ::rtl::OUString aName
, aValue
;
1263 OSQLParseNode
*pLhs
= pCondition
->getChild(0);
1264 OSQLParseNode
*pRhs
= pCondition
->getChild(2);
1268 for (i
=0;i
< pLhs
->count();i
++)
1269 pLhs
->getChild(i
)->parseNodeToPredicateStr( aName
, m_xConnection
, xFormatter
, m_aLocale
, static_cast<sal_Char
>( m_sDecimalSep
.toChar() ) );
1272 aItem
.Handle
= pCondition
->getChild(1)->getNodeType();
1273 aValue
= pCondition
->getChild(1)->getTokenValue();
1274 for(i
=0;i
< pRhs
->count();i
++)
1275 pRhs
->getChild(i
)->parseNodeToPredicateStr(aValue
, m_xConnection
, xFormatter
, m_aLocale
, static_cast<sal_Char
>( m_sDecimalSep
.toChar() ) );
1278 aItem
.Value
<<= aValue
;
1279 rFilter
.push_back(aItem
);
1283 // functions for analysing SQL
1284 //--------------------------------------------------------------------------------------------------
1285 ::rtl::OUString
OSingleSelectQueryComposer::getColumnName( ::connectivity::OSQLParseNode
* pColumnRef
, OSQLParseTreeIterator
& _rIterator
) const
1287 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getColumnName" );
1288 ::rtl::OUString aTableRange
, aColumnName
;
1289 _rIterator
.getColumnRange(pColumnRef
,aColumnName
,aTableRange
);
1292 //------------------------------------------------------------------------------
1293 ::rtl::OUString SAL_CALL
OSingleSelectQueryComposer::getFilter( ) throw(RuntimeException
)
1295 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getFilter" );
1296 ::connectivity::checkDisposed(OSubComponent::rBHelper
.bDisposed
);
1297 ::osl::MutexGuard
aGuard( m_aMutex
);
1298 return getSQLPart(Where
,m_aAdditiveIterator
,sal_False
);
1300 // -------------------------------------------------------------------------
1301 ::rtl::OUString SAL_CALL
OSingleSelectQueryComposer::getOrder( ) throw(RuntimeException
)
1303 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getOrder" );
1304 ::connectivity::checkDisposed(OSubComponent::rBHelper
.bDisposed
);
1305 ::osl::MutexGuard
aGuard( m_aMutex
);
1306 return getSQLPart(Order
,m_aAdditiveIterator
,sal_False
);
1308 // -------------------------------------------------------------------------
1309 ::rtl::OUString SAL_CALL
OSingleSelectQueryComposer::getGroup( ) throw (RuntimeException
)
1311 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getGroup" );
1312 ::connectivity::checkDisposed(OSubComponent::rBHelper
.bDisposed
);
1313 ::osl::MutexGuard
aGuard( m_aMutex
);
1314 return getSQLPart(Group
,m_aAdditiveIterator
,sal_False
);
1316 // -----------------------------------------------------------------------------
1317 ::rtl::OUString
OSingleSelectQueryComposer::getHavingClause() throw (RuntimeException
)
1319 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getHavingClause" );
1320 ::connectivity::checkDisposed(OSubComponent::rBHelper
.bDisposed
);
1321 ::osl::MutexGuard
aGuard( m_aMutex
);
1322 return getSQLPart(Having
,m_aAdditiveIterator
,sal_False
);
1324 // -----------------------------------------------------------------------------
1325 ::rtl::OUString
OSingleSelectQueryComposer::getTableAlias(const Reference
< XPropertySet
>& column
) const
1327 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getTableAlias" );
1328 ::rtl::OUString sReturn
;
1329 if(m_pTables
&& m_pTables
->getCount() > 1)
1331 ::rtl::OUString aCatalog
,aSchema
,aTable
,aComposedName
,aColumnName
;
1332 column
->getPropertyValue(PROPERTY_CATALOGNAME
) >>= aCatalog
;
1333 column
->getPropertyValue(PROPERTY_SCHEMANAME
) >>= aSchema
;
1334 column
->getPropertyValue(PROPERTY_TABLENAME
) >>= aTable
;
1335 column
->getPropertyValue(PROPERTY_NAME
) >>= aColumnName
;
1337 Sequence
< ::rtl::OUString
> aNames(m_pTables
->getElementNames());
1338 const ::rtl::OUString
* pBegin
= aNames
.getConstArray();
1339 const ::rtl::OUString
* pEnd
= pBegin
+ aNames
.getLength();
1341 if(!aTable
.getLength())
1342 { // we don't found a table name, now we must search every table for this column
1343 for(;pBegin
!= pEnd
;++pBegin
)
1345 Reference
<XColumnsSupplier
> xColumnsSupp
;
1346 m_pTables
->getByName(*pBegin
) >>= xColumnsSupp
;
1348 if(xColumnsSupp
.is() && xColumnsSupp
->getColumns()->hasByName(aColumnName
))
1350 // Reference<XPropertySet> xTableProp(xColumnsSupp,UNO_QUERY);
1351 // xTableProp->getPropertyValue(PROPERTY_CATALOGNAME) >>= aCatalog;
1352 // xTableProp->getPropertyValue(PROPERTY_SCHEMANAME) >>= aSchema;
1353 // xTableProp->getPropertyValue(PROPERTY_NAME) >>= aTable;
1361 aComposedName
= ::dbtools::composeTableName( m_xMetaData
, aCatalog
, aSchema
, aTable
, sal_False
, ::dbtools::eInDataManipulation
);
1363 // first check if this is the table we want to or has it a tablealias
1365 if(!m_pTables
->hasByName(aComposedName
))
1367 ::comphelper::UStringMixLess
aTmp(m_aAdditiveIterator
.getTables().key_comp());
1368 ::comphelper::UStringMixEqual
aComp(static_cast< ::comphelper::UStringMixLess
*>(&aTmp
)->isCaseSensitive());
1369 for(;pBegin
!= pEnd
;++pBegin
)
1371 Reference
<XPropertySet
> xTableProp
;
1372 m_pTables
->getByName(*pBegin
) >>= xTableProp
;
1373 OSL_ENSURE(xTableProp
.is(),"Table isn't a propertyset!");
1376 ::rtl::OUString aCatalog2
,aSchema2
,aTable2
;
1377 xTableProp
->getPropertyValue(PROPERTY_CATALOGNAME
) >>= aCatalog2
;
1378 xTableProp
->getPropertyValue(PROPERTY_SCHEMANAME
) >>= aSchema2
;
1379 xTableProp
->getPropertyValue(PROPERTY_NAME
) >>= aTable2
;
1380 if(aComp(aCatalog
,aCatalog2
) && aComp(aSchema
,aSchema2
) && aComp(aTable
,aTable2
))
1382 aCatalog
= aCatalog2
;
1393 sReturn
= ::dbtools::composeTableName( m_xMetaData
, aCatalog
, aSchema
, aTable
, sal_True
, ::dbtools::eInDataManipulation
);
1394 sReturn
+= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("."));
1399 // -----------------------------------------------------------------------------
1400 Reference
< XIndexAccess
> SAL_CALL
OSingleSelectQueryComposer::getParameters( ) throw(RuntimeException
)
1402 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getParameters" );
1403 // now set the Parameters
1404 if ( !m_aCurrentColumns
[ParameterColumns
] )
1406 ::vos::ORef
< OSQLColumns
> aCols
= m_aSqlIterator
.getParameters();
1407 ::std::vector
< ::rtl::OUString
> aNames
;
1408 OSQLColumns::Vector::const_iterator aEnd
= aCols
->get().end();
1409 for(OSQLColumns::Vector::const_iterator aIter
= aCols
->get().begin(); aIter
!= aEnd
;++aIter
)
1410 aNames
.push_back(getString((*aIter
)->getPropertyValue(PROPERTY_NAME
)));
1411 m_aCurrentColumns
[ParameterColumns
] = new OPrivateColumns(aCols
,m_xMetaData
->supportsMixedCaseQuotedIdentifiers(),*this,m_aMutex
,aNames
,sal_True
);
1414 return m_aCurrentColumns
[ParameterColumns
];
1416 // -----------------------------------------------------------------------------
1417 void OSingleSelectQueryComposer::clearColumns( const EColumnType _eType
)
1419 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::clearColumns" );
1420 OPrivateColumns
* pColumns
= m_aCurrentColumns
[ _eType
];
1421 if ( pColumns
!= NULL
)
1423 pColumns
->disposing();
1424 m_aColumnsCollection
.push_back( pColumns
);
1425 m_aCurrentColumns
[ _eType
] = NULL
;
1428 // -----------------------------------------------------------------------------
1429 void OSingleSelectQueryComposer::clearCurrentCollections()
1431 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::clearCurrentCollections" );
1432 ::std::vector
<OPrivateColumns
*>::iterator aIter
= m_aCurrentColumns
.begin();
1433 ::std::vector
<OPrivateColumns
*>::iterator aEnd
= m_aCurrentColumns
.end();
1434 for (;aIter
!= aEnd
;++aIter
)
1438 (*aIter
)->disposing();
1439 m_aColumnsCollection
.push_back(*aIter
);
1446 m_pTables
->disposing();
1447 m_aTablesCollection
.push_back(m_pTables
);
1451 // -----------------------------------------------------------------------------
1452 Reference
< XIndexAccess
> OSingleSelectQueryComposer::setCurrentColumns( EColumnType _eType
,
1453 const ::vos::ORef
< OSQLColumns
>& _rCols
)
1455 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setCurrentColumns" );
1456 ::connectivity::checkDisposed(OSubComponent::rBHelper
.bDisposed
);
1458 ::osl::MutexGuard
aGuard( m_aMutex
);
1459 // now set the group columns
1460 if ( !m_aCurrentColumns
[_eType
] )
1462 ::std::vector
< ::rtl::OUString
> aNames
;
1463 OSQLColumns::Vector::const_iterator aEnd
= _rCols
->get().end();
1464 for(OSQLColumns::Vector::const_iterator aIter
= _rCols
->get().begin(); aIter
!= aEnd
;++aIter
)
1465 aNames
.push_back(getString((*aIter
)->getPropertyValue(PROPERTY_NAME
)));
1466 m_aCurrentColumns
[_eType
] = new OPrivateColumns(_rCols
,m_xMetaData
->supportsMixedCaseQuotedIdentifiers(),*this,m_aMutex
,aNames
,sal_True
);
1469 return m_aCurrentColumns
[_eType
];
1471 // -----------------------------------------------------------------------------
1472 Reference
< XIndexAccess
> SAL_CALL
OSingleSelectQueryComposer::getGroupColumns( ) throw(RuntimeException
)
1474 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getGroupColumns" );
1475 return setCurrentColumns( GroupByColumns
, m_aAdditiveIterator
.getGroupColumns() );
1477 // -------------------------------------------------------------------------
1478 Reference
< XIndexAccess
> SAL_CALL
OSingleSelectQueryComposer::getOrderColumns( ) throw(RuntimeException
)
1480 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getOrderColumns" );
1481 return setCurrentColumns( OrderColumns
, m_aAdditiveIterator
.getOrderColumns() );
1483 // -----------------------------------------------------------------------------
1484 ::rtl::OUString SAL_CALL
OSingleSelectQueryComposer::getQueryWithSubstitution( ) throw (SQLException
, RuntimeException
)
1486 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getQueryWithSubstitution" );
1487 ::osl::MutexGuard
aGuard( m_aMutex
);
1488 ::connectivity::checkDisposed(OSubComponent::rBHelper
.bDisposed
);
1490 ::rtl::OUString
sSqlStatement( getQuery() );
1492 const OSQLParseNode
* pStatementNode
= m_aSqlIterator
.getParseTree();
1493 if ( pStatementNode
)
1495 SQLException aError
;
1496 if ( !pStatementNode
->parseNodeToExecutableStatement( sSqlStatement
, m_xConnection
, m_aSqlParser
, &aError
) )
1497 throw SQLException( aError
);
1500 return sSqlStatement
;
1502 // -----------------------------------------------------------------------------
1503 ::rtl::OUString
OSingleSelectQueryComposer::getStatementPart( TGetParseNode
& _aGetFunctor
, OSQLParseTreeIterator
& _rIterator
)
1505 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getStatementPart" );
1506 ::rtl::OUString sResult
;
1508 const OSQLParseNode
* pNode
= _aGetFunctor( &_rIterator
);
1510 pNode
->parseNodeToStr( sResult
, m_xConnection
);
1514 // -----------------------------------------------------------------------------
1517 ::rtl::OUString
lcl_getCondition(const Sequence
< Sequence
< PropertyValue
> >& filter
)
1519 ::rtl::OUStringBuffer sRet
;
1520 const Sequence
< PropertyValue
>* pOrIter
= filter
.getConstArray();
1521 const Sequence
< PropertyValue
>* pOrEnd
= pOrIter
+ filter
.getLength();
1522 while ( pOrIter
!= pOrEnd
)
1524 if ( pOrIter
->getLength() )
1526 sRet
.append(L_BRACKET
);
1527 const PropertyValue
* pAndIter
= pOrIter
->getConstArray();
1528 const PropertyValue
* pAndEnd
= pAndIter
+ pOrIter
->getLength();
1529 while ( pAndIter
!= pAndEnd
)
1531 sRet
.append(pAndIter
->Name
);
1532 ::rtl::OUString sValue
;
1533 pAndIter
->Value
>>= sValue
;
1534 lcl_addFilterCriteria_throw(pAndIter
->Handle
,sValue
,sRet
);
1536 if ( pAndIter
!= pAndEnd
)
1537 sRet
.append(STR_AND
);
1539 sRet
.append(R_BRACKET
);
1542 if ( pOrIter
!= pOrEnd
&& sRet
.getLength() )
1543 sRet
.append(STR_OR
);
1545 return sRet
.makeStringAndClear();
1548 // -----------------------------------------------------------------------------
1549 void SAL_CALL
OSingleSelectQueryComposer::setStructuredFilter( const Sequence
< Sequence
< PropertyValue
> >& filter
) throw (SQLException
, ::com::sun::star::lang::IllegalArgumentException
, RuntimeException
)
1551 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setStructuredFilter" );
1552 setFilter(lcl_getCondition(filter
));
1554 // -----------------------------------------------------------------------------
1555 void SAL_CALL
OSingleSelectQueryComposer::setStructuredHavingClause( const Sequence
< Sequence
< PropertyValue
> >& filter
) throw (SQLException
, RuntimeException
)
1557 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setStructuredHavingClause" );
1558 setHavingClause(lcl_getCondition(filter
));
1560 // -----------------------------------------------------------------------------
1561 void OSingleSelectQueryComposer::setConditionByColumn( const Reference
< XPropertySet
>& column
, sal_Bool andCriteria
,::std::mem_fun1_t
<bool,OSingleSelectQueryComposer
,::rtl::OUString
>& _aSetFunctor
,sal_Int32 filterOperator
)
1563 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setConditionByColumn" );
1564 ::connectivity::checkDisposed(OSubComponent::rBHelper
.bDisposed
);
1567 || !column
->getPropertySetInfo()->hasPropertyByName(PROPERTY_VALUE
)
1568 || !column
->getPropertySetInfo()->hasPropertyByName(PROPERTY_NAME
)
1569 || !column
->getPropertySetInfo()->hasPropertyByName(PROPERTY_TYPE
))
1570 throw SQLException(DBACORE_RESSTRING(RID_STR_COLUMN_NOT_VALID
),*this,SQLSTATE_GENERAL
,1000,Any() );
1572 sal_Int32 nType
= 0;
1573 column
->getPropertyValue(PROPERTY_TYPE
) >>= nType
;
1574 sal_Int32 nSearchable
= dbtools::getSearchColumnFlag(m_xConnection
,nType
);
1575 if(nSearchable
== ColumnSearch::NONE
)
1576 throw SQLException(DBACORE_RESSTRING(RID_STR_COLUMN_NOT_SEARCHABLE
),*this,SQLSTATE_GENERAL
,1000,Any() );
1578 ::osl::MutexGuard
aGuard( m_aMutex
);
1580 ::rtl::OUString aName
;
1581 column
->getPropertyValue(PROPERTY_NAME
) >>= aName
;
1584 column
->getPropertyValue(PROPERTY_VALUE
) >>= aValue
;
1586 ::rtl::OUStringBuffer aSQL
;
1587 const ::rtl::OUString aQuote
= m_xMetaData
->getIdentifierQuoteString();
1590 if ( m_aCurrentColumns
[SelectColumns
] && m_aCurrentColumns
[SelectColumns
]->hasByName(aName
) )
1592 Reference
<XPropertySet
> xColumn
;
1593 m_aCurrentColumns
[SelectColumns
]->getByName(aName
) >>= xColumn
;
1594 OSL_ENSURE(xColumn
->getPropertySetInfo()->hasPropertyByName(PROPERTY_REALNAME
),"Property REALNAME not available!");
1595 OSL_ENSURE(xColumn
->getPropertySetInfo()->hasPropertyByName(PROPERTY_TABLENAME
),"Property TABLENAME not available!");
1596 OSL_ENSURE(xColumn
->getPropertySetInfo()->hasPropertyByName(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AggregateFunction"))),"Property AggregateFunctionnot available!");
1598 ::rtl::OUString sRealName
,sTableName
;
1599 xColumn
->getPropertyValue(PROPERTY_REALNAME
) >>= sRealName
;
1600 xColumn
->getPropertyValue(PROPERTY_TABLENAME
) >>= sTableName
;
1601 if(sTableName
.indexOf('.',0) != -1)
1603 ::rtl::OUString aCatlog
,aSchema
,aTable
;
1604 ::dbtools::qualifiedNameComponents(m_xMetaData
,sTableName
,aCatlog
,aSchema
,aTable
,::dbtools::eInDataManipulation
);
1605 sTableName
= ::dbtools::composeTableName( m_xMetaData
, aCatlog
, aSchema
, aTable
, sal_True
, ::dbtools::eInDataManipulation
);
1608 sTableName
= ::dbtools::quoteName(aQuote
,sTableName
);
1610 if ( !::comphelper::getBOOL(xColumn
->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Function")))) )
1613 aSQL
.appendAscii( "." );
1614 aSQL
.append( ::dbtools::quoteName( aQuote
, sRealName
) );
1622 aSQL
= getTableAlias( column
);
1623 aSQL
.append( ::dbtools::quoteName( aQuote
, aName
) );
1627 if ( aValue
.hasValue() )
1629 if( !m_xTypeConverter
.is() )
1630 m_aContext
.createComponent( "com.sun.star.script.Converter", m_xTypeConverter
);
1631 OSL_ENSURE(m_xTypeConverter
.is(),"NO typeconverter!");
1633 if ( nType
!= DataType::BOOLEAN
&& DataType::BIT
!= nType
)
1635 ::rtl::OUString sEmpty
;
1636 lcl_addFilterCriteria_throw(filterOperator
,sEmpty
,aSQL
);
1641 case DataType::VARCHAR
:
1642 case DataType::CHAR
:
1643 case DataType::LONGVARCHAR
:
1644 aSQL
.append( DBTypeConversion::toSQLString( nType
, aValue
, sal_True
, m_xTypeConverter
) );
1646 case DataType::CLOB
:
1648 Reference
< XClob
> xClob(aValue
,UNO_QUERY
);
1651 const ::sal_Int64 nLength
= xClob
->length();
1652 if ( sal_Int64(nLength
+ aSQL
.getLength() + STR_LIKE
.getLength() ) < sal_Int64(SAL_MAX_INT32
) )
1654 aSQL
.appendAscii("'");
1655 aSQL
.append( xClob
->getSubString(1,(sal_Int32
)nLength
) );
1656 aSQL
.appendAscii("'");
1661 aSQL
.append( DBTypeConversion::toSQLString( nType
, aValue
, sal_True
, m_xTypeConverter
) );
1665 case DataType::VARBINARY
:
1666 case DataType::BINARY
:
1667 case DataType::LONGVARBINARY
:
1669 Sequence
<sal_Int8
> aSeq
;
1672 if(nSearchable
== ColumnSearch::CHAR
)
1674 aSQL
.appendAscii( "\'" );
1676 aSQL
.appendAscii( "0x" );
1677 const sal_Int8
* pBegin
= aSeq
.getConstArray();
1678 const sal_Int8
* pEnd
= pBegin
+ aSeq
.getLength();
1679 for(;pBegin
!= pEnd
;++pBegin
)
1681 aSQL
.append( (sal_Int32
)*pBegin
, 16 ).getStr();
1683 if(nSearchable
== ColumnSearch::CHAR
)
1684 aSQL
.appendAscii( "\'" );
1687 throw SQLException(DBACORE_RESSTRING(RID_STR_NOT_SEQUENCE_INT8
),*this,SQLSTATE_GENERAL
,1000,Any() );
1691 case DataType::BOOLEAN
:
1693 sal_Bool bValue
= sal_False
;
1694 m_xTypeConverter
->convertToSimpleType(aValue
, TypeClass_BOOLEAN
) >>= bValue
;
1696 ::rtl::OUString sColumnExp
= aSQL
.makeStringAndClear();
1697 getBoleanComparisonPredicate( sColumnExp
, bValue
, m_nBoolCompareMode
, aSQL
);
1701 aSQL
.append( DBTypeConversion::toSQLString( nType
, aValue
, sal_True
, m_xTypeConverter
) );
1707 sal_Int32 nFilterOp
= filterOperator
;
1708 if ( filterOperator
!= SQLFilterOperator::SQLNULL
&& filterOperator
!= SQLFilterOperator::NOT_SQLNULL
)
1709 nFilterOp
= SQLFilterOperator::SQLNULL
;
1710 ::rtl::OUString sEmpty
;
1711 lcl_addFilterCriteria_throw(nFilterOp
,sEmpty
,aSQL
);
1715 // select ohne where und order by aufbauen
1716 ::rtl::OUString sFilter
= getFilter();
1718 if ( sFilter
.getLength() && aSQL
.getLength() )
1720 ::rtl::OUString
sTemp(L_BRACKET
);
1723 sTemp
+= andCriteria
? STR_AND
: STR_OR
;
1726 sFilter
+= aSQL
.makeStringAndClear();
1728 // add the filter and the sort order
1729 _aSetFunctor(this,sFilter
);
1731 // -----------------------------------------------------------------------------
1732 Sequence
< Sequence
< PropertyValue
> > OSingleSelectQueryComposer::getStructuredCondition( TGetParseNode
& _aGetFunctor
)
1734 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getStructuredCondition" );
1735 ::connectivity::checkDisposed(OSubComponent::rBHelper
.bDisposed
);
1737 MutexGuard
aGuard(m_aMutex
);
1739 Sequence
< Sequence
< PropertyValue
> > aFilterSeq
;
1740 ::rtl::OUString sFilter
= getStatementPart( _aGetFunctor
, m_aAdditiveIterator
);
1742 if ( sFilter
.getLength() != 0 )
1744 ::rtl::OUString
aSql(m_aPureSelectSQL
);
1745 // build a temporary parse node
1746 const OSQLParseNode
* pTempNode
= m_aAdditiveIterator
.getParseTree();
1751 ::rtl::OUString aErrorMsg
;
1752 ::std::auto_ptr
<OSQLParseNode
> pSqlParseNode( m_aSqlParser
.parseTree(aErrorMsg
,aSql
));
1753 if ( pSqlParseNode
.get() )
1755 m_aAdditiveIterator
.setParseTree(pSqlParseNode
.get());
1756 // normalize the filter
1757 OSQLParseNode
* pWhereNode
= const_cast<OSQLParseNode
*>(m_aAdditiveIterator
.getWhereTree());
1759 OSQLParseNode
* pCondition
= pWhereNode
->getChild(1);
1760 #if OSL_DEBUG_LEVEL > 0
1761 ::rtl::OUString sCondition
;
1762 pCondition
->parseNodeToStr( sCondition
, m_xConnection
);
1764 OSQLParseNode::negateSearchCondition(pCondition
);
1766 pCondition
= pWhereNode
->getChild(1);
1767 #if OSL_DEBUG_LEVEL > 0
1768 sCondition
= ::rtl::OUString();
1769 pCondition
->parseNodeToStr( sCondition
, m_xConnection
);
1771 OSQLParseNode::disjunctiveNormalForm(pCondition
);
1773 pCondition
= pWhereNode
->getChild(1);
1774 #if OSL_DEBUG_LEVEL > 0
1775 sCondition
= ::rtl::OUString();
1776 pCondition
->parseNodeToStr( sCondition
, m_xConnection
);
1778 OSQLParseNode::absorptions(pCondition
);
1780 pCondition
= pWhereNode
->getChild(1);
1781 #if OSL_DEBUG_LEVEL > 0
1782 sCondition
= ::rtl::OUString();
1783 pCondition
->parseNodeToStr( sCondition
, m_xConnection
);
1787 ::std::vector
< ::std::vector
< PropertyValue
> > aFilters
;
1788 Reference
< XNumberFormatter
> xFormatter
;
1789 m_aContext
.createComponent( "com.sun.star.util.NumberFormatter", xFormatter
);
1790 xFormatter
->attachNumberFormatsSupplier( m_xNumberFormatsSupplier
);
1792 if (setORCriteria(pCondition
, m_aAdditiveIterator
, aFilters
, xFormatter
))
1794 aFilterSeq
.realloc(aFilters
.size());
1795 Sequence
<PropertyValue
>* pFilters
= aFilterSeq
.getArray();
1796 ::std::vector
< ::std::vector
< PropertyValue
> >::const_iterator aEnd
= aFilters
.end();
1797 ::std::vector
< ::std::vector
< PropertyValue
> >::const_iterator i
= aFilters
.begin();
1798 for ( ; i
!= aEnd
; ++i
)
1800 const ::std::vector
< PropertyValue
>& rProperties
= *i
;
1801 pFilters
->realloc(rProperties
.size());
1802 PropertyValue
* pFilter
= pFilters
->getArray();
1803 ::std::vector
< PropertyValue
>::const_iterator j
= rProperties
.begin();
1804 ::std::vector
< PropertyValue
>::const_iterator aEnd2
= rProperties
.end();
1805 for ( ; j
!= aEnd2
; ++j
)
1815 m_aAdditiveIterator
.setParseTree(pTempNode
);
1820 // -----------------------------------------------------------------------------
1821 ::rtl::OUString
OSingleSelectQueryComposer::getKeyword( SQLPart _ePart
) const
1823 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getKeyword" );
1824 ::rtl::OUString sKeyword
;
1828 OSL_ENSURE( 0, "OSingleSelectQueryComposer::getKeyWord: Invalid enum value!" );
1829 // no break, fallback to WHERE
1831 sKeyword
= STR_WHERE
;
1834 sKeyword
= STR_GROUP_BY
;
1837 sKeyword
= STR_HAVING
;
1840 sKeyword
= STR_ORDER_BY
;
1846 // -----------------------------------------------------------------------------
1847 ::rtl::OUString
OSingleSelectQueryComposer::getSQLPart( SQLPart _ePart
, OSQLParseTreeIterator
& _rIterator
, sal_Bool _bWithKeyword
)
1849 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getSQLPart" );
1850 TGetParseNode
F_tmp(&OSQLParseTreeIterator::getSimpleWhereTree
);
1851 ::rtl::OUString
sKeyword( getKeyword( _ePart
) );
1855 F_tmp
= TGetParseNode(&OSQLParseTreeIterator::getSimpleWhereTree
);
1858 F_tmp
= TGetParseNode (&OSQLParseTreeIterator::getSimpleGroupByTree
);
1861 F_tmp
= TGetParseNode(&OSQLParseTreeIterator::getSimpleHavingTree
);
1864 F_tmp
= TGetParseNode(&OSQLParseTreeIterator::getSimpleOrderTree
);
1867 OSL_ENSURE(0,"Invalid enum value!");
1870 ::rtl::OUString sRet
= getStatementPart( F_tmp
, _rIterator
);
1871 if ( _bWithKeyword
&& sRet
.getLength() )
1872 sRet
= sKeyword
+ sRet
;
1875 // -----------------------------------------------------------------------------