1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <sal/log.hxx>
22 #include <composertools.hxx>
23 #include <strings.hrc>
24 #include <strings.hxx>
25 #include <core_resource.hxx>
26 #include <stringconstants.hxx>
27 #include "HelperCollections.hxx"
28 #include <SingleSelectQueryComposer.hxx>
29 #include <sqlbison.hxx>
30 #include <sdbcoretools.hxx>
32 #include <com/sun/star/beans/PropertyAttribute.hpp>
33 #include <com/sun/star/i18n/LocaleData.hpp>
34 #include <com/sun/star/script/Converter.hpp>
35 #include <com/sun/star/sdb/BooleanComparisonMode.hpp>
36 #include <com/sun/star/sdb/SQLFilterOperator.hpp>
37 #include <com/sun/star/sdb/XQueriesSupplier.hpp>
38 #include <com/sun/star/sdb/CommandType.hpp>
39 #include <com/sun/star/sdbc/ColumnSearch.hpp>
40 #include <com/sun/star/sdbc/DataType.hpp>
41 #include <com/sun/star/sdbc/XConnection.hpp>
42 #include <com/sun/star/sdbc/XResultSetMetaData.hpp>
43 #include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
44 #include <com/sun/star/sdbc/XParameters.hpp>
45 #include <com/sun/star/util/NumberFormatter.hpp>
47 #include <comphelper/types.hxx>
48 #include <cppuhelper/exc_hlp.hxx>
49 #include <connectivity/dbtools.hxx>
50 #include <connectivity/PColumn.hxx>
51 #include <connectivity/predicateinput.hxx>
52 #include <comphelper/diagnose_ex.hxx>
53 #include <osl/diagnose.h>
54 #include <unotools/sharedunocomponent.hxx>
57 #include <string_view>
59 using namespace ::dbaccess
;
60 using namespace ::dbtools
;
61 using namespace ::comphelper
;
62 using namespace ::connectivity
;
63 using namespace ::com::sun::star::uno
;
64 using namespace ::com::sun::star::beans
;
65 using namespace ::com::sun::star::sdbc
;
66 using namespace ::com::sun::star::sdb
;
67 using namespace ::com::sun::star::sdbcx
;
68 using namespace ::com::sun::star::container
;
69 using namespace ::com::sun::star::i18n
;
70 using namespace ::com::sun::star::lang
;
71 using namespace ::com::sun::star::script
;
72 using namespace ::com::sun::star::util
;
73 using namespace ::cppu
;
74 using namespace ::osl
;
75 using namespace ::utl
;
78 namespace BooleanComparisonMode
= ::com::sun::star::sdb::BooleanComparisonMode
;
81 constexpr OUStringLiteral STR_SELECT
= u
"SELECT ";
82 constexpr OUStringLiteral STR_FROM
= u
" FROM ";
83 constexpr OUString STR_WHERE
= u
" WHERE "_ustr
;
84 constexpr OUStringLiteral STR_GROUP_BY
= u
" GROUP BY ";
85 constexpr OUStringLiteral STR_HAVING
= u
" HAVING ";
86 constexpr OUStringLiteral STR_ORDER_BY
= u
" ORDER BY ";
87 constexpr OUString STR_AND
= u
" AND "_ustr
;
88 constexpr OUString STR_OR
= u
" OR "_ustr
;
89 constexpr OUStringLiteral STR_LIKE
= u
" LIKE ";
90 constexpr OUString L_BRACKET
= u
"("_ustr
;
91 constexpr OUString R_BRACKET
= u
")"_ustr
;
92 constexpr OUStringLiteral COMMA
= u
",";
96 /** parses the given statement, using the given parser, returns a parse node representing
99 If the statement cannot be parsed, an error is thrown.
101 std::unique_ptr
<OSQLParseNode
> parseStatement_throwError( OSQLParser
& _rParser
, const OUString
& _rStatement
, const Reference
< XInterface
>& _rxContext
)
104 std::unique_ptr
<OSQLParseNode
> pNewSqlParseNode
= _rParser
.parseTree( aErrorMsg
, _rStatement
);
105 if ( !pNewSqlParseNode
)
107 OUString
sSQLStateGeneralError( getStandardSQLState( StandardSQLState::GENERAL_ERROR
) );
108 SQLException
aError2( aErrorMsg
, _rxContext
, sSQLStateGeneralError
, 1000, Any() );
109 SQLException
aError1( _rStatement
, _rxContext
, sSQLStateGeneralError
, 1000, Any( aError2
) );
110 throw SQLException(_rParser
.getContext().getErrorMessage(OParseContext::ErrorCode::General
),_rxContext
,sSQLStateGeneralError
,1000,Any(aError1
));
112 return pNewSqlParseNode
;
115 /** checks whether the given parse node describes a valid single select statement, throws
118 void checkForSingleSelect_throwError( const OSQLParseNode
* pStatementNode
, OSQLParseTreeIterator
& _rIterator
,
119 const Reference
< XInterface
>& _rxContext
, const OUString
& _rOriginatingCommand
)
121 const OSQLParseNode
* pOldNode
= _rIterator
.getParseTree();
123 // determine the statement type
124 _rIterator
.setParseTree( pStatementNode
);
125 _rIterator
.traverseAll();
126 bool bIsSingleSelect
= ( _rIterator
.getStatementType() == OSQLStatementType::Select
);
128 // throw the error, if necessary
129 if ( !bIsSingleSelect
|| SQL_ISRULE( pStatementNode
, union_statement
) ) // #i4229# OJ
131 // restore the old node before throwing the exception
132 _rIterator
.setParseTree( pOldNode
);
133 // and now really ...
134 SQLException
aError1( _rOriginatingCommand
, _rxContext
, getStandardSQLState( StandardSQLState::GENERAL_ERROR
), 1000, Any() );
135 throw SQLException( DBA_RES( RID_STR_ONLY_QUERY
), _rxContext
,
136 getStandardSQLState( StandardSQLState::GENERAL_ERROR
), 1000, Any( aError1
) );
142 /** combines parseStatement_throwError and checkForSingleSelect_throwError
144 void parseAndCheck_throwError( OSQLParser
& _rParser
, const OUString
& _rStatement
,
145 OSQLParseTreeIterator
& _rIterator
, const Reference
< XInterface
>& _rxContext
)
147 std::unique_ptr
<OSQLParseNode
> pNode
= parseStatement_throwError( _rParser
, _rStatement
, _rxContext
);
148 checkForSingleSelect_throwError( pNode
.release(), _rIterator
, _rxContext
, _rStatement
);
151 /** transforms a parse node describing a complete statement into a pure select
152 statement, without any filter/order/groupby/having clauses
154 OUString
getPureSelectStatement( const OSQLParseNode
* _pRootNode
, const Reference
< XConnection
>& _rxConnection
)
156 OUString sSQL
= STR_SELECT
;
157 _pRootNode
->getChild(1)->parseNodeToStr( sSQL
, _rxConnection
);
158 _pRootNode
->getChild(2)->parseNodeToStr( sSQL
, _rxConnection
);
160 _pRootNode
->getChild(3)->getChild(0)->getChild(1)->parseNodeToStr( sSQL
, _rxConnection
);
164 /** resets an SQL iterator, including deletion of the parse tree, and dispose
166 void resetIterator( OSQLParseTreeIterator
& _rIterator
)
168 const OSQLParseNode
* pSqlParseNode
= _rIterator
.getParseTree();
169 _rIterator
.setParseTree(nullptr);
170 delete pSqlParseNode
;
171 _rIterator
.dispose();
173 void lcl_addFilterCriteria_throw(sal_Int32 i_nFilterOperator
,std::u16string_view i_sValue
,OUStringBuffer
& o_sRet
)
175 switch( i_nFilterOperator
)
177 case SQLFilterOperator::EQUAL
:
178 o_sRet
.append(OUString::Concat(" = ") + i_sValue
);
180 case SQLFilterOperator::NOT_EQUAL
:
181 o_sRet
.append(OUString::Concat(" <> ") + i_sValue
);
183 case SQLFilterOperator::LESS
:
184 o_sRet
.append(OUString::Concat(" < ") + i_sValue
);
186 case SQLFilterOperator::GREATER
:
187 o_sRet
.append(OUString::Concat(" > ") + i_sValue
);
189 case SQLFilterOperator::LESS_EQUAL
:
190 o_sRet
.append(OUString::Concat(" <= ") + i_sValue
);
192 case SQLFilterOperator::GREATER_EQUAL
:
193 o_sRet
.append(OUString::Concat(" >= ") + i_sValue
);
195 case SQLFilterOperator::LIKE
:
196 o_sRet
.append(OUString::Concat(" LIKE ") + i_sValue
);
198 case SQLFilterOperator::NOT_LIKE
:
199 o_sRet
.append(OUString::Concat(" NOT LIKE ") + i_sValue
);
201 case SQLFilterOperator::SQLNULL
:
202 o_sRet
.append(" IS NULL");
204 case SQLFilterOperator::NOT_SQLNULL
:
205 o_sRet
.append(" IS NOT NULL");
208 throw SQLException();
215 OSingleSelectQueryComposer::OSingleSelectQueryComposer(const Reference
< XNameAccess
>& _rxTables
,
216 const Reference
< XConnection
>& _xConnection
,
217 const Reference
<XComponentContext
>& _rContext
)
218 :OSubComponent(m_aMutex
,_xConnection
)
219 ,OPropertyContainer(m_aBHelper
)
220 ,m_aSqlParser( _rContext
, &m_aParseContext
, &m_aNeutralContext
)
221 ,m_aSqlIterator( _xConnection
, _rxTables
, m_aSqlParser
)
222 ,m_aAdditiveIterator( _xConnection
, _rxTables
, m_aSqlParser
)
223 ,m_aElementaryParts( size_t(SQLPartCount
) )
224 ,m_xConnection(_xConnection
)
225 ,m_xMetaData(_xConnection
->getMetaData())
226 ,m_xConnectionTables( _rxTables
)
227 ,m_aContext( _rContext
)
228 ,m_nBoolCompareMode( BooleanComparisonMode::EQUAL_INTEGER
)
229 ,m_nCommandType(CommandType::COMMAND
)
231 if ( !m_aContext
.is() || !m_xConnection
.is() || !m_xConnectionTables
.is() )
232 throw IllegalArgumentException();
234 registerProperty(PROPERTY_ORIGINAL
,PROPERTY_ID_ORIGINAL
,PropertyAttribute::BOUND
|PropertyAttribute::READONLY
,&m_sOriginal
,cppu::UnoType
<decltype(m_sOriginal
)>::get());
236 m_aCurrentColumns
.resize(4);
238 m_aLocale
= m_aParseContext
.getPreferredLocale();
239 m_xNumberFormatsSupplier
= dbtools::getNumberFormats( m_xConnection
, true, m_aContext
);
240 Reference
< XLocaleData4
> xLocaleData( LocaleData::create(m_aContext
) );
241 LocaleDataItem aData
= xLocaleData
->getLocaleItem(m_aLocale
);
242 m_sDecimalSep
= aData
.decimalSeparator
;
243 OSL_ENSURE(m_sDecimalSep
.getLength() == 1,"OSingleSelectQueryComposer::OSingleSelectQueryComposer decimal separator is not 1 length");
247 Reference
<XInterface
> xDs
= dbaccess::getDataSource(_xConnection
);
248 if ( dbtools::getDataSourceSetting(xDs
,PROPERTY_BOOLEANCOMPARISONMODE
,aValue
) )
250 OSL_VERIFY( aValue
>>= m_nBoolCompareMode
);
252 Reference
< XQueriesSupplier
> xQueriesAccess(m_xConnection
, UNO_QUERY
);
253 if (xQueriesAccess
.is())
254 m_xConnectionQueries
= xQueriesAccess
->getQueries();
261 OSingleSelectQueryComposer::~OSingleSelectQueryComposer()
266 void SAL_CALL
OSingleSelectQueryComposer::disposing()
268 OSubComponent::disposing();
270 MutexGuard
aGuard(m_aMutex
);
272 resetIterator( m_aSqlIterator
);
273 resetIterator( m_aAdditiveIterator
);
275 m_xConnectionTables
= nullptr;
276 m_xConnection
= nullptr;
278 clearCurrentCollections();
281 IMPLEMENT_FORWARD_XINTERFACE3(OSingleSelectQueryComposer
,OSubComponent
,OSingleSelectQueryComposer_BASE
,OPropertyContainer
)
282 OUString SAL_CALL
OSingleSelectQueryComposer::getImplementationName()
284 return u
"org.openoffice.comp.dba.OSingleSelectQueryComposer"_ustr
;
286 sal_Bool SAL_CALL
OSingleSelectQueryComposer::supportsService(const OUString
& _rServiceName
)
288 const css::uno::Sequence
< OUString
> aSupported(getSupportedServiceNames());
289 for (const OUString
& s
: aSupported
)
290 if (s
== _rServiceName
)
295 css::uno::Sequence
< OUString
> SAL_CALL
OSingleSelectQueryComposer::getSupportedServiceNames()
297 return { SERVICE_NAME_SINGLESELECTQUERYCOMPOSER
};
300 css::uno::Sequence
<sal_Int8
> OSingleSelectQueryComposer::getImplementationId()
302 return css::uno::Sequence
<sal_Int8
>();
305 css::uno::Sequence
< css::uno::Type
> OSingleSelectQueryComposer::getTypes()
307 return ::comphelper::concatSequences(
308 OSubComponent::getTypes( ),
309 OSingleSelectQueryComposer_BASE::getTypes( ),
310 OPropertyContainer::getTypes( )
314 css::uno::Reference
< css::beans::XPropertySetInfo
> SAL_CALL
OSingleSelectQueryComposer::getPropertySetInfo()
316 Reference
< XPropertySetInfo
> xInfo( createPropertySetInfo( getInfoHelper() ) );
319 ::cppu::IPropertyArrayHelper
& OSingleSelectQueryComposer::getInfoHelper()
321 return *OSingleSelectQueryComposer::getArrayHelper();
323 ::cppu::IPropertyArrayHelper
* OSingleSelectQueryComposer::createArrayHelper( ) const
325 css::uno::Sequence
< css::beans::Property
> aProps
;
326 describeProperties(aProps
);
327 return new ::cppu::OPropertyArrayHelper(aProps
);
331 // XSingleSelectQueryAnalyzer
332 OUString SAL_CALL
OSingleSelectQueryComposer::getQuery( )
334 ::connectivity::checkDisposed(OSubComponent::rBHelper
.bDisposed
);
335 ::osl::MutexGuard
aGuard( m_aMutex
);
337 TGetParseNode
F_tmp(&OSQLParseTreeIterator::getParseTree
);
338 return getStatementPart(F_tmp
,m_aSqlIterator
);
341 void SAL_CALL
OSingleSelectQueryComposer::setQuery( const OUString
& command
)
343 ::connectivity::checkDisposed(OSubComponent::rBHelper
.bDisposed
);
345 ::osl::MutexGuard
aGuard( m_aMutex
);
346 m_nCommandType
= CommandType::COMMAND
;
347 // first clear the tables and columns
348 clearCurrentCollections();
349 // now set the new one
350 setQuery_Impl(command
);
351 m_sOriginal
= command
;
353 // reset the additive iterator to the same statement
354 parseAndCheck_throwError( m_aSqlParser
, m_sOriginal
, m_aAdditiveIterator
, *this );
356 // we have no "elementary" parts anymore (means filter/groupby/having/order clauses)
357 for ( SQLPart eLoopParts
= Where
; eLoopParts
!= SQLPartCount
; incSQLPart( eLoopParts
) )
358 m_aElementaryParts
[ eLoopParts
].clear();
361 void SAL_CALL
OSingleSelectQueryComposer::setCommand( const OUString
& Command
,sal_Int32 _nCommandType
)
364 switch(_nCommandType
)
366 case CommandType::COMMAND
:
367 setElementaryQuery(Command
);
369 case CommandType::TABLE
:
370 if ( m_xConnectionTables
->hasByName(Command
) )
372 sSQL
.append("SELECT * FROM ");
373 Reference
< XPropertySet
> xTable
;
376 m_xConnectionTables
->getByName( Command
) >>= xTable
;
378 catch(const WrappedTargetException
& e
)
381 if ( e
.TargetException
>>= e2
)
386 DBG_UNHANDLED_EXCEPTION("dbaccess");
389 sSQL
.append(dbtools::composeTableNameForSelect(m_xConnection
,xTable
));
393 OUString
sMessage( DBA_RES( RID_STR_TABLE_DOES_NOT_EXIST
) );
394 throwGenericSQLException(sMessage
.replaceAll( "$table$", Command
),*this);
397 case CommandType::QUERY
:
398 if ( m_xConnectionQueries
->hasByName(Command
) )
401 Reference
<XPropertySet
> xQuery(m_xConnectionQueries
->getByName(Command
),UNO_QUERY
);
403 xQuery
->getPropertyValue(PROPERTY_COMMAND
) >>= sCommand
;
404 sSQL
.append(sCommand
);
408 OUString
sMessage( DBA_RES( RID_STR_QUERY_DOES_NOT_EXIST
) );
409 throwGenericSQLException(sMessage
.replaceAll( "$table$", Command
),*this);
416 ::connectivity::checkDisposed(OSubComponent::rBHelper
.bDisposed
);
418 ::osl::MutexGuard
aGuard( m_aMutex
);
419 m_nCommandType
= _nCommandType
;
420 m_sCommand
= Command
;
421 // first clear the tables and columns
422 clearCurrentCollections();
423 // now set the new one
424 OUString sCommand
= sSQL
.makeStringAndClear();
425 setElementaryQuery(sCommand
);
426 m_sOriginal
= sCommand
;
429 void OSingleSelectQueryComposer::setQuery_Impl( const OUString
& command
)
432 parseAndCheck_throwError( m_aSqlParser
, command
, m_aSqlIterator
, *this );
434 // strip it from all clauses, to have the pure SELECT statement
435 m_aPureSelectSQL
= getPureSelectStatement( m_aSqlIterator
.getParseTree(), m_xConnection
);
441 Sequence
< Sequence
< PropertyValue
> > SAL_CALL
OSingleSelectQueryComposer::getStructuredHavingClause( )
443 TGetParseNode
F_tmp(&OSQLParseTreeIterator::getSimpleHavingTree
);
444 return getStructuredCondition(F_tmp
);
447 Sequence
< Sequence
< PropertyValue
> > SAL_CALL
OSingleSelectQueryComposer::getStructuredFilter( )
449 TGetParseNode
F_tmp(&OSQLParseTreeIterator::getSimpleWhereTree
);
450 return getStructuredCondition(F_tmp
);
453 void SAL_CALL
OSingleSelectQueryComposer::appendHavingClauseByColumn( const Reference
< XPropertySet
>& column
, sal_Bool andCriteria
,sal_Int32 filterOperator
)
455 auto F_tmp
= std::mem_fn(&OSingleSelectQueryComposer::implSetHavingClause
);
456 setConditionByColumn(column
,andCriteria
,F_tmp
,filterOperator
);
459 void SAL_CALL
OSingleSelectQueryComposer::appendFilterByColumn( const Reference
< XPropertySet
>& column
, sal_Bool andCriteria
,sal_Int32 filterOperator
)
461 auto F_tmp
= std::mem_fn(&OSingleSelectQueryComposer::implSetFilter
);
462 setConditionByColumn(column
,andCriteria
,F_tmp
,filterOperator
);
465 OUString
OSingleSelectQueryComposer::impl_getColumnRealName_throw(const Reference
< XPropertySet
>& column
, bool bGroupBy
)
467 ::connectivity::checkDisposed(OSubComponent::rBHelper
.bDisposed
);
471 || !m_aCurrentColumns
[SelectColumns
]
472 || !column
->getPropertySetInfo()->hasPropertyByName(PROPERTY_NAME
)
475 OUString
sError(DBA_RES(RID_STR_COLUMN_UNKNOWN_PROP
));
476 SQLException
aErr(sError
.replaceAll("%value", PROPERTY_NAME
),*this,SQLSTATE_GENERAL
,1000,Any() );
477 throw SQLException(DBA_RES(RID_STR_COLUMN_NOT_VALID
),*this,SQLSTATE_GENERAL
,1000,Any(aErr
) );
480 OUString aName
, aNewName
;
481 column
->getPropertyValue(PROPERTY_NAME
) >>= aName
;
484 !m_xMetaData
->supportsGroupByUnrelated() &&
485 m_aCurrentColumns
[SelectColumns
] &&
486 !m_aCurrentColumns
[SelectColumns
]->hasByName(aName
) )
488 OUString
sError(DBA_RES(RID_STR_COLUMN_MUST_VISIBLE
));
489 throw SQLException(sError
.replaceAll("%name", aName
),*this,SQLSTATE_GENERAL
,1000,Any() );
492 OUString aQuote
= m_xMetaData
->getIdentifierQuoteString();
493 if ( m_aCurrentColumns
[SelectColumns
]->hasByName(aName
) )
495 Reference
<XPropertySet
> xColumn
;
496 m_aCurrentColumns
[SelectColumns
]->getByName(aName
) >>= xColumn
;
497 OSL_ENSURE(xColumn
->getPropertySetInfo()->hasPropertyByName(PROPERTY_REALNAME
),"Property REALNAME not available!");
498 OSL_ENSURE(xColumn
->getPropertySetInfo()->hasPropertyByName(PROPERTY_TABLENAME
),"Property TABLENAME not available!");
499 OSL_ENSURE(xColumn
->getPropertySetInfo()->hasPropertyByName(u
"Function"_ustr
),"Property FUNCTION not available!");
501 OUString sRealName
, sTableName
;
502 xColumn
->getPropertyValue(PROPERTY_REALNAME
) >>= sRealName
;
503 xColumn
->getPropertyValue(PROPERTY_TABLENAME
) >>= sTableName
;
504 bool bFunction
= false;
505 xColumn
->getPropertyValue(u
"Function"_ustr
) >>= bFunction
;
506 if ( sRealName
== aName
)
512 if(sTableName
.indexOf('.') != -1)
514 OUString aCatalog
,aSchema
,aTable
;
515 ::dbtools::qualifiedNameComponents(m_xMetaData
,sTableName
,aCatalog
,aSchema
,aTable
,::dbtools::EComposeRule::InDataManipulation
);
516 sTableName
= ::dbtools::composeTableName( m_xMetaData
, aCatalog
, aSchema
, aTable
, true, ::dbtools::EComposeRule::InDataManipulation
);
518 else if (!sTableName
.isEmpty())
519 sTableName
= ::dbtools::quoteName(aQuote
,sTableName
);
521 if(sTableName
.isEmpty())
522 aNewName
= ::dbtools::quoteName(aQuote
,sRealName
);
524 aNewName
= sTableName
+ "." + ::dbtools::quoteName(aQuote
,sRealName
);
528 aNewName
= ::dbtools::quoteName(aQuote
,aName
);
531 aNewName
= getTableAlias(column
) + ::dbtools::quoteName(aQuote
,aName
);
535 OUString
OSingleSelectQueryComposer::impl_getColumnNameOrderBy_throw(const Reference
< XPropertySet
>& column
)
537 ::connectivity::checkDisposed(OSubComponent::rBHelper
.bDisposed
);
541 || !m_aCurrentColumns
[SelectColumns
]
542 || !column
->getPropertySetInfo()->hasPropertyByName(PROPERTY_NAME
)
545 OUString
sError(DBA_RES(RID_STR_COLUMN_UNKNOWN_PROP
));
546 SQLException
aErr(sError
.replaceAll("%value", PROPERTY_NAME
),*this,SQLSTATE_GENERAL
,1000,Any() );
547 throw SQLException(DBA_RES(RID_STR_COLUMN_NOT_VALID
),*this,SQLSTATE_GENERAL
,1000,Any(aErr
) );
551 column
->getPropertyValue(PROPERTY_NAME
) >>= aName
;
553 const OUString aQuote
= m_xMetaData
->getIdentifierQuoteString();
555 if ( m_aCurrentColumns
[SelectColumns
] &&
556 m_aCurrentColumns
[SelectColumns
]->hasByName(aName
) )
558 // It is a column from the SELECT list, use it as such.
559 return ::dbtools::quoteName(aQuote
,aName
);
562 // Nope, it is an unrelated column.
563 // Is that supported?
564 if ( !m_xMetaData
->supportsOrderByUnrelated() )
566 OUString
sError(DBA_RES(RID_STR_COLUMN_MUST_VISIBLE
));
567 throw SQLException(sError
.replaceAll("%name", aName
),*this,SQLSTATE_GENERAL
,1000,Any() );
570 // We need to refer to it by its "real" name, that is by schemaName.tableName.columnNameInTable
571 return impl_getColumnRealName_throw(column
, false);
574 void SAL_CALL
OSingleSelectQueryComposer::appendOrderByColumn( const Reference
< XPropertySet
>& column
, sal_Bool ascending
)
576 ::osl::MutexGuard
aGuard( m_aMutex
);
577 OUString
sColumnName( impl_getColumnNameOrderBy_throw(column
) );
578 OUString sOrder
= getOrder();
579 if ( !(sOrder
.isEmpty() || sColumnName
.isEmpty()) )
581 sOrder
+= sColumnName
;
582 if ( !(ascending
|| sColumnName
.isEmpty()) )
588 void SAL_CALL
OSingleSelectQueryComposer::appendGroupByColumn( const Reference
< XPropertySet
>& column
)
590 ::osl::MutexGuard
aGuard( m_aMutex
);
591 OUString
sColumnName( impl_getColumnRealName_throw(column
, true) );
592 OrderCreator aComposer
;
593 aComposer
.append( getGroup() );
594 aComposer
.append( sColumnName
);
595 setGroup( aComposer
.getComposedAndClear() );
598 OUString
OSingleSelectQueryComposer::composeStatementFromParts( const std::vector
< OUString
>& _rParts
)
600 OSL_ENSURE( _rParts
.size() == size_t(SQLPartCount
), "OSingleSelectQueryComposer::composeStatementFromParts: invalid parts array!" );
602 OUStringBuffer
aSql( m_aPureSelectSQL
);
603 for ( SQLPart eLoopParts
= Where
; eLoopParts
!= SQLPartCount
; incSQLPart( eLoopParts
) )
604 if ( !_rParts
[ eLoopParts
].isEmpty() )
606 aSql
.append( getKeyword( eLoopParts
) );
607 aSql
.append( _rParts
[ eLoopParts
] );
610 return aSql
.makeStringAndClear();
613 OUString SAL_CALL
OSingleSelectQueryComposer::getElementaryQuery()
615 return composeStatementFromParts( m_aElementaryParts
);
618 void SAL_CALL
OSingleSelectQueryComposer::setElementaryQuery( const OUString
& _rElementary
)
620 ::connectivity::checkDisposed(OSubComponent::rBHelper
.bDisposed
);
621 ::osl::MutexGuard
aGuard( m_aMutex
);
623 // remember the 4 current "additive" clauses
624 std::vector
< OUString
> aAdditiveClauses( SQLPartCount
);
625 for ( SQLPart eLoopParts
= Where
; eLoopParts
!= SQLPartCount
; incSQLPart( eLoopParts
) )
626 aAdditiveClauses
[ eLoopParts
] = getSQLPart( eLoopParts
, m_aAdditiveIterator
, false );
628 // clear the tables and columns
629 clearCurrentCollections();
630 // set and parse the new query
631 setQuery_Impl( _rElementary
);
633 // get the 4 elementary parts of the statement
634 for ( SQLPart eLoopParts
= Where
; eLoopParts
!= SQLPartCount
; incSQLPart( eLoopParts
) )
635 m_aElementaryParts
[ eLoopParts
] = getSQLPart( eLoopParts
, m_aSqlIterator
, false );
637 // reset the AdditiveIterator: m_aPureSelectSQL may have changed
640 parseAndCheck_throwError( m_aSqlParser
, composeStatementFromParts( aAdditiveClauses
), m_aAdditiveIterator
, *this );
642 catch( const Exception
& )
644 DBG_UNHANDLED_EXCEPTION("dbaccess");
645 SAL_WARN("dbaccess", "OSingleSelectQueryComposer::setElementaryQuery: there should be no error anymore for the additive statement!" );
646 // every part of the additive statement should have passed other tests already, and should not
647 // be able to cause any errors ... me thinks
653 OUString
getComposedClause( const OUString
& _rElementaryClause
, const OUString
& _rAdditionalClause
,
654 TokenComposer
& _rComposer
, std::u16string_view _rKeyword
)
657 _rComposer
.append( _rElementaryClause
);
658 _rComposer
.append( _rAdditionalClause
);
659 OUString sComposed
= _rComposer
.getComposedAndClear();
660 if ( !sComposed
.isEmpty() )
661 sComposed
= _rKeyword
+ sComposed
;
666 void OSingleSelectQueryComposer::setSingleAdditiveClause( SQLPart _ePart
, const OUString
& _rClause
)
668 ::connectivity::checkDisposed(OSubComponent::rBHelper
.bDisposed
);
669 ::osl::MutexGuard
aGuard( m_aMutex
);
671 // if nothing is changed, do nothing
672 if ( getSQLPart( _ePart
, m_aAdditiveIterator
, false ) == _rClause
)
675 // collect the 4 single parts as they're currently set
676 std::vector
< OUString
> aClauses
;
677 aClauses
.reserve( size_t(SQLPartCount
) );
678 for ( SQLPart eLoopParts
= Where
; eLoopParts
!= SQLPartCount
; incSQLPart( eLoopParts
) )
679 aClauses
.push_back( getSQLPart( eLoopParts
, m_aSqlIterator
, true ) );
681 // overwrite the one part in question here
682 std::unique_ptr
< TokenComposer
> pComposer
;
683 if ( ( _ePart
== Where
) || ( _ePart
== Having
) )
684 pComposer
.reset( new FilterCreator
);
686 pComposer
.reset( new OrderCreator
);
687 aClauses
[ _ePart
] = getComposedClause( m_aElementaryParts
[ _ePart
], _rClause
,
688 *pComposer
, getKeyword( _ePart
) );
690 // construct the complete statement
691 OUStringBuffer
aSql(m_aPureSelectSQL
);
692 for ( SQLPart eLoopParts
= Where
; eLoopParts
!= SQLPartCount
; incSQLPart( eLoopParts
) )
693 aSql
.append(aClauses
[ eLoopParts
]);
696 setQuery_Impl(aSql
.makeStringAndClear());
698 // clear column collections which (might) have changed
699 clearColumns( ParameterColumns
);
700 if ( _ePart
== Order
)
701 clearColumns( OrderColumns
);
702 else if ( _ePart
== Group
)
703 clearColumns( GroupByColumns
);
705 // also, since the "additive filter" change, we need to rebuild our "additive" statement
706 aSql
= m_aPureSelectSQL
;
707 // again, first get all the old additive parts
708 for ( SQLPart eLoopParts
= Where
; eLoopParts
!= SQLPartCount
; incSQLPart( eLoopParts
) )
709 aClauses
[ eLoopParts
] = getSQLPart( eLoopParts
, m_aAdditiveIterator
, true );
710 // then overwrite the one in question
711 aClauses
[ _ePart
] = getComposedClause( OUString(), _rClause
, *pComposer
, getKeyword( _ePart
) );
712 // and parse it, so that m_aAdditiveIterator is up to date
713 for ( SQLPart eLoopParts
= Where
; eLoopParts
!= SQLPartCount
; incSQLPart( eLoopParts
) )
714 aSql
.append(aClauses
[ eLoopParts
]);
717 parseAndCheck_throwError( m_aSqlParser
, aSql
.makeStringAndClear(), m_aAdditiveIterator
, *this );
719 catch( const Exception
& )
721 SAL_WARN("dbaccess", "OSingleSelectQueryComposer::setSingleAdditiveClause: there should be no error anymore for the additive statement!" );
722 // every part of the additive statement should have passed other tests already, and should not
723 // be able to cause any errors ... me thinks
727 void SAL_CALL
OSingleSelectQueryComposer::setFilter( const OUString
& filter
)
729 setSingleAdditiveClause( Where
, filter
);
732 void SAL_CALL
OSingleSelectQueryComposer::setOrder( const OUString
& order
)
734 setSingleAdditiveClause( Order
, order
);
737 void SAL_CALL
OSingleSelectQueryComposer::setGroup( const OUString
& group
)
739 setSingleAdditiveClause( Group
, group
);
742 void SAL_CALL
OSingleSelectQueryComposer::setHavingClause( const OUString
& filter
)
744 setSingleAdditiveClause( Having
, filter
);
748 Reference
< XNameAccess
> SAL_CALL
OSingleSelectQueryComposer::getTables( )
750 ::connectivity::checkDisposed(OSubComponent::rBHelper
.bDisposed
);
752 ::osl::MutexGuard
aGuard( m_aMutex
);
755 const OSQLTables
& aTables
= m_aSqlIterator
.getTables();
756 std::vector
< OUString
> aNames
;
757 for (auto const& elem
: aTables
)
758 aNames
.push_back(elem
.first
);
760 m_pTables
.reset( new OPrivateTables(aTables
,m_xMetaData
->supportsMixedCaseQuotedIdentifiers(),*this,m_aMutex
,std::move(aNames
)) );
763 return m_pTables
.get();
767 Reference
< XNameAccess
> SAL_CALL
OSingleSelectQueryComposer::getColumns( )
769 ::connectivity::checkDisposed(OSubComponent::rBHelper
.bDisposed
);
770 ::osl::MutexGuard
aGuard( m_aMutex
);
771 if ( !!m_aCurrentColumns
[SelectColumns
] )
772 return m_aCurrentColumns
[SelectColumns
].get();
774 std::vector
< OUString
> aNames
;
775 ::rtl::Reference
< OSQLColumns
> aSelectColumns
;
777 Reference
< XNameAccess
> xQueryColumns
;
778 if ( m_nCommandType
== CommandType::QUERY
)
780 Reference
<XColumnsSupplier
> xSup(m_xConnectionQueries
->getByName(m_sCommand
),UNO_QUERY
);
782 xQueryColumns
= xSup
->getColumns();
789 SharedUNOComponent
< XStatement
, DisposableComponent
> xStatement
;
790 SharedUNOComponent
< XPreparedStatement
, DisposableComponent
> xPreparedStatement
;
792 bCase
= m_xMetaData
->supportsMixedCaseQuotedIdentifiers();
793 aSelectColumns
= m_aSqlIterator
.getSelectColumns();
795 OUStringBuffer
aSQL( m_aPureSelectSQL
+ STR_WHERE
+ " ( 0 = 1 )");
797 // preserve the original WHERE clause
799 OUString sOriginalWhereClause
= getSQLPart( Where
, m_aSqlIterator
, false );
800 if ( !sOriginalWhereClause
.isEmpty() )
802 aSQL
.append( " AND ( " + sOriginalWhereClause
+ " ) " );
805 OUString sGroupBy
= getSQLPart( Group
, m_aSqlIterator
, true );
806 if ( !sGroupBy
.isEmpty() )
807 aSQL
.append( sGroupBy
);
809 OUString
sSQL( aSQL
.makeStringAndClear() );
810 // normalize the statement so that it doesn't contain any application-level features anymore
812 const std::unique_ptr
< OSQLParseNode
> pStatementTree( m_aSqlParser
.parseTree( sError
, sSQL
) );
813 OSL_ENSURE(pStatementTree
, "OSingleSelectQueryComposer::getColumns: could not parse the "
814 "column retrieval statement!");
816 if ( !pStatementTree
->parseNodeToExecutableStatement( sSQL
, m_xConnection
, m_aSqlParser
, nullptr ) )
819 Reference
< XResultSetMetaData
> xResultSetMeta
;
820 Reference
< XResultSetMetaDataSupplier
> xResMetaDataSup
;
823 xPreparedStatement
.set( m_xConnection
->prepareStatement( sSQL
), UNO_QUERY_THROW
);
824 xResMetaDataSup
.set( xPreparedStatement
, UNO_QUERY_THROW
);
825 xResultSetMeta
.set( xResMetaDataSup
->getMetaData(), UNO_SET_THROW
);
827 catch( const Exception
& ) { }
829 if ( !xResultSetMeta
.is() && xPreparedStatement
.is() )
833 //@see issue http://qa.openoffice.org/issues/show_bug.cgi?id=110111
834 // access returns a different order of column names when executing select * from
835 // and asking the columns from the metadata.
836 Reference
< XParameters
> xParameters( xPreparedStatement
, UNO_QUERY_THROW
);
837 Reference
< XIndexAccess
> xPara
= getParameters();
838 for(sal_Int32 i
= 1;i
<= xPara
->getCount();++i
)
839 xParameters
->setNull(i
,DataType::VARCHAR
);
840 xResMetaDataSup
.set(xPreparedStatement
->executeQuery(), UNO_QUERY_THROW
);
841 xResultSetMeta
.set( xResMetaDataSup
->getMetaData(), UNO_SET_THROW
);
843 catch( const Exception
& ) { }
846 if ( !xResultSetMeta
.is() )
848 xStatement
.reset( Reference
< XStatement
>( m_xConnection
->createStatement(), UNO_SET_THROW
) );
849 Reference
< XPropertySet
> xStatementProps( xStatement
, UNO_QUERY_THROW
);
850 try { xStatementProps
->setPropertyValue( PROPERTY_ESCAPE_PROCESSING
, Any( false ) ); }
851 catch ( const Exception
& ) { DBG_UNHANDLED_EXCEPTION("dbaccess"); }
852 xResMetaDataSup
.set( xStatement
->executeQuery( sSQL
), UNO_QUERY_THROW
);
853 xResultSetMeta
.set( xResMetaDataSup
->getMetaData(), UNO_SET_THROW
);
855 if (xResultSetMeta
.is())
857 SAL_WARN("dbaccess", "OSingleSelectQueryComposer::getColumns failed to get xResultSetMeta from executed PreparedStatement, but got it from 'no escape processing' statement. SQL command:\n\t" << sSQL
);
861 if ( aSelectColumns
->empty() )
863 // This is a valid case. If we can syntactically parse the query, but not semantically
864 // (e.g. because it is based on a table we do not know), then there will be no SelectColumns
865 aSelectColumns
= ::connectivity::parse::OParseColumn::createColumnsForResultSet( xResultSetMeta
, m_xMetaData
,xQueryColumns
);
869 const ::comphelper::UStringMixEqual
aCaseCompare( bCase
);
870 std::set
< size_t > aUsedSelectColumns
;
871 ::connectivity::parse::OParseColumn::StringMap aColumnNames
;
873 sal_Int32 nCount
= xResultSetMeta
->getColumnCount();
874 OSL_ENSURE( static_cast<size_t>(nCount
) == aSelectColumns
->size(), "OSingleSelectQueryComposer::getColumns: inconsistent column counts, this might result in wrong columns!" );
875 for(sal_Int32 i
=1;i
<=nCount
;++i
)
877 OUString sColumnName
= xResultSetMeta
->getColumnName(i
);
878 OUString sColumnLabel
;
879 if ( xQueryColumns
.is() && xQueryColumns
->hasByName(sColumnName
) )
881 Reference
<XPropertySet
> xQueryColumn(xQueryColumns
->getByName(sColumnName
),UNO_QUERY_THROW
);
882 xQueryColumn
->getPropertyValue(PROPERTY_LABEL
) >>= sColumnLabel
;
885 sColumnLabel
= xResultSetMeta
->getColumnLabel(i
);
887 OSQLColumns::Vector::const_iterator aFind
= ::connectivity::find(aSelectColumns
->begin(),aSelectColumns
->end(),sColumnLabel
,aCaseCompare
);
888 size_t nFoundSelectColumnPos
= aFind
- aSelectColumns
->begin();
889 if ( aFind
!= aSelectColumns
->end() )
891 if ( aUsedSelectColumns
.find( nFoundSelectColumnPos
) != aUsedSelectColumns
.end() )
892 { // we found a column name which exists twice
893 // so we start after the first found
896 aFind
= ::connectivity::findRealName(++aFind
,aSelectColumns
->end(),sColumnName
,aCaseCompare
);
897 nFoundSelectColumnPos
= aFind
- aSelectColumns
->begin();
899 while ( ( aUsedSelectColumns
.find( nFoundSelectColumnPos
) != aUsedSelectColumns
.end() )
900 && ( aFind
!= aSelectColumns
->end() )
903 if ( aFind
!= aSelectColumns
->end() )
905 (*aFind
)->getPropertyValue(PROPERTY_NAME
) >>= sColumnName
;
906 aUsedSelectColumns
.insert( nFoundSelectColumnPos
);
907 aNames
.push_back(sColumnName
);
915 OSQLColumns::Vector::const_iterator aRealFind
= ::connectivity::findRealName(
916 aSelectColumns
->begin(), aSelectColumns
->end(), sColumnName
, aCaseCompare
);
918 if ( i
> static_cast< sal_Int32
>( aSelectColumns
->size() ) )
920 aSelectColumns
->emplace_back(::connectivity::parse::OParseColumn::createColumnForResultSet( xResultSetMeta
, m_xMetaData
, i
,aColumnNames
)
922 OSL_ENSURE( aSelectColumns
->size() == static_cast<size_t>(i
), "OSingleSelectQueryComposer::getColumns: inconsistency!" );
924 else if ( aRealFind
== aSelectColumns
->end() )
926 // we can now only look if we found it under the realname property
927 // here we have to make the assumption that the position is correct
928 OSQLColumns::Vector::const_iterator aFind2
= aSelectColumns
->begin() + i
-1;
929 const Reference
<XPropertySet
>& xProp
= *aFind2
;
930 if ( !xProp
.is() || !xProp
->getPropertySetInfo()->hasPropertyByName( PROPERTY_REALNAME
) )
933 rtl::Reference
<::connectivity::parse::OParseColumn
> pColumn
= new ::connectivity::parse::OParseColumn(xProp
,bCase
);
934 pColumn
->setFunction(::comphelper::getBOOL(xProp
->getPropertyValue(u
"Function"_ustr
)));
935 pColumn
->setAggregateFunction(::comphelper::getBOOL(xProp
->getPropertyValue(u
"AggregateFunction"_ustr
)));
938 xProp
->getPropertyValue(PROPERTY_REALNAME
) >>= sRealName
;
939 if ( sColumnName
.isEmpty() )
940 xProp
->getPropertyValue(PROPERTY_NAME
) >>= sColumnName
;
943 while ( std::any_of(aNames
.begin(),aNames
.end(),
944 [&aCaseCompare
, &sColumnName
](const OUString
& lhs
)
945 { return aCaseCompare(lhs
, sColumnName
); } ) )
947 sColumnName
+= OUString::number(++j
);
950 pColumn
->setName(sColumnName
);
951 pColumn
->setRealName(sRealName
);
952 pColumn
->setTableName(::comphelper::getString(xProp
->getPropertyValue(PROPERTY_TABLENAME
)));
954 (*aSelectColumns
)[i
-1] = pColumn
;
959 aUsedSelectColumns
.insert( static_cast<size_t>(i
- 1) );
960 aNames
.push_back( sColumnName
);
963 catch(const Exception
&)
969 bool bMissingSomeColumnLabels
= !aNames
.empty() && aNames
.size() != aSelectColumns
->size();
970 SAL_WARN_IF(bMissingSomeColumnLabels
, "dbaccess", "We have column labels for *some* columns but not all");
971 //^^this happens in the evolution address book where we have real column names of e.g.
972 //first_name, second_name and city. On parsing via
973 //OSQLParseTreeIterator::appendColumns it creates some labels using those real names
974 //but the evo address book gives them proper labels of First Name, Second Name and City
975 //the munge means that here we have e.g. just "City" as a label because it matches
977 //This is all a horrible mess
978 if (bMissingSomeColumnLabels
)
981 if ( aNames
.empty() )
982 m_aCurrentColumns
[ SelectColumns
] = OPrivateColumns::createWithIntrinsicNames( aSelectColumns
, bCase
, *this, m_aMutex
);
984 m_aCurrentColumns
[ SelectColumns
].reset( new OPrivateColumns( aSelectColumns
, bCase
, *this, m_aMutex
, aNames
) );
986 return m_aCurrentColumns
[SelectColumns
].get();
989 bool OSingleSelectQueryComposer::setORCriteria(OSQLParseNode
const * pCondition
, OSQLParseTreeIterator
& _rIterator
,
990 std::vector
< std::vector
< PropertyValue
> >& rFilters
, const Reference
< css::util::XNumberFormatter
> & xFormatter
) const
992 // Round brackets around the expression
993 if (pCondition
->count() == 3 &&
994 SQL_ISPUNCTUATION(pCondition
->getChild(0),"(") &&
995 SQL_ISPUNCTUATION(pCondition
->getChild(2),")"))
997 return setORCriteria(pCondition
->getChild(1), _rIterator
, rFilters
, xFormatter
);
999 // OR logic expression
1000 // a searchcondition can only look like this: search_condition SQL_TOKEN_OR boolean_term
1001 else if (SQL_ISRULE(pCondition
,search_condition
))
1003 bool bResult
= true;
1004 for (int i
= 0; bResult
&& i
< 3; i
+=2)
1006 // Is the first element a OR logic expression again?
1007 // Then descend recursively ...
1008 if (SQL_ISRULE(pCondition
->getChild(i
),search_condition
))
1009 bResult
= setORCriteria(pCondition
->getChild(i
), _rIterator
, rFilters
, xFormatter
);
1012 rFilters
.emplace_back();
1013 bResult
= setANDCriteria(pCondition
->getChild(i
), _rIterator
, rFilters
[rFilters
.size() - 1], xFormatter
);
1020 rFilters
.emplace_back();
1021 return setANDCriteria(pCondition
, _rIterator
, rFilters
[rFilters
.size() - 1], xFormatter
);
1025 bool OSingleSelectQueryComposer::setANDCriteria( OSQLParseNode
const * pCondition
,
1026 OSQLParseTreeIterator
& _rIterator
, std::vector
< PropertyValue
>& rFilter
, const Reference
< XNumberFormatter
> & xFormatter
) const
1029 if (SQL_ISRULE(pCondition
,boolean_primary
))
1031 // this should not occur
1032 SAL_WARN("dbaccess","boolean_primary in And-Criteria");
1035 // The first element is an AND logical expression again
1036 else if ( SQL_ISRULE(pCondition
,boolean_term
) && pCondition
->count() == 3 )
1038 return setANDCriteria(pCondition
->getChild(0), _rIterator
, rFilter
, xFormatter
) &&
1039 setANDCriteria(pCondition
->getChild(2), _rIterator
, rFilter
, xFormatter
);
1041 else if (SQL_ISRULE(pCondition
, comparison_predicate
))
1043 return setComparisonPredicate(pCondition
,_rIterator
,rFilter
,xFormatter
);
1045 else if (SQL_ISRULE(pCondition
,like_predicate
))
1047 return setLikePredicate(pCondition
,_rIterator
,rFilter
,xFormatter
);
1049 else if (SQL_ISRULE(pCondition
,test_for_null
) ||
1050 SQL_ISRULE(pCondition
,in_predicate
) ||
1051 SQL_ISRULE(pCondition
,all_or_any_predicate
) ||
1052 SQL_ISRULE(pCondition
,between_predicate
))
1054 if (SQL_ISRULE(pCondition
->getChild(0), column_ref
))
1056 PropertyValue aItem
;
1058 OUString aColumnName
;
1060 pCondition
->parseNodeToStr( aValue
, m_xConnection
);
1061 pCondition
->getChild(0)->parseNodeToStr( aColumnName
, m_xConnection
);
1063 // don't display the column name
1064 aValue
= aValue
.copy(aColumnName
.getLength());
1065 aValue
= aValue
.trim();
1067 aItem
.Name
= getColumnName(pCondition
->getChild(0),_rIterator
);
1068 aItem
.Value
<<= aValue
;
1069 aItem
.Handle
= 0; // just to know that this is not one the known ones
1070 if ( SQL_ISRULE(pCondition
,like_predicate
) )
1072 if ( SQL_ISTOKEN(pCondition
->getChild(1)->getChild(0),NOT
) )
1073 aItem
.Handle
= SQLFilterOperator::NOT_LIKE
;
1075 aItem
.Handle
= SQLFilterOperator::LIKE
;
1077 else if (SQL_ISRULE(pCondition
,test_for_null
))
1079 if (SQL_ISTOKEN(pCondition
->getChild(1)->getChild(1),NOT
) )
1080 aItem
.Handle
= SQLFilterOperator::NOT_SQLNULL
;
1082 aItem
.Handle
= SQLFilterOperator::SQLNULL
;
1084 else if (SQL_ISRULE(pCondition
,in_predicate
))
1086 SAL_WARN("dbaccess", "OSingleSelectQueryComposer::setANDCriteria: in_predicate not implemented!" );
1088 else if (SQL_ISRULE(pCondition
,all_or_any_predicate
))
1090 SAL_WARN("dbaccess", "OSingleSelectQueryComposer::setANDCriteria: all_or_any_predicate not implemented!" );
1092 else if (SQL_ISRULE(pCondition
,between_predicate
))
1094 SAL_WARN("dbaccess", "OSingleSelectQueryComposer::setANDCriteria: between_predicate not implemented!" );
1097 rFilter
.push_back(aItem
);
1102 else if (SQL_ISRULE(pCondition
,existence_test
) ||
1103 SQL_ISRULE(pCondition
,unique_test
))
1105 // this couldn't be handled here, too complex
1106 // as we need a field name
1115 sal_Int32
OSingleSelectQueryComposer::getPredicateType(OSQLParseNode
const * _pPredicate
)
1117 sal_Int32 nPredicate
= SQLFilterOperator::EQUAL
;
1118 switch (_pPredicate
->getNodeType())
1120 case SQLNodeType::Equal
:
1121 nPredicate
= SQLFilterOperator::EQUAL
;
1123 case SQLNodeType::NotEqual
:
1124 nPredicate
= SQLFilterOperator::NOT_EQUAL
;
1126 case SQLNodeType::Less
:
1127 nPredicate
= SQLFilterOperator::LESS
;
1129 case SQLNodeType::LessEq
:
1130 nPredicate
= SQLFilterOperator::LESS_EQUAL
;
1132 case SQLNodeType::Great
:
1133 nPredicate
= SQLFilterOperator::GREATER
;
1135 case SQLNodeType::GreatEq
:
1136 nPredicate
= SQLFilterOperator::GREATER_EQUAL
;
1139 SAL_WARN("dbaccess","Wrong NodeType!");
1144 bool OSingleSelectQueryComposer::setLikePredicate(OSQLParseNode
const * pCondition
, OSQLParseTreeIterator
const & _rIterator
,
1145 std::vector
< PropertyValue
>& rFilter
, const Reference
< css::util::XNumberFormatter
> & xFormatter
) const
1147 OSL_ENSURE(SQL_ISRULE(pCondition
, like_predicate
),"setLikePredicate: pCondition is not a LikePredicate");
1149 assert(pCondition
->count() == 2);
1150 OSQLParseNode
const *pRowValue
= pCondition
->getChild(0);
1151 OSQLParseNode
const *pPart2
= pCondition
->getChild(1);
1153 PropertyValue aItem
;
1154 if ( SQL_ISTOKEN(pPart2
->getChild(0),NOT
) )
1155 aItem
.Handle
= SQLFilterOperator::NOT_LIKE
;
1157 aItem
.Handle
= SQLFilterOperator::LIKE
;
1159 if (SQL_ISRULE(pRowValue
, column_ref
))
1163 // skip (optional "NOT") and "LIKE"
1164 for (size_t i
=2; i
< pPart2
->count(); i
++)
1166 pPart2
->getChild(i
)->parseNodeToPredicateStr(
1167 aValue
, m_xConnection
, xFormatter
, m_aLocale
, m_sDecimalSep
);
1170 aItem
.Name
= getColumnName(pRowValue
,_rIterator
);
1171 aItem
.Value
<<= aValue
;
1172 rFilter
.push_back(aItem
);
1174 else if (SQL_ISRULE(pRowValue
, set_fct_spec
) ||
1175 SQL_ISRULE(pRowValue
, general_set_fct
))
1178 OUString aColumnName
;
1180 pPart2
->getChild(2)->parseNodeToPredicateStr(aValue
, m_xConnection
, xFormatter
, m_aLocale
, m_sDecimalSep
);
1181 pPart2
->getChild(3)->parseNodeToPredicateStr(aValue
, m_xConnection
, xFormatter
, m_aLocale
, m_sDecimalSep
);
1182 pRowValue
->parseNodeToPredicateStr( aColumnName
, m_xConnection
, xFormatter
, m_aLocale
, m_sDecimalSep
);
1184 aItem
.Name
= getColumnName(pRowValue
,_rIterator
);
1185 aItem
.Value
<<= aValue
;
1186 rFilter
.push_back(aItem
);
1188 else // Can only be an expression
1190 OUString aName
, aValue
;
1192 OSQLParseNode
const *pValue
= pPart2
->getChild(2);
1195 for (size_t i
=0;i
< pRowValue
->count();i
++)
1196 pRowValue
->getChild(i
)->parseNodeToPredicateStr( aName
, m_xConnection
, xFormatter
, m_aLocale
, m_sDecimalSep
);
1199 for(size_t i
=0;i
< pValue
->count();i
++)
1200 pValue
->getChild(i
)->parseNodeToPredicateStr(aValue
, m_xConnection
, xFormatter
, m_aLocale
, m_sDecimalSep
);
1201 pPart2
->getChild(3)->parseNodeToPredicateStr(aValue
, m_xConnection
, xFormatter
, m_aLocale
, m_sDecimalSep
);
1204 aItem
.Value
<<= aValue
;
1205 rFilter
.push_back(aItem
);
1210 bool OSingleSelectQueryComposer::setComparisonPredicate(OSQLParseNode
const * pCondition
, OSQLParseTreeIterator
const & _rIterator
,
1211 std::vector
< PropertyValue
>& rFilter
, const Reference
< css::util::XNumberFormatter
> & xFormatter
) const
1213 OSL_ENSURE(SQL_ISRULE(pCondition
, comparison_predicate
),"setComparisonPredicate: pCondition is not a ComparisonPredicate");
1214 if (SQL_ISRULE(pCondition
->getChild(0), column_ref
) ||
1215 SQL_ISRULE(pCondition
->getChild(pCondition
->count()-1), column_ref
))
1217 PropertyValue aItem
;
1220 if (SQL_ISRULE(pCondition
->getChild(0), column_ref
))
1225 aItem
.Handle
= getPredicateType(pCondition
->getChild(i
));
1227 // go forward - don't display the operator
1228 for (i
++;i
< pCondition
->count();i
++)
1229 pCondition
->getChild(i
)->parseNodeToPredicateStr(
1230 aValue
, m_xConnection
, xFormatter
, m_aLocale
, m_sDecimalSep
);
1232 else if (SQL_ISRULE(pCondition
->getChild(pCondition
->count()-1), column_ref
))
1234 nPos
= pCondition
->count()-1;
1236 sal_Int32 i
= pCondition
->count() - 2;
1237 switch (pCondition
->getChild(i
)->getNodeType())
1239 case SQLNodeType::Equal
:
1240 aItem
.Handle
= SQLFilterOperator::EQUAL
;
1242 case SQLNodeType::NotEqual
:
1243 aItem
.Handle
= SQLFilterOperator::NOT_EQUAL
;
1245 case SQLNodeType::Less
:
1246 // take the opposite as we change the order
1247 aItem
.Handle
= SQLFilterOperator::GREATER_EQUAL
;
1249 case SQLNodeType::LessEq
:
1250 // take the opposite as we change the order
1251 aItem
.Handle
= SQLFilterOperator::GREATER
;
1253 case SQLNodeType::Great
:
1254 // take the opposite as we change the order
1255 aItem
.Handle
= SQLFilterOperator::LESS_EQUAL
;
1257 case SQLNodeType::GreatEq
:
1258 // take the opposite as we change the order
1259 aItem
.Handle
= SQLFilterOperator::LESS
;
1265 // go backward - don't display the operator
1266 for (i
--; i
>= 0; i
--)
1267 pCondition
->getChild(i
)->parseNodeToPredicateStr(
1268 aValue
, m_xConnection
, xFormatter
, m_aLocale
, m_sDecimalSep
);
1273 aItem
.Name
= getColumnName(pCondition
->getChild(nPos
),_rIterator
);
1274 aItem
.Value
<<= aValue
;
1275 rFilter
.push_back(aItem
);
1277 else if (SQL_ISRULE(pCondition
->getChild(0), set_fct_spec
) ||
1278 SQL_ISRULE(pCondition
->getChild(0), general_set_fct
))
1280 PropertyValue aItem
;
1282 OUString aColumnName
;
1284 pCondition
->getChild(2)->parseNodeToPredicateStr(aValue
, m_xConnection
, xFormatter
, m_aLocale
, m_sDecimalSep
);
1285 pCondition
->getChild(0)->parseNodeToPredicateStr( aColumnName
, m_xConnection
, xFormatter
, m_aLocale
, m_sDecimalSep
);
1287 aItem
.Name
= getColumnName(pCondition
->getChild(0),_rIterator
);
1288 aItem
.Value
<<= aValue
;
1289 aItem
.Handle
= getPredicateType(pCondition
->getChild(1));
1290 rFilter
.push_back(aItem
);
1292 else // Can only be an expression
1294 PropertyValue aItem
;
1295 OUString aName
, aValue
;
1297 OSQLParseNode
*pLhs
= pCondition
->getChild(0);
1298 OSQLParseNode
*pRhs
= pCondition
->getChild(2);
1301 for (size_t i
=0;i
< pLhs
->count();i
++)
1302 pLhs
->getChild(i
)->parseNodeToPredicateStr( aName
, m_xConnection
, xFormatter
, m_aLocale
, m_sDecimalSep
);
1305 aItem
.Handle
= getPredicateType(pCondition
->getChild(1));
1306 for(size_t i
=0;i
< pRhs
->count();i
++)
1307 pRhs
->getChild(i
)->parseNodeToPredicateStr(aValue
, m_xConnection
, xFormatter
, m_aLocale
, m_sDecimalSep
);
1310 aItem
.Value
<<= aValue
;
1311 rFilter
.push_back(aItem
);
1316 // Functions for analysing SQL
1317 OUString
OSingleSelectQueryComposer::getColumnName( ::connectivity::OSQLParseNode
const * pColumnRef
, OSQLParseTreeIterator
const & _rIterator
)
1319 OUString aTableRange
, aColumnName
;
1320 _rIterator
.getColumnRange(pColumnRef
,aColumnName
,aTableRange
);
1324 OUString SAL_CALL
OSingleSelectQueryComposer::getFilter( )
1326 ::connectivity::checkDisposed(OSubComponent::rBHelper
.bDisposed
);
1327 ::osl::MutexGuard
aGuard( m_aMutex
);
1328 return getSQLPart(Where
,m_aAdditiveIterator
,false);
1331 OUString SAL_CALL
OSingleSelectQueryComposer::getOrder( )
1333 ::connectivity::checkDisposed(OSubComponent::rBHelper
.bDisposed
);
1334 ::osl::MutexGuard
aGuard( m_aMutex
);
1335 return getSQLPart(Order
,m_aAdditiveIterator
,false);
1338 OUString SAL_CALL
OSingleSelectQueryComposer::getGroup( )
1340 ::connectivity::checkDisposed(OSubComponent::rBHelper
.bDisposed
);
1341 ::osl::MutexGuard
aGuard( m_aMutex
);
1342 return getSQLPart(Group
,m_aAdditiveIterator
,false);
1345 OUString
OSingleSelectQueryComposer::getHavingClause()
1347 ::connectivity::checkDisposed(OSubComponent::rBHelper
.bDisposed
);
1348 ::osl::MutexGuard
aGuard( m_aMutex
);
1349 return getSQLPart(Having
,m_aAdditiveIterator
,false);
1352 OUString
OSingleSelectQueryComposer::getTableAlias(const Reference
< XPropertySet
>& column
) const
1355 if(m_pTables
&& m_pTables
->getCount() > 1)
1357 OUString aCatalog
,aSchema
,aTable
,aColumnName
;
1358 if(column
->getPropertySetInfo()->hasPropertyByName(PROPERTY_CATALOGNAME
))
1359 column
->getPropertyValue(PROPERTY_CATALOGNAME
) >>= aCatalog
;
1360 if(column
->getPropertySetInfo()->hasPropertyByName(PROPERTY_SCHEMANAME
))
1361 column
->getPropertyValue(PROPERTY_SCHEMANAME
) >>= aSchema
;
1362 if(column
->getPropertySetInfo()->hasPropertyByName(PROPERTY_TABLENAME
))
1363 column
->getPropertyValue(PROPERTY_TABLENAME
) >>= aTable
;
1364 column
->getPropertyValue(PROPERTY_NAME
) >>= aColumnName
;
1366 Sequence
< OUString
> aNames(m_pTables
->getElementNames());
1367 const OUString
* pBegin
= aNames
.begin();
1368 const OUString
* const pEnd
= aNames
.end();
1370 if(aTable
.isEmpty())
1371 { // we haven't found a table name, now we must search every table for this column
1372 for(;pBegin
!= pEnd
;++pBegin
)
1374 Reference
<XColumnsSupplier
> xColumnsSupp
;
1375 m_pTables
->getByName(*pBegin
) >>= xColumnsSupp
;
1377 if(xColumnsSupp
.is() && xColumnsSupp
->getColumns()->hasByName(aColumnName
))
1386 OUString aComposedName
= ::dbtools::composeTableName( m_xMetaData
, aCatalog
, aSchema
, aTable
, false, ::dbtools::EComposeRule::InDataManipulation
);
1388 // Is this the right case for the table name?
1389 // Else, look for it with different case, if applicable.
1391 if(!m_pTables
->hasByName(aComposedName
))
1393 ::comphelper::UStringMixLess
aTmp(m_aAdditiveIterator
.getTables().key_comp());
1394 ::comphelper::UStringMixEqual
aComp(aTmp
.isCaseSensitive());
1395 for(;pBegin
!= pEnd
;++pBegin
)
1397 Reference
<XPropertySet
> xTableProp
;
1398 m_pTables
->getByName(*pBegin
) >>= xTableProp
;
1399 OSL_ENSURE(xTableProp
.is(),"Table isn't a propertyset!");
1402 OUString aCatalog2
,aSchema2
,aTable2
;
1403 xTableProp
->getPropertyValue(PROPERTY_CATALOGNAME
) >>= aCatalog2
;
1404 xTableProp
->getPropertyValue(PROPERTY_SCHEMANAME
) >>= aSchema2
;
1405 xTableProp
->getPropertyValue(PROPERTY_NAME
) >>= aTable2
;
1406 if(aComp(aCatalog
,aCatalog2
) && aComp(aSchema
,aSchema2
) && aComp(aTable
,aTable2
))
1408 aCatalog
= aCatalog2
;
1419 sReturn
= ::dbtools::composeTableName( m_xMetaData
, aCatalog
, aSchema
, aTable
, true, ::dbtools::EComposeRule::InDataManipulation
) + ".";
1425 Reference
< XIndexAccess
> SAL_CALL
OSingleSelectQueryComposer::getParameters( )
1427 // now set the Parameters
1428 if ( !m_aCurrentColumns
[ParameterColumns
] )
1430 ::rtl::Reference
< OSQLColumns
> aCols
= m_aSqlIterator
.getParameters();
1431 std::vector
< OUString
> aNames
;
1432 for (auto const& elem
: *aCols
)
1433 aNames
.push_back(getString(elem
->getPropertyValue(PROPERTY_NAME
)));
1434 m_aCurrentColumns
[ParameterColumns
].reset( new OPrivateColumns(aCols
,m_xMetaData
->supportsMixedCaseQuotedIdentifiers(),*this,m_aMutex
,aNames
,true) );
1437 return m_aCurrentColumns
[ParameterColumns
].get();
1440 void OSingleSelectQueryComposer::clearColumns( const EColumnType _eType
)
1442 OPrivateColumns
* pColumns
= m_aCurrentColumns
[ _eType
].get();
1443 if ( pColumns
!= nullptr )
1445 pColumns
->disposing();
1446 m_aColumnsCollection
.push_back( std::move(m_aCurrentColumns
[ _eType
]) );
1450 void OSingleSelectQueryComposer::clearCurrentCollections()
1452 for (auto & currentColumn
: m_aCurrentColumns
)
1456 currentColumn
->disposing();
1457 m_aColumnsCollection
.push_back(std::move(currentColumn
));
1463 m_pTables
->disposing();
1464 m_aTablesCollection
.push_back(std::move(m_pTables
));
1468 Reference
< XIndexAccess
> OSingleSelectQueryComposer::setCurrentColumns( EColumnType _eType
,
1469 const ::rtl::Reference
< OSQLColumns
>& _rCols
)
1471 ::connectivity::checkDisposed(OSubComponent::rBHelper
.bDisposed
);
1473 ::osl::MutexGuard
aGuard( m_aMutex
);
1474 // now set the group columns
1475 if ( !m_aCurrentColumns
[_eType
] )
1477 std::vector
< OUString
> aNames
;
1478 for (auto const& elem
: *_rCols
)
1479 aNames
.push_back(getString(elem
->getPropertyValue(PROPERTY_NAME
)));
1480 m_aCurrentColumns
[_eType
].reset( new OPrivateColumns(_rCols
,m_xMetaData
->supportsMixedCaseQuotedIdentifiers(),*this,m_aMutex
,aNames
,true) );
1483 return m_aCurrentColumns
[_eType
].get();
1486 Reference
< XIndexAccess
> SAL_CALL
OSingleSelectQueryComposer::getGroupColumns( )
1488 return setCurrentColumns( GroupByColumns
, m_aAdditiveIterator
.getGroupColumns() );
1491 Reference
< XIndexAccess
> SAL_CALL
OSingleSelectQueryComposer::getOrderColumns( )
1493 return setCurrentColumns( OrderColumns
, m_aAdditiveIterator
.getOrderColumns() );
1496 OUString SAL_CALL
OSingleSelectQueryComposer::getQueryWithSubstitution( )
1498 ::osl::MutexGuard
aGuard( m_aMutex
);
1499 ::connectivity::checkDisposed(OSubComponent::rBHelper
.bDisposed
);
1501 OUString
sSqlStatement( getQuery() );
1503 const OSQLParseNode
* pStatementNode
= m_aSqlIterator
.getParseTree();
1504 if ( pStatementNode
)
1506 SQLException aError
;
1507 if ( !pStatementNode
->parseNodeToExecutableStatement( sSqlStatement
, m_xConnection
, m_aSqlParser
, &aError
) )
1511 return sSqlStatement
;
1514 OUString
OSingleSelectQueryComposer::getStatementPart( TGetParseNode
const & _aGetFunctor
, OSQLParseTreeIterator
& _rIterator
)
1518 const OSQLParseNode
* pNode
= _aGetFunctor( &_rIterator
);
1520 pNode
->parseNodeToStr( sResult
, m_xConnection
);
1527 OUString
lcl_getDecomposedColumnName(const OUString
& rComposedName
, std::u16string_view rQuoteString
)
1529 const size_t nQuoteLength
= rQuoteString
.size();
1530 OUString sName
= rComposedName
.trim();
1531 OUString sColumnName
;
1532 sal_Int32 nPos
, nRPos
= 0;
1536 nPos
= sName
.indexOf( rQuoteString
, nRPos
);
1539 nRPos
= sName
.indexOf( rQuoteString
, nPos
+ nQuoteLength
);
1542 if ( static_cast<sal_Int32
>(nRPos
+ nQuoteLength
) < sName
.getLength() )
1544 nRPos
+= nQuoteLength
; // -1 + 1 skip dot
1548 sColumnName
= sName
.copy( nPos
+ nQuoteLength
, nRPos
- nPos
- nQuoteLength
);
1558 return sColumnName
.isEmpty() ? rComposedName
: sColumnName
;
1561 OUString
lcl_getCondition(const Sequence
< Sequence
< PropertyValue
> >& filter
,
1562 const OPredicateInputController
& i_aPredicateInputController
,
1563 const Reference
< XNameAccess
>& i_xSelectColumns
,
1564 std::u16string_view rQuoteString
)
1566 OUStringBuffer sRet
;
1567 for (auto& rOr
: filter
)
1569 if (rOr
.hasElements())
1571 if (!sRet
.isEmpty())
1572 sRet
.append(STR_OR
);
1573 sRet
.append(L_BRACKET
);
1574 OUStringBuffer sAnd
;
1575 for (auto& rAnd
: rOr
)
1577 if (!sAnd
.isEmpty())
1578 sAnd
.append(STR_AND
);
1579 sAnd
.append(rAnd
.Name
);
1581 rAnd
.Value
>>= sValue
;
1582 const OUString sColumnName
= lcl_getDecomposedColumnName( rAnd
.Name
, rQuoteString
);
1583 if ( i_xSelectColumns
.is() && i_xSelectColumns
->hasByName(sColumnName
) )
1585 Reference
<XPropertySet
> xColumn(i_xSelectColumns
->getByName(sColumnName
),UNO_QUERY
);
1586 sValue
= i_aPredicateInputController
.getPredicateValueStr(sValue
,xColumn
);
1590 sValue
= i_aPredicateInputController
.getPredicateValueStr(rAnd
.Name
,sValue
);
1592 lcl_addFilterCriteria_throw(rAnd
.Handle
, sValue
, sAnd
);
1594 sRet
.append(OUString::unacquired(sAnd
) + R_BRACKET
);
1597 return sRet
.makeStringAndClear();
1601 void SAL_CALL
OSingleSelectQueryComposer::setStructuredFilter( const Sequence
< Sequence
< PropertyValue
> >& filter
)
1603 OPredicateInputController
aPredicateInput(m_aContext
, m_xConnection
, &m_aParseContext
);
1604 setFilter(lcl_getCondition(filter
, aPredicateInput
, getColumns(), m_xMetaData
->getIdentifierQuoteString()));
1607 void SAL_CALL
OSingleSelectQueryComposer::setStructuredHavingClause( const Sequence
< Sequence
< PropertyValue
> >& filter
)
1609 OPredicateInputController
aPredicateInput(m_aContext
, m_xConnection
);
1610 setHavingClause(lcl_getCondition(filter
, aPredicateInput
, getColumns(), m_xMetaData
->getIdentifierQuoteString()));
1613 void OSingleSelectQueryComposer::setConditionByColumn( const Reference
< XPropertySet
>& column
, bool andCriteria
, std::function
<bool(OSingleSelectQueryComposer
*, const OUString
&)> const & _aSetFunctor
, sal_Int32 filterOperator
)
1617 ::connectivity::checkDisposed(OSubComponent::rBHelper
.bDisposed
);
1620 || !column
->getPropertySetInfo()->hasPropertyByName(PROPERTY_VALUE
)
1621 || !column
->getPropertySetInfo()->hasPropertyByName(PROPERTY_NAME
)
1622 || !column
->getPropertySetInfo()->hasPropertyByName(PROPERTY_TYPE
))
1623 throw SQLException(DBA_RES(RID_STR_COLUMN_NOT_VALID
),*this,SQLSTATE_GENERAL
,1000,Any() );
1625 sal_Int32 nType
= 0;
1626 column
->getPropertyValue(PROPERTY_TYPE
) >>= nType
;
1627 sal_Int32 nSearchable
= dbtools::getSearchColumnFlag(m_xConnection
,nType
);
1628 if(nSearchable
== ColumnSearch::NONE
)
1629 throw SQLException(DBA_RES(RID_STR_COLUMN_NOT_SEARCHABLE
),*this,SQLSTATE_GENERAL
,1000,Any() );
1631 ::osl::MutexGuard
aGuard( m_aMutex
);
1634 column
->getPropertyValue(PROPERTY_NAME
) >>= aName
;
1636 const Any aValue
= column
->getPropertyValue(PROPERTY_VALUE
);
1638 OUStringBuffer aSQL
;
1639 const OUString aQuote
= m_xMetaData
->getIdentifierQuoteString();
1642 // TODO: if this is called for HAVING, check that the column is a GROUP BY column
1643 // or that it is an aggregate function
1645 if ( m_aCurrentColumns
[SelectColumns
] && m_aCurrentColumns
[SelectColumns
]->hasByName(aName
) )
1647 Reference
<XPropertySet
> xColumn
;
1648 m_aCurrentColumns
[SelectColumns
]->getByName(aName
) >>= xColumn
;
1649 OSL_ENSURE(xColumn
->getPropertySetInfo()->hasPropertyByName(PROPERTY_REALNAME
),"Property REALNAME not available!");
1650 OSL_ENSURE(xColumn
->getPropertySetInfo()->hasPropertyByName(PROPERTY_TABLENAME
),"Property TABLENAME not available!");
1651 OSL_ENSURE(xColumn
->getPropertySetInfo()->hasPropertyByName(u
"AggregateFunction"_ustr
),"Property AggregateFunction not available!");
1653 OUString sRealName
,sTableName
;
1654 xColumn
->getPropertyValue(PROPERTY_REALNAME
) >>= sRealName
;
1655 xColumn
->getPropertyValue(PROPERTY_TABLENAME
) >>= sTableName
;
1656 if(sTableName
.indexOf('.') != -1)
1658 OUString aCatalog
,aSchema
,aTable
;
1659 ::dbtools::qualifiedNameComponents(m_xMetaData
,sTableName
,aCatalog
,aSchema
,aTable
,::dbtools::EComposeRule::InDataManipulation
);
1660 sTableName
= ::dbtools::composeTableName( m_xMetaData
, aCatalog
, aSchema
, aTable
, true, ::dbtools::EComposeRule::InDataManipulation
);
1663 sTableName
= ::dbtools::quoteName(aQuote
,sTableName
);
1665 if ( !::comphelper::getBOOL(xColumn
->getPropertyValue(u
"Function"_ustr
)) )
1667 aSQL
= sTableName
+ "." + ::dbtools::quoteName( aQuote
, sRealName
);
1674 aSQL
= getTableAlias( column
) + ::dbtools::quoteName( aQuote
, aName
);
1677 if ( aValue
.hasValue() )
1679 if( !m_xTypeConverter
.is() )
1680 m_xTypeConverter
.set( Converter::create(m_aContext
) );
1681 OSL_ENSURE(m_xTypeConverter
.is(),"NO typeconverter!");
1683 if ( nType
!= DataType::BOOLEAN
&& DataType::BIT
!= nType
)
1685 lcl_addFilterCriteria_throw(filterOperator
,u
"",aSQL
);
1690 case DataType::VARCHAR
:
1691 case DataType::CHAR
:
1692 case DataType::LONGVARCHAR
:
1693 aSQL
.append( DBTypeConversion::toSQLString( nType
, aValue
, m_xTypeConverter
) );
1695 case DataType::CLOB
:
1697 Reference
< XClob
> xClob(aValue
,UNO_QUERY
);
1700 const ::sal_Int64 nLength
= xClob
->length();
1701 if ( sal_Int64(nLength
+ aSQL
.getLength() + STR_LIKE
.getLength() ) < sal_Int64(SAL_MAX_INT32
) )
1703 aSQL
.append("'" + xClob
->getSubString(1,static_cast<sal_Int32
>(nLength
)) + "'");
1708 aSQL
.append( DBTypeConversion::toSQLString( nType
, aValue
, m_xTypeConverter
) );
1712 case DataType::VARBINARY
:
1713 case DataType::BINARY
:
1714 case DataType::LONGVARBINARY
:
1716 Sequence
<sal_Int8
> aSeq
;
1717 if(!(aValue
>>= aSeq
))
1718 throw SQLException(DBA_RES(RID_STR_NOT_SEQUENCE_INT8
),*this,SQLSTATE_GENERAL
,1000,Any() );
1719 if(nSearchable
== ColumnSearch::CHAR
)
1721 aSQL
.append( "\'" );
1723 aSQL
.append( "0x" );
1724 for (sal_Int32 byte
: aSeq
)
1725 aSQL
.append(byte
, 16);
1726 if(nSearchable
== ColumnSearch::CHAR
)
1727 aSQL
.append( "\'" );
1731 case DataType::BOOLEAN
:
1733 bool bValue
= false;
1734 m_xTypeConverter
->convertToSimpleType(aValue
, TypeClass_BOOLEAN
) >>= bValue
;
1736 OUString sColumnExp
= aSQL
.makeStringAndClear();
1737 getBooleanComparisonPredicate( sColumnExp
, bValue
, m_nBoolCompareMode
, aSQL
);
1741 aSQL
.append( DBTypeConversion::toSQLString( nType
, aValue
, m_xTypeConverter
) );
1747 sal_Int32 nFilterOp
= filterOperator
;
1748 if ( filterOperator
!= SQLFilterOperator::SQLNULL
&& filterOperator
!= SQLFilterOperator::NOT_SQLNULL
)
1749 nFilterOp
= SQLFilterOperator::SQLNULL
;
1750 lcl_addFilterCriteria_throw(nFilterOp
,u
"",aSQL
);
1754 // Construct SELECT without WHERE and ORDER BY
1755 OUString sFilter
= getFilter();
1757 if ( !sFilter
.isEmpty() && !aSQL
.isEmpty() )
1759 sFilter
= L_BRACKET
+ sFilter
+ R_BRACKET
+
1760 (andCriteria
? std::u16string_view(STR_AND
) : std::u16string_view(STR_OR
));
1764 // add the filter and the sort order
1765 _aSetFunctor(this,sFilter
);
1767 catch (css::lang::WrappedTargetException
& e
)
1769 if (e
.TargetException
.isExtractableTo(
1770 cppu::UnoType
<css::sdbc::SQLException
>::get()))
1772 cppu::throwException(e
.TargetException
);
1781 Sequence
< Sequence
< PropertyValue
> > OSingleSelectQueryComposer::getStructuredCondition( TGetParseNode
const & _aGetFunctor
)
1783 ::connectivity::checkDisposed(OSubComponent::rBHelper
.bDisposed
);
1785 MutexGuard
aGuard(m_aMutex
);
1787 Sequence
< Sequence
< PropertyValue
> > aFilterSeq
;
1788 OUString sFilter
= getStatementPart( _aGetFunctor
, m_aAdditiveIterator
);
1791 if ( !sFilter
.isEmpty() )
1793 OUString
aSql(m_aPureSelectSQL
+ STR_WHERE
+ sFilter
);
1794 // build a temporary parse node
1795 const OSQLParseNode
* pTempNode
= m_aAdditiveIterator
.getParseTree();
1798 std::unique_ptr
<OSQLParseNode
> pSqlParseNode( m_aSqlParser
.parseTree(aErrorMsg
,aSql
));
1801 m_aAdditiveIterator
.setParseTree(pSqlParseNode
.get());
1802 // normalize the filter
1803 OSQLParseNode
* pWhereNode
= const_cast<OSQLParseNode
*>(m_aAdditiveIterator
.getWhereTree());
1805 OSQLParseNode
* pCondition
= pWhereNode
->getChild(1);
1806 #if OSL_DEBUG_LEVEL > 0
1807 OUString sCondition
;
1808 pCondition
->parseNodeToStr( sCondition
, m_xConnection
);
1810 OSQLParseNode::negateSearchCondition(pCondition
);
1812 pCondition
= pWhereNode
->getChild(1);
1813 #if OSL_DEBUG_LEVEL > 0
1815 pCondition
->parseNodeToStr( sCondition
, m_xConnection
);
1817 OSQLParseNode::disjunctiveNormalForm(pCondition
);
1819 pCondition
= pWhereNode
->getChild(1);
1820 #if OSL_DEBUG_LEVEL > 0
1822 pCondition
->parseNodeToStr( sCondition
, m_xConnection
);
1824 OSQLParseNode::absorptions(pCondition
);
1826 pCondition
= pWhereNode
->getChild(1);
1827 #if OSL_DEBUG_LEVEL > 0
1829 pCondition
->parseNodeToStr( sCondition
, m_xConnection
);
1833 std::vector
< std::vector
< PropertyValue
> > aFilters
;
1834 Reference
< XNumberFormatter
> xFormatter( NumberFormatter::create(m_aContext
), UNO_QUERY_THROW
);
1835 xFormatter
->attachNumberFormatsSupplier( m_xNumberFormatsSupplier
);
1837 if (setORCriteria(pCondition
, m_aAdditiveIterator
, aFilters
, xFormatter
))
1839 aFilterSeq
.realloc(aFilters
.size());
1840 Sequence
<PropertyValue
>* pFilters
= aFilterSeq
.getArray();
1841 for (auto const& filter
: aFilters
)
1843 pFilters
->realloc(filter
.size());
1844 PropertyValue
* pFilter
= pFilters
->getArray();
1845 for (auto const& elem
: filter
)
1855 m_aAdditiveIterator
.setParseTree(pTempNode
);
1861 OUString
OSingleSelectQueryComposer::getKeyword( SQLPart _ePart
)
1867 SAL_WARN("dbaccess", "OSingleSelectQueryComposer::getKeyWord: Invalid enum value!" );
1868 [[fallthrough
]]; // fallback to WHERE
1870 sKeyword
= STR_WHERE
;
1873 sKeyword
= STR_GROUP_BY
;
1876 sKeyword
= STR_HAVING
;
1879 sKeyword
= STR_ORDER_BY
;
1885 OUString
OSingleSelectQueryComposer::getSQLPart( SQLPart _ePart
, OSQLParseTreeIterator
& _rIterator
, bool _bWithKeyword
)
1887 TGetParseNode
F_tmp(&OSQLParseTreeIterator::getSimpleWhereTree
);
1888 OUString
sKeyword( getKeyword( _ePart
) );
1892 F_tmp
= TGetParseNode(&OSQLParseTreeIterator::getSimpleWhereTree
);
1895 F_tmp
= TGetParseNode (&OSQLParseTreeIterator::getSimpleGroupByTree
);
1898 F_tmp
= TGetParseNode(&OSQLParseTreeIterator::getSimpleHavingTree
);
1901 F_tmp
= TGetParseNode(&OSQLParseTreeIterator::getSimpleOrderTree
);
1904 SAL_WARN("dbaccess","Invalid enum value!");
1907 OUString sRet
= getStatementPart( F_tmp
, _rIterator
);
1908 if ( _bWithKeyword
&& !sRet
.isEmpty() )
1909 sRet
= sKeyword
+ sRet
;
1913 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */