xref: /core/connectivity/source/parse/sqlnode.cxx (revision aa80eaee)
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #include <sal/macros.h>
21 #include <connectivity/sqlnode.hxx>
22 #include <connectivity/sqlerror.hxx>
23 #include <connectivity/sqlbison_exports.hxx>
24 #include <connectivity/internalnode.hxx>
25 #define YYBISON   1
26 #include <sqlbison.hxx>
27 #include <connectivity/sqlparse.hxx>
28 #include <connectivity/sqlscan.hxx>
29 #include <com/sun/star/lang/Locale.hpp>
30 #include <com/sun/star/util/XNumberFormatter.hpp>
31 #include <com/sun/star/util/XNumberFormatTypes.hpp>
32 #include <com/sun/star/i18n/LocaleData.hpp>
33 #include <com/sun/star/i18n/NumberFormatIndex.hpp>
34 #include <com/sun/star/beans/XPropertySet.hpp>
35 #include <com/sun/star/sdbc/XDatabaseMetaData.hpp>
36 #include <com/sun/star/sdbc/DataType.hpp>
37 #include <com/sun/star/sdb/XQueriesSupplier.hpp>
38 #include <com/sun/star/sdb/ErrorCondition.hpp>
39 #include <com/sun/star/util/XNumberFormatsSupplier.hpp>
40 #include <com/sun/star/util/XNumberFormats.hpp>
41 #include <com/sun/star/util/NumberFormat.hpp>
42 #include <com/sun/star/i18n/KParseType.hpp>
43 #include <com/sun/star/i18n/KParseTokens.hpp>
44 #include <com/sun/star/i18n/CharacterClassification.hpp>
45 #include <connectivity/dbconversion.hxx>
46 #include <com/sun/star/util/DateTime.hpp>
47 #include <com/sun/star/util/Time.hpp>
48 #include <com/sun/star/util/Date.hpp>
49 #include <TConnection.hxx>
50 #include <comphelper/numbers.hxx>
51 #include <connectivity/dbtools.hxx>
52 #include <connectivity/dbmetadata.hxx>
53 #include <comphelper/diagnose_ex.hxx>
54 #include <string.h>
55 #include <algorithm>
56 #include <functional>
57 #include <memory>
58 #include <string_view>
59 
60 #include <rtl/ustrbuf.hxx>
61 #include <sal/log.hxx>
62 #include <utility>
63 
64 using namespace ::com::sun::star::sdbc;
65 using namespace ::com::sun::star::util;
66 using namespace ::com::sun::star::beans;
67 using namespace ::com::sun::star::sdb;
68 using namespace ::com::sun::star::uno;
69 using namespace ::com::sun::star::lang;
70 using namespace ::com::sun::star::i18n;
71 using namespace ::com::sun::star;
72 using namespace ::osl;
73 using namespace ::dbtools;
74 using namespace ::comphelper;
75 
76 namespace
77 {
78 
lcl_saveConvertToNumber(const Reference<XNumberFormatter> & _xFormatter,sal_Int32 _nKey,const OUString & _sValue,double & _nrValue)79     bool lcl_saveConvertToNumber(const Reference< XNumberFormatter > & _xFormatter,sal_Int32 _nKey,const OUString& _sValue,double& _nrValue)
80     {
81         bool bRet = false;
82         try
83         {
84             _nrValue = _xFormatter->convertStringToNumber(_nKey, _sValue);
85             bRet = true;
86         }
87         catch(Exception&)
88         {
89         }
90         return bRet;
91     }
92 
replaceAndReset(connectivity::OSQLParseNode * & _pResetNode,connectivity::OSQLParseNode * _pNewNode)93     void replaceAndReset(connectivity::OSQLParseNode*& _pResetNode,connectivity::OSQLParseNode* _pNewNode)
94     {
95         _pResetNode->getParent()->replaceAndDelete(_pResetNode, _pNewNode);
96         _pResetNode = _pNewNode;
97     }
98 
99     /** quotes a string and search for quotes inside the string and replace them with the new quote
100         @param  rValue
101             The value to be quoted.
102         @param  rQuote
103             The quote
104         @param  rQuoteToReplace
105             The quote to replace with
106         @return
107             The quoted string.
108     */
SetQuotation(const OUString & rValue,std::u16string_view rQuote,std::u16string_view rQuoteToReplace)109     OUString SetQuotation(const OUString& rValue, std::u16string_view rQuote, std::u16string_view rQuoteToReplace)
110     {
111         // Replace quotes with double quotes or the parser gets into problems
112         if (!rQuote.empty())
113             return rQuote + rValue.replaceAll(rQuote, rQuoteToReplace) + rQuote;
114         return rValue;
115     }
116 
columnMatchP(const connectivity::OSQLParseNode * pSubTree,const connectivity::SQLParseNodeParameter & rParam)117     bool columnMatchP(const connectivity::OSQLParseNode* pSubTree, const connectivity::SQLParseNodeParameter& rParam)
118     {
119         using namespace connectivity;
120         assert(SQL_ISRULE(pSubTree,column_ref));
121 
122         if(!rParam.xField.is())
123             return false;
124 
125         // retrieve the field's name & table range
126         OUString aFieldName;
127         try
128         {
129             sal_Int32 nNamePropertyId = PROPERTY_ID_NAME;
130             if ( rParam.xField->getPropertySetInfo()->hasPropertyByName( OMetaConnection::getPropMap().getNameByIndex( PROPERTY_ID_REALNAME ) ) )
131                 nNamePropertyId = PROPERTY_ID_REALNAME;
132             rParam.xField->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex( nNamePropertyId ) ) >>= aFieldName;
133         }
134         catch ( Exception& )
135         {
136         }
137 
138         if(!pSubTree->count())
139             return false;
140 
141         const OSQLParseNode* pCol = pSubTree->getChild(pSubTree->count()-1);
142         if (SQL_ISRULE(pCol,column_val))
143         {
144             assert(pCol->count() == 1);
145             pCol = pCol->getChild(0);
146         }
147         const OSQLParseNode* pTable(nullptr);
148         switch (pSubTree->count())
149         {
150         case 1:
151             break;
152         case 3:
153             pTable = pSubTree->getChild(0);
154             break;
155         case 5:
156         case 7:
157             SAL_WARN("connectivity.parse", "SQL: catalog and/or schema in column_ref in predicate");
158             break;
159         default:
160             SAL_WARN("connectivity.parse", "columnMatchP: SQL grammar changed; column_ref has " << pSubTree->count() << " children");
161             assert(false);
162             break;
163         }
164         // TODO: not all DBMS match column names case-insensitively...
165         // see XDatabaseMetaData::supportsMixedCaseIdentifiers()
166         // and XDatabaseMetaData::supportsMixedCaseQuotedIdentifiers()
167         if  (   // table name matches (or no table name)?
168                 ( !pTable || pTable->getTokenValue().equalsIgnoreAsciiCase(rParam.sPredicateTableAlias) )
169              && // column name matches?
170                 pCol->getTokenValue().equalsIgnoreAsciiCase(aFieldName)
171             )
172             return true;
173         return false;
174     }
175 }
176 
177 namespace connectivity
178 {
179 
SQLParseNodeParameter(const Reference<XConnection> & _rxConnection,const Reference<XNumberFormatter> & _xFormatter,const Reference<XPropertySet> & _xField,OUString _sPredicateTableAlias,const Locale & _rLocale,const IParseContext * _pContext,bool _bIntl,bool _bQuote,OUString _sDecSep,bool _bPredicate,bool _bParseToSDBC)180 SQLParseNodeParameter::SQLParseNodeParameter( const Reference< XConnection >& _rxConnection,
181         const Reference< XNumberFormatter >& _xFormatter, const Reference< XPropertySet >& _xField,
182         OUString _sPredicateTableAlias,
183         const Locale& _rLocale, const IParseContext* _pContext,
184         bool _bIntl, bool _bQuote, OUString _sDecSep, bool _bPredicate, bool _bParseToSDBC )
185     :rLocale(_rLocale)
186     ,aMetaData( _rxConnection )
187     ,pParser( nullptr )
188     ,pSubQueryHistory( std::make_shared<QueryNameSet>() )
189     ,xFormatter(_xFormatter)
190     ,xField(_xField)
191     ,sPredicateTableAlias(std::move(_sPredicateTableAlias))
192     ,m_rContext( _pContext ? *_pContext : OSQLParser::s_aDefaultContext )
193     ,sDecSep(std::move(_sDecSep))
194     ,bQuote(_bQuote)
195     ,bInternational(_bIntl)
196     ,bPredicate(_bPredicate)
197     ,bParseToSDBCLevel( _bParseToSDBC )
198 {
199 }
200 
convertDateString(const SQLParseNodeParameter & rParam,std::u16string_view rString)201 OUString OSQLParseNode::convertDateString(const SQLParseNodeParameter& rParam, std::u16string_view rString)
202 {
203     Date aDate = DBTypeConversion::toDate(rString);
204     Reference< XNumberFormatsSupplier > xSupplier(rParam.xFormatter->getNumberFormatsSupplier());
205     Reference< XNumberFormatTypes >     xTypes(xSupplier->getNumberFormats(), UNO_QUERY);
206 
207     double fDate = DBTypeConversion::toDouble(aDate,DBTypeConversion::getNULLDate(xSupplier));
208     sal_Int32 nKey = xTypes->getFormatIndex(NumberFormatIndex::DATE_SYS_DDMMYYYY, rParam.rLocale);
209     return rParam.xFormatter->convertNumberToString(nKey, fDate);
210 }
211 
212 
convertDateTimeString(const SQLParseNodeParameter & rParam,const OUString & rString)213 OUString OSQLParseNode::convertDateTimeString(const SQLParseNodeParameter& rParam, const OUString& rString)
214 {
215     DateTime aDate = DBTypeConversion::toDateTime(rString);
216     Reference< XNumberFormatsSupplier >  xSupplier(rParam.xFormatter->getNumberFormatsSupplier());
217     Reference< XNumberFormatTypes >  xTypes(xSupplier->getNumberFormats(), UNO_QUERY);
218 
219     double fDateTime = DBTypeConversion::toDouble(aDate,DBTypeConversion::getNULLDate(xSupplier));
220     sal_Int32 nKey = xTypes->getFormatIndex(NumberFormatIndex::DATETIME_SYS_DDMMYYYY_HHMMSS, rParam.rLocale);
221     return rParam.xFormatter->convertNumberToString(nKey, fDateTime);
222 }
223 
224 
convertTimeString(const SQLParseNodeParameter & rParam,std::u16string_view rString)225 OUString OSQLParseNode::convertTimeString(const SQLParseNodeParameter& rParam, std::u16string_view rString)
226 {
227     css::util::Time aTime = DBTypeConversion::toTime(rString);
228     Reference< XNumberFormatsSupplier >  xSupplier(rParam.xFormatter->getNumberFormatsSupplier());
229 
230     Reference< XNumberFormatTypes >  xTypes(xSupplier->getNumberFormats(), UNO_QUERY);
231 
232     double fTime = DBTypeConversion::toDouble(aTime);
233     sal_Int32 nKey = xTypes->getFormatIndex(NumberFormatIndex::TIME_HHMMSS, rParam.rLocale);
234     return rParam.xFormatter->convertNumberToString(nKey, fTime);
235 }
236 
237 
parseNodeToStr(OUString & rString,const Reference<XConnection> & _rxConnection,const IParseContext * pContext,bool _bIntl,bool _bQuote) const238 void OSQLParseNode::parseNodeToStr(OUString& rString,
239                                    const Reference< XConnection >& _rxConnection,
240                                    const IParseContext* pContext,
241                                    bool _bIntl,
242                                    bool _bQuote) const
243 {
244     parseNodeToStr(
245         rString, _rxConnection, nullptr, nullptr, OUString(),
246         pContext ? pContext->getPreferredLocale() : OParseContext::getDefaultLocale(),
247         pContext, _bIntl, _bQuote, u"."_ustr, false );
248 }
249 
250 
parseNodeToPredicateStr(OUString & rString,const Reference<XConnection> & _rxConnection,const Reference<XNumberFormatter> & xFormatter,const css::lang::Locale & rIntl,const OUString & rDec,const IParseContext * pContext) const251 void OSQLParseNode::parseNodeToPredicateStr(OUString& rString,
252                                               const Reference< XConnection >& _rxConnection,
253                                               const Reference< XNumberFormatter > & xFormatter,
254                                               const css::lang::Locale& rIntl,
255                                               const OUString& rDec,
256                                               const IParseContext* pContext ) const
257 {
258     OSL_ENSURE(xFormatter.is(), "OSQLParseNode::parseNodeToPredicateStr:: no formatter!");
259 
260     if (xFormatter.is())
261         parseNodeToStr(rString, _rxConnection, xFormatter, nullptr, OUString(), rIntl, pContext, true, true, rDec, true);
262 }
263 
264 
parseNodeToPredicateStr(OUString & rString,const Reference<XConnection> & _rxConnection,const Reference<XNumberFormatter> & xFormatter,const Reference<XPropertySet> & _xField,const OUString & _sPredicateTableAlias,const css::lang::Locale & rIntl,const OUString & rDec,const IParseContext * pContext) const265 void OSQLParseNode::parseNodeToPredicateStr(OUString& rString,
266                                               const Reference< XConnection > & _rxConnection,
267                                               const Reference< XNumberFormatter > & xFormatter,
268                                               const Reference< XPropertySet > & _xField,
269                                               const OUString &_sPredicateTableAlias,
270                                               const css::lang::Locale& rIntl,
271                                               const OUString& rDec,
272                                               const IParseContext* pContext ) const
273 {
274     OSL_ENSURE(xFormatter.is(), "OSQLParseNode::parseNodeToPredicateStr:: no formatter!");
275 
276     if (xFormatter.is())
277         parseNodeToStr( rString, _rxConnection, xFormatter, _xField, _sPredicateTableAlias, rIntl, pContext, true, true, rDec, true );
278 }
279 
280 
parseNodeToStr(OUString & rString,const Reference<XConnection> & _rxConnection,const Reference<XNumberFormatter> & xFormatter,const Reference<XPropertySet> & _xField,const OUString & _sPredicateTableAlias,const css::lang::Locale & rIntl,const IParseContext * pContext,bool _bIntl,bool _bQuote,const OUString & _rDecSep,bool _bPredicate) const281 void OSQLParseNode::parseNodeToStr(OUString& rString,
282                       const Reference< XConnection > & _rxConnection,
283                       const Reference< XNumberFormatter > & xFormatter,
284                       const Reference< XPropertySet > & _xField,
285                       const OUString &_sPredicateTableAlias,
286                       const css::lang::Locale& rIntl,
287                       const IParseContext* pContext,
288                       bool _bIntl,
289                       bool _bQuote,
290                       const OUString& _rDecSep,
291                       bool _bPredicate) const
292 {
293     OSL_ENSURE( _rxConnection.is(), "OSQLParseNode::parseNodeToStr: invalid connection!" );
294 
295     if ( !_rxConnection.is() )
296         return;
297 
298     OUStringBuffer sBuffer(rString);
299     try
300     {
301         OSQLParseNode::impl_parseNodeToString_throw( sBuffer,
302             SQLParseNodeParameter(
303                  _rxConnection, xFormatter, _xField, _sPredicateTableAlias, rIntl, pContext,
304                 _bIntl, _bQuote, _rDecSep, _bPredicate, false
305             ) );
306     }
307     catch( const SQLException& )
308     {
309         SAL_WARN( "connectivity.parse", "OSQLParseNode::parseNodeToStr: this should not throw!" );
310         // our callers don't expect this method to throw anything. The only known situation
311         // where impl_parseNodeToString_throw can throw is when there is a cyclic reference
312         // in the sub queries, but this cannot be the case here, as we do not parse to
313         // SDBC level.
314     }
315     rString = sBuffer.makeStringAndClear();
316 }
317 
parseNodeToExecutableStatement(OUString & _out_rString,const Reference<XConnection> & _rxConnection,OSQLParser & _rParser,css::sdbc::SQLException * _pErrorHolder) const318 bool OSQLParseNode::parseNodeToExecutableStatement( OUString& _out_rString, const Reference< XConnection >& _rxConnection,
319     OSQLParser& _rParser, css::sdbc::SQLException* _pErrorHolder ) const
320 {
321     OSL_PRECOND( _rxConnection.is(), "OSQLParseNode::parseNodeToExecutableStatement: invalid connection!" );
322     SQLParseNodeParameter aParseParam( _rxConnection,
323         nullptr, nullptr, OUString(), OParseContext::getDefaultLocale(), nullptr, false, true, u"."_ustr, false, true );
324 
325     if ( aParseParam.aMetaData.supportsSubqueriesInFrom() )
326     {
327         Reference< XQueriesSupplier > xSuppQueries( _rxConnection, UNO_QUERY );
328         OSL_ENSURE( xSuppQueries.is(), "OSQLParseNode::parseNodeToExecutableStatement: cannot substitute everything without a QueriesSupplier!" );
329         if ( xSuppQueries.is() )
330             aParseParam.xQueries = xSuppQueries->getQueries();
331     }
332 
333     aParseParam.pParser = &_rParser;
334 
335     // LIMIT keyword differs in Firebird
336     OSQLParseNode* pTableExp = getChild(3);
337     Reference< XDatabaseMetaData > xMeta( _rxConnection->getMetaData() );
338     OUString sLimitValue;
339     if( pTableExp->getChild(6)->count() >= 2 && pTableExp->getChild(6)->getChild(1)
340             && (xMeta->getURL().equalsIgnoreAsciiCase("sdbc:embedded:firebird")
341                 || xMeta->getURL().startsWithIgnoreAsciiCase("sdbc:firebird:")))
342     {
343         sLimitValue = pTableExp->getChild(6)->getChild(1)->getTokenValue();
344         delete pTableExp->removeAt(6);
345     }
346 
347     _out_rString.clear();
348     OUStringBuffer sBuffer;
349     bool bSuccess = false;
350     try
351     {
352         impl_parseNodeToString_throw( sBuffer, aParseParam );
353         bSuccess = true;
354     }
355     catch( const SQLException& e )
356     {
357         if ( _pErrorHolder )
358             *_pErrorHolder = e;
359     }
360 
361     if(sLimitValue.getLength() > 0)
362     {
363         constexpr char SELECT_KEYWORD[] = "SELECT";
364         sBuffer.insert(sBuffer.indexOf(SELECT_KEYWORD) + strlen(SELECT_KEYWORD),
365                 Concat2View(" FIRST " + sLimitValue));
366     }
367 
368     _out_rString = sBuffer.makeStringAndClear();
369     return bSuccess;
370 }
371 
372 
373 namespace
374 {
lcl_isAliasNamePresent(const OSQLParseNode & _rTableNameNode)375     bool lcl_isAliasNamePresent( const OSQLParseNode& _rTableNameNode )
376     {
377         return !OSQLParseNode::getTableRange(_rTableNameNode.getParent()).isEmpty();
378     }
379 }
380 
381 
impl_parseNodeToString_throw(OUStringBuffer & rString,const SQLParseNodeParameter & rParam,bool bSimple) const382 void OSQLParseNode::impl_parseNodeToString_throw(OUStringBuffer& rString, const SQLParseNodeParameter& rParam, bool bSimple) const
383 {
384     if ( isToken() )
385     {
386         parseLeaf(rString,rParam);
387         return;
388     }
389 
390     // Let's see how many nodes this subtree has
391     sal_uInt32 nCount = count();
392 
393     bool bHandled = false;
394     switch ( getKnownRuleID() )
395     {
396     // special handling for parameters
397     case parameter:
398     {
399         bSimple=false;
400         if(!rString.isEmpty())
401             rString.append(" ");
402         if (nCount == 1)    // ?
403             m_aChildren[0]->impl_parseNodeToString_throw( rString, rParam, false );
404         else if (rParam.bParseToSDBCLevel && rParam.aMetaData.shouldSubstituteParameterNames())
405         {
406             rString.append("?");
407         }
408         else if (nCount == 2)   // :Name
409         {
410             m_aChildren[0]->impl_parseNodeToString_throw( rString, rParam, false );
411             rString.append(m_aChildren[1]->m_aNodeValue);
412         }                   // [Name]
413         else
414         {
415             assert (nCount == 3);
416             m_aChildren[0]->impl_parseNodeToString_throw( rString, rParam, false );
417             rString.append(m_aChildren[1]->m_aNodeValue);
418             rString.append(m_aChildren[2]->m_aNodeValue);
419         }
420         bHandled = true;
421     }
422     break;
423 
424     // table refs
425     case table_ref:
426         bSimple=false;
427         if (  ( nCount == 2 ) || ( nCount == 3 ) || ( nCount == 5 ) )
428         {
429             impl_parseTableRangeNodeToString_throw( rString, rParam );
430             bHandled = true;
431         }
432         break;
433 
434     // table name - might be a query name
435     case table_name:
436         bSimple=false;
437         bHandled = impl_parseTableNameNodeToString_throw( rString, rParam );
438         break;
439 
440     case as_clause:
441         bSimple=false;
442         assert(nCount == 0 || nCount == 2);
443         if (nCount == 2)
444         {
445             if ( rParam.aMetaData.generateASBeforeCorrelationName() )
446                 rString.append(" AS ");
447             m_aChildren[1]->impl_parseNodeToString_throw( rString, rParam, false );
448         }
449         bHandled = true;
450         break;
451 
452     case opt_as:
453         assert(nCount == 0);
454         bHandled = true;
455         break;
456 
457     case like_predicate:
458         // Depending on whether international is given, LIKE is treated differently
459         // international: *, ? are placeholders
460         // else SQL92 conform: %, _
461         impl_parseLikeNodeToString_throw( rString, rParam, bSimple );
462         bHandled = true;
463         break;
464 
465     case general_set_fct:
466     case set_fct_spec:
467     case position_exp:
468     case extract_exp:
469     case length_exp:
470     case char_value_fct:
471         bSimple=false;
472         if (!addDateValue(rString, rParam))
473         {
474             // Do not quote function name
475             SQLParseNodeParameter aNewParam(rParam);
476             aNewParam.bQuote = ( SQL_ISRULE(this,length_exp)    || SQL_ISRULE(this,char_value_fct) );
477 
478             m_aChildren[0]->impl_parseNodeToString_throw( rString, aNewParam, false );
479             aNewParam.bQuote = rParam.bQuote;
480             //aNewParam.bPredicate = sal_False; // disable [ ] around names // look at i73215
481             OUStringBuffer aStringPara;
482             for (sal_uInt32 i=1; i<nCount; i++)
483             {
484                 const OSQLParseNode * pSubTree = m_aChildren[i].get();
485                 if (pSubTree)
486                 {
487                     pSubTree->impl_parseNodeToString_throw( aStringPara, aNewParam, false );
488 
489                     // In the comma lists, put commas in-between all subtrees
490                     if ((m_eNodeType == SQLNodeType::CommaListRule)     && (i < (nCount - 1)))
491                         aStringPara.append(",");
492                 }
493                 else
494                     i++;
495             }
496             rString.append(aStringPara);
497         }
498         bHandled = true;
499         break;
500     case odbc_call_spec:
501     case subquery:
502     case term:
503     case factor:
504     case window_function:
505     case cast_spec:
506     case num_value_exp:
507         bSimple = false;
508         break;
509     default:
510         break;
511     }   // switch ( getKnownRuleID() )
512 
513     if ( bHandled )
514         return;
515 
516     for (auto i = m_aChildren.begin(); i != m_aChildren.end();)
517     {
518         const OSQLParseNode* pSubTree = i->get();
519         if ( !pSubTree )
520         {
521             ++i;
522             continue;
523         }
524 
525         SQLParseNodeParameter aNewParam(rParam);
526 
527         // don't replace the field for subqueries
528         if (rParam.xField.is() && SQL_ISRULE(pSubTree,subquery))
529             aNewParam.xField = nullptr;
530 
531         // When we are building a criterion inside a query view,
532         // simplify criterion display by removing:
533         //   "currentFieldName"
534         //   "currentFieldName" =
535         // but only in simple expressions.
536         // This means anything that is made of:
537         // (see the rules conditionalised by inPredicateCheck() in sqlbison.y).
538         //  - parentheses
539         //  - logical operators (and, or, not)
540         //  - comparison operators (IS, =, >, <, BETWEEN, LIKE, ...)
541         // but *not* e.g. in function arguments
542         if (bSimple && rParam.bPredicate && rParam.xField.is() && SQL_ISRULE(pSubTree,column_ref))
543         {
544             if (columnMatchP(pSubTree, rParam))
545             {
546                 // skip field
547                 ++i;
548                 // if the following node is the comparison operator'=',
549                 // we filter it as well
550                 if (SQL_ISRULE(this, comparison_predicate))
551                 {
552                     if(i != m_aChildren.end())
553                     {
554                         pSubTree = i->get();
555                         if (pSubTree && pSubTree->getNodeType() == SQLNodeType::Equal)
556                             ++i;
557                     }
558                 }
559             }
560             else
561             {
562                 pSubTree->impl_parseNodeToString_throw( rString, aNewParam, bSimple );
563                 ++i;
564 
565                 // In the comma lists, put commas in-between all subtrees
566                 if ((m_eNodeType == SQLNodeType::CommaListRule)     && (i != m_aChildren.end()))
567                     rString.append(",");
568             }
569         }
570         else
571         {
572             pSubTree->impl_parseNodeToString_throw( rString, aNewParam, bSimple );
573             ++i;
574 
575             // In the comma lists, put commas in-between all subtrees
576             if ((m_eNodeType == SQLNodeType::CommaListRule)     && (i != m_aChildren.end()))
577             {
578                 if (SQL_ISRULE(this,value_exp_commalist) && rParam.bPredicate)
579                     rString.append(";");
580                 else
581                     rString.append(",");
582             }
583         }
584         // The right hand-side of these operators is not simple
585         switch ( getKnownRuleID() )
586         {
587         case general_set_fct:
588         case set_fct_spec:
589         case position_exp:
590         case extract_exp:
591         case length_exp:
592         case char_value_fct:
593         case odbc_call_spec:
594         case subquery:
595         case comparison_predicate:
596         case between_predicate:
597         case like_predicate:
598         case test_for_null:
599         case in_predicate:
600         case existence_test:
601         case unique_test:
602         case all_or_any_predicate:
603         case join_condition:
604         case comparison_predicate_part_2:
605         case parenthesized_boolean_value_expression:
606         case other_like_predicate_part_2:
607         case between_predicate_part_2:
608             bSimple=false;
609             break;
610         default:
611             break;
612         }
613     }
614 }
615 
616 
impl_parseTableNameNodeToString_throw(OUStringBuffer & rString,const SQLParseNodeParameter & rParam) const617 bool OSQLParseNode::impl_parseTableNameNodeToString_throw( OUStringBuffer& rString, const SQLParseNodeParameter& rParam ) const
618 {
619     // is the table_name part of a table_ref?
620     OSL_ENSURE( getParent(), "OSQLParseNode::impl_parseTableNameNodeToString_throw: table_name without parent?" );
621     if ( !getParent() || ( getParent()->getKnownRuleID() != table_ref ) )
622         return false;
623 
624     // if it's a query, maybe we need to substitute the SQL statement ...
625     if ( !rParam.bParseToSDBCLevel )
626         return false;
627 
628     if ( !rParam.xQueries.is() )
629         // connection does not support queries in queries, or was no query supplier
630         return false;
631 
632     try
633     {
634         OUString sTableOrQueryName( getChild(0)->getTokenValue() );
635         bool bIsQuery = rParam.xQueries->hasByName( sTableOrQueryName );
636         if ( !bIsQuery )
637             return false;
638 
639         // avoid recursion (e.g. "foo" defined as "SELECT * FROM bar" and "bar" defined as "SELECT * FROM foo".
640         if ( rParam.pSubQueryHistory->find( sTableOrQueryName ) != rParam.pSubQueryHistory->end() )
641         {
642             OSL_ENSURE( rParam.pParser, "OSQLParseNode::impl_parseTableNameNodeToString_throw: no parser?" );
643             if ( rParam.pParser )
644             {
645                 const SQLError& rErrors( rParam.pParser->getErrorHelper() );
646                 rErrors.raiseException( sdb::ErrorCondition::PARSER_CYCLIC_SUB_QUERIES );
647             }
648             else
649             {
650                 SQLError aErrors;
651                 aErrors.raiseException( sdb::ErrorCondition::PARSER_CYCLIC_SUB_QUERIES );
652             }
653         }
654         rParam.pSubQueryHistory->insert( sTableOrQueryName );
655 
656         Reference< XPropertySet > xQuery( rParam.xQueries->getByName( sTableOrQueryName ), UNO_QUERY_THROW );
657 
658         // substitute the query name with the constituting command
659         OUString sCommand;
660         OSL_VERIFY( xQuery->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex( PROPERTY_ID_COMMAND ) ) >>= sCommand );
661 
662         bool bEscapeProcessing = false;
663         OSL_VERIFY( xQuery->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex( PROPERTY_ID_ESCAPEPROCESSING ) ) >>= bEscapeProcessing );
664 
665         // the query we found here might itself be based on another query, so parse it recursively
666         OSL_ENSURE( rParam.pParser, "OSQLParseNode::impl_parseTableNameNodeToString_throw: cannot analyze sub queries without a parser!" );
667         if ( bEscapeProcessing && rParam.pParser )
668         {
669             OUString sError;
670             std::unique_ptr< OSQLParseNode > pSubQueryNode( rParam.pParser->parseTree( sError, sCommand ) );
671             if (pSubQueryNode)
672             {
673                 // parse the sub-select to SDBC level, too
674                 OUStringBuffer sSubSelect;
675                 pSubQueryNode->impl_parseNodeToString_throw( sSubSelect, rParam, false );
676                 if ( !sSubSelect.isEmpty() )
677                     sCommand = sSubSelect.makeStringAndClear();
678             }
679         }
680 
681         rString.append( " ( " );
682         rString.append(sCommand);
683         rString.append( " )" );
684 
685         // append the query name as table alias, since it might be referenced in other
686         // parts of the statement - but only if there's no other alias name present
687         if ( !lcl_isAliasNamePresent( *this ) )
688         {
689             rString.append( " AS " );
690             if ( rParam.bQuote )
691                 rString.append(SetQuotation( sTableOrQueryName,
692                     rParam.aMetaData.getIdentifierQuoteString(), rParam.aMetaData.getIdentifierQuoteString() ));
693         }
694 
695         // don't forget to remove the query name from the history, else multiple inclusions
696         // won't work
697         // #i69227# / 2006-10-10 / frank.schoenheit@sun.com
698         rParam.pSubQueryHistory->erase( sTableOrQueryName );
699 
700         return true;
701     }
702     catch( const SQLException& )
703     {
704         throw;
705     }
706     catch( const Exception& )
707     {
708         DBG_UNHANDLED_EXCEPTION("connectivity.parse");
709     }
710     return false;
711 }
712 
713 
impl_parseTableRangeNodeToString_throw(OUStringBuffer & rString,const SQLParseNodeParameter & rParam) const714 void OSQLParseNode::impl_parseTableRangeNodeToString_throw(OUStringBuffer& rString, const SQLParseNodeParameter& rParam) const
715 {
716     OSL_PRECOND(  ( count() == 2 ) || ( count() == 3 ) || ( count() == 5 ) ,"Illegal count");
717 
718     // rString += " ";
719     std::for_each(m_aChildren.begin(),m_aChildren.end(),
720         [&] (std::unique_ptr<OSQLParseNode> const & pNode) { pNode->impl_parseNodeToString_throw(rString, rParam, false); });
721 }
722 
723 
impl_parseLikeNodeToString_throw(OUStringBuffer & rString,const SQLParseNodeParameter & rParam,bool bSimple) const724 void OSQLParseNode::impl_parseLikeNodeToString_throw( OUStringBuffer& rString, const SQLParseNodeParameter& rParam, bool bSimple ) const
725 {
726     assert(SQL_ISRULE(this,like_predicate));
727     OSL_ENSURE(count() == 2,"count != 2: Prepare for GPF");
728 
729     const OSQLParseNode* pEscNode = nullptr;
730     const OSQLParseNode* pParaNode = nullptr;
731 
732     SQLParseNodeParameter aNewParam(rParam);
733     //aNewParam.bQuote = sal_True; // why setting this to true? @see https://bz.apache.org/ooo/show_bug.cgi?id=75557
734 
735     if ( !(bSimple && rParam.bPredicate && rParam.xField.is() && SQL_ISRULE(m_aChildren[0],column_ref) && columnMatchP(m_aChildren[0].get(), rParam)) )
736         m_aChildren[0]->impl_parseNodeToString_throw( rString, aNewParam, bSimple );
737 
738     const OSQLParseNode* pPart2 = m_aChildren[1].get();
739     pPart2->getChild(0)->impl_parseNodeToString_throw( rString, aNewParam, false );
740     pPart2->getChild(1)->impl_parseNodeToString_throw( rString, aNewParam, false );
741     pParaNode = pPart2->getChild(2);
742     pEscNode  = pPart2->getChild(3);
743 
744     if (pParaNode->isToken())
745     {
746         OUString aStr = ConvertLikeToken(pParaNode, pEscNode, rParam.bInternational);
747         rString.append(" ");
748         rString.append(SetQuotation(aStr, u"\'", u"\'\'"));
749     }
750     else
751         pParaNode->impl_parseNodeToString_throw( rString, aNewParam, false );
752 
753     pEscNode->impl_parseNodeToString_throw( rString, aNewParam, false );
754 }
755 
756 
getTableComponents(const OSQLParseNode * _pTableNode,css::uno::Any & _rCatalog,OUString & _rSchema,OUString & _rTable,const Reference<XDatabaseMetaData> & _xMetaData)757 bool OSQLParseNode::getTableComponents(const OSQLParseNode* _pTableNode,
758                                             css::uno::Any &_rCatalog,
759                                             OUString &_rSchema,
760                                             OUString &_rTable,
761                                             const Reference< XDatabaseMetaData >& _xMetaData)
762 {
763     OSL_ENSURE(_pTableNode,"Wrong use of getTableComponents! _pTableNode is not allowed to be null!");
764     if(_pTableNode)
765     {
766         const bool bSupportsCatalog = _xMetaData.is() && _xMetaData->supportsCatalogsInDataManipulation();
767         const bool bSupportsSchema = _xMetaData.is() && _xMetaData->supportsSchemasInDataManipulation();
768         const OSQLParseNode* pTableNode = _pTableNode;
769         // clear the parameter given
770         _rCatalog = Any();
771         _rSchema.clear();
772         _rTable.clear();
773         // see rule catalog_name: in sqlbison.y
774         if (SQL_ISRULE(pTableNode,catalog_name))
775         {
776             OSL_ENSURE(pTableNode->getChild(0) && pTableNode->getChild(0)->isToken(),"Invalid parsenode!");
777             _rCatalog <<= pTableNode->getChild(0)->getTokenValue();
778             pTableNode = pTableNode->getChild(2);
779         }
780         // check if we have schema_name rule
781         if(SQL_ISRULE(pTableNode,schema_name))
782         {
783             if ( bSupportsCatalog && !bSupportsSchema )
784                 _rCatalog <<= pTableNode->getChild(0)->getTokenValue();
785             else
786                 _rSchema = pTableNode->getChild(0)->getTokenValue();
787             pTableNode = pTableNode->getChild(2);
788         }
789         // check if we have table_name rule
790         if(SQL_ISRULE(pTableNode,table_name))
791         {
792             _rTable = pTableNode->getChild(0)->getTokenValue();
793         }
794         else
795         {
796             SAL_WARN( "connectivity.parse","Error in parse tree!");
797         }
798     }
799     return !_rTable.isEmpty();
800 }
801 
killThousandSeparator(OSQLParseNode * pLiteral)802 void OSQLParser::killThousandSeparator(OSQLParseNode* pLiteral)
803 {
804     if ( pLiteral )
805     {
806         if ( s_xLocaleData.get()->get()->getLocaleItem( m_pData->aLocale ).decimalSeparator.toChar() == ',' )
807         {
808             pLiteral->m_aNodeValue = pLiteral->m_aNodeValue.replace('.', sal_Unicode());
809             // and replace decimal
810             pLiteral->m_aNodeValue = pLiteral->m_aNodeValue.replace(',', '.');
811         }
812         else
813             pLiteral->m_aNodeValue = pLiteral->m_aNodeValue.replace(',', sal_Unicode());
814     }
815 }
816 
convertNode(sal_Int32 nType,OSQLParseNode * pLiteral)817 OSQLParseNode* OSQLParser::convertNode(sal_Int32 nType, OSQLParseNode* pLiteral)
818 {
819     if ( !pLiteral )
820         return nullptr;
821 
822     OSQLParseNode* pReturn = pLiteral;
823 
824     if ( ( pLiteral->isRule() && !SQL_ISRULE(pLiteral,value_exp) ) || SQL_ISTOKEN(pLiteral,FALSE) || SQL_ISTOKEN(pLiteral,TRUE) )
825     {
826         switch(nType)
827         {
828             case DataType::CHAR:
829             case DataType::VARCHAR:
830             case DataType::LONGVARCHAR:
831             case DataType::CLOB:
832                 if ( !SQL_ISRULE(pReturn,char_value_exp) && !buildStringNodes(pReturn) )
833                     pReturn = nullptr;
834                 break;
835             default:
836                 break;
837         }
838     }
839     else
840     {
841         switch(pLiteral->getNodeType())
842         {
843         case SQLNodeType::String:
844             switch(nType)
845             {
846                 case DataType::CHAR:
847                 case DataType::VARCHAR:
848                 case DataType::LONGVARCHAR:
849                 case DataType::CLOB:
850                     break;
851                 case DataType::DATE:
852                 case DataType::TIME:
853                 case DataType::TIMESTAMP:
854                     if (m_xFormatter.is())
855                         pReturn = buildDate( nType, pReturn);
856                     break;
857                 default:
858                     m_sErrorMessage = m_pContext->getErrorMessage(IParseContext::ErrorCode::InvalidCompare);
859                     break;
860             }
861             break;
862         case SQLNodeType::AccessDate:
863             switch(nType)
864             {
865                 case DataType::DATE:
866                 case DataType::TIME:
867                 case DataType::TIMESTAMP:
868                     if ( m_xFormatter.is() )
869                         pReturn = buildDate( nType, pReturn);
870                     else
871                         m_sErrorMessage = m_pContext->getErrorMessage(IParseContext::ErrorCode::InvalidDateCompare);
872                     break;
873                 default:
874                     m_sErrorMessage = m_pContext->getErrorMessage(IParseContext::ErrorCode::InvalidCompare);
875                     break;
876             }
877             break;
878         case SQLNodeType::IntNum:
879             switch(nType)
880             {
881                 case DataType::BIT:
882                 case DataType::BOOLEAN:
883                 case DataType::DECIMAL:
884                 case DataType::NUMERIC:
885                 case DataType::TINYINT:
886                 case DataType::SMALLINT:
887                 case DataType::INTEGER:
888                 case DataType::BIGINT:
889                 case DataType::FLOAT:
890                 case DataType::REAL:
891                 case DataType::DOUBLE:
892                     // kill thousand separators if any
893                     killThousandSeparator(pReturn);
894                     break;
895                 case DataType::CHAR:
896                 case DataType::VARCHAR:
897                 case DataType::LONGVARCHAR:
898                 case DataType::CLOB:
899                     pReturn = buildNode_STR_NUM(pReturn);
900                     break;
901                 default:
902                     m_sErrorMessage = m_pContext->getErrorMessage(IParseContext::ErrorCode::InvalidIntCompare);
903                     break;
904             }
905             break;
906         case SQLNodeType::ApproxNum:
907             switch(nType)
908             {
909                 case DataType::DECIMAL:
910                 case DataType::NUMERIC:
911                 case DataType::FLOAT:
912                 case DataType::REAL:
913                 case DataType::DOUBLE:
914                     // kill thousand separators if any
915                     killThousandSeparator(pReturn);
916                     break;
917                 case DataType::CHAR:
918                 case DataType::VARCHAR:
919                 case DataType::LONGVARCHAR:
920                 case DataType::CLOB:
921                     pReturn = buildNode_STR_NUM(pReturn);
922                     break;
923                 case DataType::INTEGER:
924                 default:
925                     m_sErrorMessage = m_pContext->getErrorMessage(IParseContext::ErrorCode::InvalidRealCompare);
926                     break;
927             }
928             break;
929         default:
930             ;
931         }
932     }
933     return pReturn;
934 }
935 
buildPredicateRule(OSQLParseNode * & pAppend,OSQLParseNode * pLiteral,OSQLParseNode * pCompare,OSQLParseNode * pLiteral2)936 sal_Int16 OSQLParser::buildPredicateRule(OSQLParseNode*& pAppend, OSQLParseNode* pLiteral, OSQLParseNode* pCompare, OSQLParseNode* pLiteral2)
937 {
938     OSL_ENSURE(inPredicateCheck(),"Only in predicate check allowed!");
939     sal_Int16 nErg = 0;
940     if ( m_xField.is() )
941     {
942         sal_Int32 nType = 0;
943         try
944         {
945             m_xField->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE)) >>= nType;
946         }
947         catch( Exception& )
948         {
949             return nErg;
950         }
951 
952         OSQLParseNode* pNode1 = convertNode(nType,pLiteral);
953         if ( pNode1 )
954         {
955             OSQLParseNode* pNode2 = convertNode(nType,pLiteral2);
956             if ( m_sErrorMessage.isEmpty() )
957                 nErg = buildNode(pAppend,pCompare,pNode1,pNode2);
958         }
959     }
960     if (!pCompare->getParent()) // I have no parent so I was not used and I must die :-)
961         delete pCompare;
962     return nErg;
963 }
964 
buildLikeRule(OSQLParseNode * pAppend,OSQLParseNode * & pLiteral,const OSQLParseNode * pEscape)965 sal_Int16 OSQLParser::buildLikeRule(OSQLParseNode* pAppend, OSQLParseNode*& pLiteral, const OSQLParseNode* pEscape)
966 {
967     sal_Int16 nErg = 0;
968     sal_Int32 nType = 0;
969 
970     if (!m_xField.is())
971         return nErg;
972     try
973     {
974         Any aValue;
975         {
976             aValue = m_xField->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE));
977             aValue >>= nType;
978         }
979     }
980     catch( Exception& )
981     {
982         return nErg;
983     }
984 
985     switch (nType)
986     {
987         case DataType::CHAR:
988         case DataType::VARCHAR:
989         case DataType::LONGVARCHAR:
990         case DataType::CLOB:
991             if(pLiteral->isRule())
992             {
993                 pAppend->append(pLiteral);
994                 nErg = 1;
995             }
996             else
997             {
998                 switch(pLiteral->getNodeType())
999                 {
1000                     case SQLNodeType::String:
1001                         pLiteral->m_aNodeValue = ConvertLikeToken(pLiteral, pEscape, false);
1002                         pAppend->append(pLiteral);
1003                         nErg = 1;
1004                         break;
1005                     case SQLNodeType::ApproxNum:
1006                         if (m_xFormatter.is() && m_nFormatKey)
1007                         {
1008                             sal_Int16 nScale = 0;
1009                             try
1010                             {
1011                                 Any aValue = getNumberFormatProperty( m_xFormatter, m_nFormatKey, u"Decimals"_ustr );
1012                                 aValue >>= nScale;
1013                             }
1014                             catch( Exception& )
1015                             {
1016                             }
1017 
1018                             pAppend->append(new OSQLInternalNode(stringToDouble(pLiteral->getTokenValue(),nScale),SQLNodeType::String));
1019                         }
1020                         else
1021                             pAppend->append(new OSQLInternalNode(pLiteral->getTokenValue(),SQLNodeType::String));
1022 
1023                         delete pLiteral;
1024                         nErg = 1;
1025                         break;
1026                     default:
1027                         m_sErrorMessage = m_pContext->getErrorMessage(IParseContext::ErrorCode::ValueNoLike);
1028                         m_sErrorMessage = m_sErrorMessage.replaceAt(m_sErrorMessage.indexOf("#1"),2,pLiteral->getTokenValue());
1029                         break;
1030                 }
1031             }
1032             break;
1033         default:
1034             m_sErrorMessage = m_pContext->getErrorMessage(IParseContext::ErrorCode::FieldNoLike);
1035             break;
1036     }
1037     return nErg;
1038 }
1039 
buildNode_Date(const double & fValue,sal_Int32 nType)1040 OSQLParseNode* OSQLParser::buildNode_Date(const double& fValue, sal_Int32 nType)
1041 {
1042     OSQLParseNode* pNewNode = new OSQLInternalNode("", SQLNodeType::Rule,OSQLParser::RuleID(OSQLParseNode::set_fct_spec));
1043     pNewNode->append(new OSQLInternalNode("{", SQLNodeType::Punctuation));
1044     OSQLParseNode* pDateNode = new OSQLInternalNode("", SQLNodeType::Rule,OSQLParser::RuleID(OSQLParseNode::odbc_fct_spec));
1045     pNewNode->append(pDateNode);
1046     pNewNode->append(new OSQLInternalNode("}", SQLNodeType::Punctuation));
1047 
1048     switch (nType)
1049     {
1050         case DataType::DATE:
1051         {
1052             Date aDate = DBTypeConversion::toDate(fValue,DBTypeConversion::getNULLDate(m_xFormatter->getNumberFormatsSupplier()));
1053             OUString aString = DBTypeConversion::toDateString(aDate);
1054             pDateNode->append(new OSQLInternalNode("", SQLNodeType::Keyword, SQL_TOKEN_D));
1055             pDateNode->append(new OSQLInternalNode(aString, SQLNodeType::String));
1056             break;
1057         }
1058         case DataType::TIME:
1059         {
1060             css::util::Time aTime = DBTypeConversion::toTime(fValue);
1061             OUString aString = DBTypeConversion::toTimeString(aTime);
1062             pDateNode->append(new OSQLInternalNode("", SQLNodeType::Keyword, SQL_TOKEN_T));
1063             pDateNode->append(new OSQLInternalNode(aString, SQLNodeType::String));
1064             break;
1065         }
1066         case DataType::TIMESTAMP:
1067         {
1068             DateTime aDateTime = DBTypeConversion::toDateTime(fValue,DBTypeConversion::getNULLDate(m_xFormatter->getNumberFormatsSupplier()));
1069             if (aDateTime.Seconds || aDateTime.Minutes || aDateTime.Hours)
1070             {
1071                 OUString aString = DBTypeConversion::toDateTimeString(aDateTime);
1072                 pDateNode->append(new OSQLInternalNode("", SQLNodeType::Keyword, SQL_TOKEN_TS));
1073                 pDateNode->append(new OSQLInternalNode(aString, SQLNodeType::String));
1074             }
1075             else
1076             {
1077                 Date aDate(aDateTime.Day,aDateTime.Month,aDateTime.Year);
1078                 pDateNode->append(new OSQLInternalNode("", SQLNodeType::Keyword, SQL_TOKEN_D));
1079                 pDateNode->append(new OSQLInternalNode(DBTypeConversion::toDateString(aDate), SQLNodeType::String));
1080             }
1081             break;
1082         }
1083     }
1084 
1085     return pNewNode;
1086 }
1087 
buildNode_STR_NUM(OSQLParseNode * & _pLiteral)1088 OSQLParseNode* OSQLParser::buildNode_STR_NUM(OSQLParseNode*& _pLiteral)
1089 {
1090     OSQLParseNode* pReturn = nullptr;
1091     if ( _pLiteral )
1092     {
1093         if (m_nFormatKey)
1094         {
1095             sal_Int16 nScale = 0;
1096             try
1097             {
1098                 Any aValue = getNumberFormatProperty( m_xFormatter, m_nFormatKey, u"Decimals"_ustr );
1099                 aValue >>= nScale;
1100             }
1101             catch( Exception& )
1102             {
1103             }
1104 
1105             pReturn = new OSQLInternalNode(stringToDouble(_pLiteral->getTokenValue(),nScale),SQLNodeType::String);
1106         }
1107         else
1108             pReturn = new OSQLInternalNode(_pLiteral->getTokenValue(),SQLNodeType::String);
1109 
1110         delete _pLiteral;
1111         _pLiteral = nullptr;
1112     }
1113     return pReturn;
1114 }
1115 
stringToDouble(const OUString & _rValue,sal_Int16 _nScale)1116 OUString OSQLParser::stringToDouble(const OUString& _rValue,sal_Int16 _nScale)
1117 {
1118     OUString aValue;
1119     if(!m_xCharClass.is())
1120         m_xCharClass  = CharacterClassification::create( m_xContext );
1121     if( s_xLocaleData.get() )
1122     {
1123         try
1124         {
1125             ParseResult aResult = m_xCharClass->parsePredefinedToken(KParseType::ANY_NUMBER,_rValue,0,m_pData->aLocale,0,OUString(),KParseType::ANY_NUMBER,OUString());
1126             if((aResult.TokenType & KParseType::IDENTNAME) && aResult.EndPos == _rValue.getLength())
1127             {
1128                 aValue = OUString::number(aResult.Value);
1129                 sal_Int32 nPos = aValue.lastIndexOf('.');
1130                 if((nPos+_nScale) < aValue.getLength())
1131                     aValue = aValue.replaceAt(nPos+_nScale,aValue.getLength()-nPos-_nScale, u"");
1132                 OUString sDecimalSeparator = s_xLocaleData.get()->get()->getLocaleItem(m_pData->aLocale).decimalSeparator;
1133                 aValue = aValue.replaceAt(aValue.lastIndexOf('.'), 1, sDecimalSeparator);
1134                 return aValue;
1135             }
1136         }
1137         catch(Exception&)
1138         {
1139         }
1140     }
1141     return aValue;
1142 }
1143 
1144 
getMutex()1145 std::mutex& OSQLParser::getMutex()
1146 {
1147     static std::mutex aMutex;
1148     return aMutex;
1149 }
1150 
1151 
predicateTree(OUString & rErrorMessage,const OUString & rStatement,const Reference<css::util::XNumberFormatter> & xFormatter,const Reference<XPropertySet> & xField,bool bUseRealName)1152 std::unique_ptr<OSQLParseNode> OSQLParser::predicateTree(OUString& rErrorMessage, const OUString& rStatement,
1153                                          const Reference< css::util::XNumberFormatter > & xFormatter,
1154                                          const Reference< XPropertySet > & xField,
1155                                          bool bUseRealName)
1156 {
1157     // Guard the parsing
1158     std::unique_lock aGuard(getMutex());
1159     // must be reset
1160     setParser(this);
1161 
1162 
1163     // reset the parser
1164     m_xField        = xField;
1165     m_xFormatter    = xFormatter;
1166 
1167     if (m_xField.is())
1168     {
1169         sal_Int32 nType=0;
1170         try
1171         {
1172             // get the field name
1173             OUString aString;
1174 
1175             // retrieve the fields name
1176             // #75243# use the RealName of the column if there is any otherwise the name which could be the alias
1177             // of the field
1178             Reference< XPropertySetInfo> xInfo = m_xField->getPropertySetInfo();
1179             if ( bUseRealName && xInfo->hasPropertyByName(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_REALNAME)))
1180                 m_xField->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_REALNAME)) >>= aString;
1181             else
1182                 m_xField->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME)) >>= aString;
1183 
1184             m_sFieldName = aString;
1185 
1186             // get the field format key
1187             if ( xInfo->hasPropertyByName(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FORMATKEY)))
1188                 m_xField->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FORMATKEY)) >>= m_nFormatKey;
1189             else
1190                 m_nFormatKey = 0;
1191 
1192             // get the field type
1193             m_xField->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE)) >>= nType;
1194         }
1195         catch ( Exception& )
1196         {
1197             OSL_ASSERT(false);
1198         }
1199 
1200         if (m_nFormatKey && m_xFormatter.is())
1201         {
1202             Any aValue = getNumberFormatProperty( m_xFormatter, m_nFormatKey, OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_LOCALE) );
1203             OSL_ENSURE(aValue.getValueType() == cppu::UnoType<css::lang::Locale>::get(), "OSQLParser::PredicateTree : invalid language property !");
1204 
1205             if (aValue.getValueType() == cppu::UnoType<css::lang::Locale>::get())
1206                 aValue >>= m_pData->aLocale;
1207         }
1208         else
1209             m_pData->aLocale = m_pContext->getPreferredLocale();
1210 
1211         if ( m_xFormatter.is() )
1212         {
1213             try
1214             {
1215                 Reference< css::util::XNumberFormatsSupplier >  xFormatSup = m_xFormatter->getNumberFormatsSupplier();
1216                 if ( xFormatSup.is() )
1217                 {
1218                     Reference< css::util::XNumberFormats >  xFormats = xFormatSup->getNumberFormats();
1219                     if ( xFormats.is() )
1220                     {
1221                         css::lang::Locale aLocale;
1222                         aLocale.Language = "en";
1223                         aLocale.Country = "US";
1224                         OUString sFormat(u"YYYY-MM-DD"_ustr);
1225                         m_nDateFormatKey = xFormats->queryKey(sFormat,aLocale,false);
1226                         if ( m_nDateFormatKey == sal_Int32(-1) )
1227                             m_nDateFormatKey = xFormats->addNew(sFormat, aLocale);
1228                     }
1229                 }
1230             }
1231             catch ( Exception& )
1232             {
1233                 SAL_WARN( "connectivity.parse","DateFormatKey");
1234             }
1235         }
1236 
1237         switch (nType)
1238         {
1239             case DataType::DATE:
1240             case DataType::TIME:
1241             case DataType::TIMESTAMP:
1242                 s_pScanner->SetRule(OSQLScanner::GetDATERule());
1243                 break;
1244             case DataType::CHAR:
1245             case DataType::VARCHAR:
1246             case DataType::LONGVARCHAR:
1247             case DataType::CLOB:
1248                 s_pScanner->SetRule(OSQLScanner::GetSTRINGRule());
1249                 break;
1250             default:
1251                 if ( s_xLocaleData.get()->get()->getLocaleItem( m_pData->aLocale ).decimalSeparator.toChar() == ',' )
1252                     s_pScanner->SetRule(OSQLScanner::GetGERRule());
1253                 else
1254                     s_pScanner->SetRule(OSQLScanner::GetENGRule());
1255         }
1256 
1257     }
1258     else
1259         s_pScanner->SetRule(OSQLScanner::GetSQLRule());
1260 
1261     s_pScanner->prepareScan(rStatement, m_pContext, true);
1262 
1263     SQLyylval.pParseNode = nullptr;
1264     //  SQLyypvt = NULL;
1265     m_pParseTree = nullptr;
1266     m_sErrorMessage.clear();
1267 
1268     // Start the parser
1269     if (SQLyyparse() != 0)
1270     {
1271         m_sFieldName.clear();
1272         m_xField.clear();
1273         m_xFormatter.clear();
1274         m_nFormatKey = 0;
1275         m_nDateFormatKey = 0;
1276 
1277         if (m_sErrorMessage.isEmpty())
1278             m_sErrorMessage = s_pScanner->getErrorMessage();
1279         if (m_sErrorMessage.isEmpty())
1280             m_sErrorMessage = m_pContext->getErrorMessage(IParseContext::ErrorCode::General);
1281 
1282         rErrorMessage = m_sErrorMessage;
1283 
1284         // clear the garbage collector
1285         (*s_pGarbageCollector)->clearAndDelete();
1286         // coverity[leaked_storage : FALSE] - because the garbage collector deleted it
1287         m_pParseTree.release();
1288         return nullptr;
1289     }
1290     else
1291     {
1292         (*s_pGarbageCollector)->clear();
1293 
1294         m_sFieldName.clear();
1295         m_xField.clear();
1296         m_xFormatter.clear();
1297         m_nFormatKey = 0;
1298         m_nDateFormatKey = 0;
1299 
1300         // Return the result (the root parse node):
1301 
1302         // Instead, the parse method sets the member pParseTree and simply returns that
1303         OSL_ENSURE(m_pParseTree != nullptr,"OSQLParser: Parser did not return a ParseTree!");
1304         return std::move(m_pParseTree);
1305     }
1306 }
1307 
1308 
OSQLParser(css::uno::Reference<css::uno::XComponentContext> xContext,const IParseContext * _pContext,const IParseContext * _pNeutral)1309 OSQLParser::OSQLParser(css::uno::Reference< css::uno::XComponentContext > xContext,
1310                        const IParseContext* _pContext,
1311                        const IParseContext* _pNeutral)
1312     :m_pContext(_pContext)
1313     ,m_pNeutral(_pNeutral)
1314     ,m_pData( new OSQLParser_Data )
1315     ,m_nFormatKey(0)
1316     ,m_nDateFormatKey(0)
1317     ,m_xContext(std::move(xContext))
1318 {
1319 
1320 
1321     setParser(this);
1322 
1323 #ifdef SQLYYDEBUG
1324 #ifdef SQLYYDEBUG_ON
1325     SQLyydebug = 1;
1326 #endif
1327 #endif
1328 
1329     std::unique_lock aGuard(getMutex());
1330     // Do we have to initialize the data?
1331     if (s_nRefCount == 0)
1332     {
1333         s_pScanner = new OSQLScanner();
1334         s_pScanner->setScanner();
1335         s_pGarbageCollector = new OSQLParseNodesGarbageCollector();
1336 
1337         if(!s_xLocaleData.get())
1338             s_xLocaleData.set(LocaleData::create(m_xContext));
1339 
1340         // reset to UNKNOWN_RULE
1341         static_assert(OSQLParseNode::UNKNOWN_RULE==0, "UNKNOWN_RULE must be 0 for memset to 0 to work");
1342         memset(OSQLParser::s_nRuleIDs,0,sizeof(OSQLParser::s_nRuleIDs));
1343 
1344         const struct
1345         {
1346             OSQLParseNode::Rule eRule;      // the parse node's ID for the rule
1347             OString      sRuleName;  // the name of the rule ("select_statement")
1348         }   aRuleDescriptions[] =
1349         {
1350             { OSQLParseNode::select_statement, "select_statement"_ostr },
1351             { OSQLParseNode::table_exp, "table_exp"_ostr },
1352             { OSQLParseNode::table_ref_commalist, "table_ref_commalist"_ostr },
1353             { OSQLParseNode::table_ref, "table_ref"_ostr },
1354             { OSQLParseNode::catalog_name, "catalog_name"_ostr },
1355             { OSQLParseNode::schema_name, "schema_name"_ostr },
1356             { OSQLParseNode::table_name, "table_name"_ostr },
1357             { OSQLParseNode::opt_column_commalist, "opt_column_commalist"_ostr },
1358             { OSQLParseNode::column_commalist, "column_commalist"_ostr },
1359             { OSQLParseNode::column_ref_commalist, "column_ref_commalist"_ostr },
1360             { OSQLParseNode::column_ref, "column_ref"_ostr },
1361             { OSQLParseNode::opt_order_by_clause, "opt_order_by_clause"_ostr },
1362             { OSQLParseNode::ordering_spec_commalist, "ordering_spec_commalist"_ostr },
1363             { OSQLParseNode::ordering_spec, "ordering_spec"_ostr },
1364             { OSQLParseNode::opt_asc_desc, "opt_asc_desc"_ostr },
1365             { OSQLParseNode::where_clause, "where_clause"_ostr },
1366             { OSQLParseNode::opt_where_clause, "opt_where_clause"_ostr },
1367             { OSQLParseNode::search_condition, "search_condition"_ostr },
1368             { OSQLParseNode::comparison, "comparison"_ostr },
1369             { OSQLParseNode::comparison_predicate, "comparison_predicate"_ostr },
1370             { OSQLParseNode::between_predicate, "between_predicate"_ostr },
1371             { OSQLParseNode::like_predicate, "like_predicate"_ostr },
1372             { OSQLParseNode::opt_escape, "opt_escape"_ostr },
1373             { OSQLParseNode::test_for_null, "test_for_null"_ostr },
1374             { OSQLParseNode::scalar_exp_commalist, "scalar_exp_commalist"_ostr },
1375             { OSQLParseNode::scalar_exp, "scalar_exp"_ostr },
1376             { OSQLParseNode::parameter_ref, "parameter_ref"_ostr },
1377             { OSQLParseNode::parameter, "parameter"_ostr },
1378             { OSQLParseNode::general_set_fct, "general_set_fct"_ostr },
1379             { OSQLParseNode::range_variable, "range_variable"_ostr },
1380             { OSQLParseNode::column, "column"_ostr },
1381             { OSQLParseNode::delete_statement_positioned, "delete_statement_positioned"_ostr },
1382             { OSQLParseNode::delete_statement_searched, "delete_statement_searched"_ostr },
1383             { OSQLParseNode::update_statement_positioned, "update_statement_positioned"_ostr },
1384             { OSQLParseNode::update_statement_searched, "update_statement_searched"_ostr },
1385             { OSQLParseNode::assignment_commalist, "assignment_commalist"_ostr },
1386             { OSQLParseNode::assignment, "assignment"_ostr },
1387             { OSQLParseNode::values_or_query_spec, "values_or_query_spec"_ostr },
1388             { OSQLParseNode::insert_statement, "insert_statement"_ostr },
1389             { OSQLParseNode::insert_atom_commalist, "insert_atom_commalist"_ostr },
1390             { OSQLParseNode::insert_atom, "insert_atom"_ostr },
1391             { OSQLParseNode::from_clause, "from_clause"_ostr },
1392             { OSQLParseNode::qualified_join, "qualified_join"_ostr },
1393             { OSQLParseNode::cross_union, "cross_union"_ostr },
1394             { OSQLParseNode::select_sublist, "select_sublist"_ostr },
1395             { OSQLParseNode::derived_column, "derived_column"_ostr },
1396             { OSQLParseNode::column_val, "column_val"_ostr },
1397             { OSQLParseNode::set_fct_spec, "set_fct_spec"_ostr },
1398             { OSQLParseNode::boolean_term, "boolean_term"_ostr },
1399             { OSQLParseNode::boolean_primary, "boolean_primary"_ostr },
1400             { OSQLParseNode::num_value_exp, "num_value_exp"_ostr },
1401             { OSQLParseNode::join_type, "join_type"_ostr },
1402             { OSQLParseNode::position_exp, "position_exp"_ostr },
1403             { OSQLParseNode::extract_exp, "extract_exp"_ostr },
1404             { OSQLParseNode::length_exp, "length_exp"_ostr },
1405             { OSQLParseNode::char_value_fct, "char_value_fct"_ostr },
1406             { OSQLParseNode::odbc_call_spec, "odbc_call_spec"_ostr },
1407             { OSQLParseNode::in_predicate, "in_predicate"_ostr },
1408             { OSQLParseNode::existence_test, "existence_test"_ostr },
1409             { OSQLParseNode::unique_test, "unique_test"_ostr },
1410             { OSQLParseNode::all_or_any_predicate, "all_or_any_predicate"_ostr },
1411             { OSQLParseNode::named_columns_join, "named_columns_join"_ostr },
1412             { OSQLParseNode::join_condition, "join_condition"_ostr },
1413             { OSQLParseNode::joined_table, "joined_table"_ostr },
1414             { OSQLParseNode::boolean_factor, "boolean_factor"_ostr },
1415             { OSQLParseNode::sql_not, "sql_not"_ostr },
1416             { OSQLParseNode::manipulative_statement, "manipulative_statement"_ostr },
1417             { OSQLParseNode::subquery, "subquery"_ostr },
1418             { OSQLParseNode::value_exp_commalist, "value_exp_commalist"_ostr },
1419             { OSQLParseNode::odbc_fct_spec, "odbc_fct_spec"_ostr },
1420             { OSQLParseNode::union_statement, "union_statement"_ostr },
1421             { OSQLParseNode::outer_join_type, "outer_join_type"_ostr },
1422             { OSQLParseNode::char_value_exp, "char_value_exp"_ostr },
1423             { OSQLParseNode::term, "term"_ostr },
1424             { OSQLParseNode::value_exp_primary, "value_exp_primary"_ostr },
1425             { OSQLParseNode::value_exp, "value_exp"_ostr },
1426             { OSQLParseNode::selection, "selection"_ostr },
1427             { OSQLParseNode::fold, "fold"_ostr },
1428             { OSQLParseNode::char_substring_fct, "char_substring_fct"_ostr },
1429             { OSQLParseNode::factor, "factor"_ostr },
1430             { OSQLParseNode::base_table_def, "base_table_def"_ostr },
1431             { OSQLParseNode::base_table_element_commalist, "base_table_element_commalist"_ostr },
1432             { OSQLParseNode::data_type, "data_type"_ostr },
1433             { OSQLParseNode::column_def, "column_def"_ostr },
1434             { OSQLParseNode::table_node, "table_node"_ostr },
1435             { OSQLParseNode::as_clause, "as_clause"_ostr },
1436             { OSQLParseNode::opt_as, "opt_as"_ostr },
1437             { OSQLParseNode::op_column_commalist, "op_column_commalist"_ostr },
1438             { OSQLParseNode::table_primary_as_range_column, "table_primary_as_range_column"_ostr },
1439             { OSQLParseNode::datetime_primary, "datetime_primary"_ostr },
1440             { OSQLParseNode::concatenation, "concatenation"_ostr },
1441             { OSQLParseNode::char_factor, "char_factor"_ostr },
1442             { OSQLParseNode::bit_value_fct, "bit_value_fct"_ostr },
1443             { OSQLParseNode::comparison_predicate_part_2, "comparison_predicate_part_2"_ostr },
1444             { OSQLParseNode::parenthesized_boolean_value_expression, "parenthesized_boolean_value_expression"_ostr },
1445             { OSQLParseNode::character_string_type, "character_string_type"_ostr },
1446             { OSQLParseNode::other_like_predicate_part_2, "other_like_predicate_part_2"_ostr },
1447             { OSQLParseNode::between_predicate_part_2, "between_predicate_part_2"_ostr },
1448             { OSQLParseNode::null_predicate_part_2, "null_predicate_part_2"_ostr },
1449             { OSQLParseNode::cast_spec, "cast_spec"_ostr },
1450             { OSQLParseNode::window_function, "window_function"_ostr }
1451         };
1452         const size_t nRuleMapCount = std::size( aRuleDescriptions );
1453         // added a new rule? Adjust this map!
1454         // +1 for UNKNOWN_RULE
1455         static_assert(nRuleMapCount + 1 == static_cast<size_t>(OSQLParseNode::rule_count), "must be equal");
1456 
1457         for (const auto & aRuleDescription : aRuleDescriptions)
1458         {
1459             // look up the rule description in the our identifier map
1460             sal_uInt32 nParserRuleID = StrToRuleID( aRuleDescription.sRuleName );
1461             // map the parser's rule ID to the OSQLParseNode::Rule
1462             s_aReverseRuleIDLookup[ nParserRuleID ] = aRuleDescription.eRule;
1463             // and map the OSQLParseNode::Rule to the parser's rule ID
1464             s_nRuleIDs[ aRuleDescription.eRule ] = nParserRuleID;
1465         }
1466     }
1467     ++s_nRefCount;
1468 
1469     if (m_pContext == nullptr)
1470         // take the default context
1471         m_pContext = &s_aDefaultContext;
1472 
1473     m_pData->aLocale = m_pContext->getPreferredLocale();
1474 }
1475 
1476 
~OSQLParser()1477 OSQLParser::~OSQLParser()
1478 {
1479     std::unique_lock aGuard(getMutex());
1480     OSL_ENSURE(s_nRefCount > 0, "OSQLParser::~OSQLParser() : suspicious call : has a refcount of 0 !");
1481     if (!--s_nRefCount)
1482     {
1483         s_pScanner->setScanner(true);
1484         delete s_pScanner;
1485         s_pScanner = nullptr;
1486 
1487         delete s_pGarbageCollector;
1488         s_pGarbageCollector = nullptr;
1489 
1490         RuleIDMap().swap(s_aReverseRuleIDLookup);
1491     }
1492     m_pParseTree = nullptr;
1493 }
1494 
substituteParameterNames(OSQLParseNode const * _pNode)1495 void OSQLParseNode::substituteParameterNames(OSQLParseNode const * _pNode)
1496 {
1497     sal_Int32 nCount = _pNode->count();
1498     for(sal_Int32 i=0;i < nCount;++i)
1499     {
1500         OSQLParseNode* pChildNode = _pNode->getChild(i);
1501         if(SQL_ISRULE(pChildNode,parameter) && pChildNode->count() > 1)
1502         {
1503             OSQLParseNode* pNewNode = new OSQLParseNode("?" ,SQLNodeType::Punctuation,0);
1504             pChildNode->replaceAndDelete(pChildNode->getChild(0), pNewNode);
1505             sal_Int32 nChildCount = pChildNode->count();
1506             for(sal_Int32 j=1;j < nChildCount;++j)
1507                 delete pChildNode->removeAt(1);
1508         }
1509         else
1510             substituteParameterNames(pChildNode);
1511 
1512     }
1513 }
1514 
extractDate(OSQLParseNode const * pLiteral,double & _rfValue)1515 bool OSQLParser::extractDate(OSQLParseNode const * pLiteral,double& _rfValue)
1516 {
1517     Reference< XNumberFormatsSupplier > xFormatSup = m_xFormatter->getNumberFormatsSupplier();
1518     Reference< XNumberFormatTypes > xFormatTypes;
1519     if ( xFormatSup.is() )
1520         xFormatTypes.set(xFormatSup->getNumberFormats(), css::uno::UNO_QUERY);
1521 
1522     // if there is no format key, yet, make sure we have a feasible one for our locale
1523     try
1524     {
1525         if ( !m_nFormatKey && xFormatTypes.is() )
1526             m_nFormatKey = ::dbtools::getDefaultNumberFormat( m_xField, xFormatTypes, m_pData->aLocale );
1527     }
1528     catch( Exception& ) { }
1529     const OUString& sValue = pLiteral->getTokenValue();
1530     sal_Int32 nTryFormat = m_nFormatKey;
1531     bool bSuccess = lcl_saveConvertToNumber( m_xFormatter, nTryFormat, sValue, _rfValue );
1532 
1533     // If our format key didn't do, try the default date format for our locale.
1534     if ( !bSuccess && xFormatTypes.is() )
1535     {
1536         try
1537         {
1538             nTryFormat = xFormatTypes->getStandardFormat( NumberFormat::DATE, m_pData->aLocale );
1539         }
1540         catch( Exception& ) { }
1541         bSuccess = lcl_saveConvertToNumber( m_xFormatter, nTryFormat, sValue, _rfValue );
1542     }
1543 
1544     // if this also didn't do, try ISO format
1545     if ( !bSuccess && xFormatTypes.is() )
1546     {
1547         try
1548         {
1549             nTryFormat = xFormatTypes->getFormatIndex( NumberFormatIndex::DATE_DIN_YYYYMMDD, m_pData->aLocale );
1550         }
1551         catch( Exception& ) { }
1552         bSuccess = lcl_saveConvertToNumber( m_xFormatter, nTryFormat, sValue, _rfValue );
1553     }
1554 
1555     // if this also didn't do, try fallback date format (en-US)
1556     if ( !bSuccess )
1557     {
1558         nTryFormat = m_nDateFormatKey;
1559         bSuccess = lcl_saveConvertToNumber( m_xFormatter, nTryFormat, sValue, _rfValue );
1560     }
1561     return bSuccess;
1562 }
1563 
buildDate(sal_Int32 _nType,OSQLParseNode * & pLiteral)1564 OSQLParseNode* OSQLParser::buildDate(sal_Int32 _nType,OSQLParseNode*& pLiteral)
1565 {
1566     // try converting the string into a date, according to our format key
1567     double fValue = 0.0;
1568     OSQLParseNode* pFCTNode = nullptr;
1569 
1570     if ( extractDate(pLiteral,fValue) )
1571         pFCTNode = buildNode_Date( fValue, _nType);
1572 
1573     delete pLiteral;
1574     pLiteral = nullptr;
1575 
1576     if ( !pFCTNode )
1577         m_sErrorMessage = m_pContext->getErrorMessage(IParseContext::ErrorCode::InvalidDateCompare);
1578 
1579     return pFCTNode;
1580 }
1581 
1582 
OSQLParseNode(const char * pNewValue,SQLNodeType eNewNodeType,sal_uInt32 nNewNodeID)1583 OSQLParseNode::OSQLParseNode(const char * pNewValue,
1584                              SQLNodeType eNewNodeType,
1585                              sal_uInt32 nNewNodeID)
1586         :m_pParent(nullptr)
1587         ,m_aNodeValue(pNewValue,strlen(pNewValue),RTL_TEXTENCODING_UTF8)
1588         ,m_eNodeType(eNewNodeType)
1589         ,m_nNodeID(nNewNodeID)
1590 {
1591     OSL_ENSURE(m_eNodeType >= SQLNodeType::Rule && m_eNodeType <= SQLNodeType::Concat,"OSQLParseNode: created with invalid NodeType");
1592 }
1593 
OSQLParseNode(std::string_view _rNewValue,SQLNodeType eNewNodeType,sal_uInt32 nNewNodeID)1594 OSQLParseNode::OSQLParseNode(std::string_view _rNewValue,
1595                              SQLNodeType eNewNodeType,
1596                              sal_uInt32 nNewNodeID)
1597         :m_pParent(nullptr)
1598         ,m_aNodeValue(OStringToOUString(_rNewValue,RTL_TEXTENCODING_UTF8))
1599         ,m_eNodeType(eNewNodeType)
1600         ,m_nNodeID(nNewNodeID)
1601 {
1602     OSL_ENSURE(m_eNodeType >= SQLNodeType::Rule && m_eNodeType <= SQLNodeType::Concat,"OSQLParseNode: created with invalid NodeType");
1603 }
1604 
OSQLParseNode(OUString _aNewValue,SQLNodeType eNewNodeType,sal_uInt32 nNewNodeID)1605 OSQLParseNode::OSQLParseNode(OUString _aNewValue,
1606                                  SQLNodeType eNewNodeType,
1607                                  sal_uInt32 nNewNodeID)
1608         :m_pParent(nullptr)
1609         ,m_aNodeValue(std::move(_aNewValue))
1610         ,m_eNodeType(eNewNodeType)
1611         ,m_nNodeID(nNewNodeID)
1612 {
1613     OSL_ENSURE(m_eNodeType >= SQLNodeType::Rule && m_eNodeType <= SQLNodeType::Concat,"OSQLParseNode: created with invalid NodeType");
1614 }
1615 
OSQLParseNode(const OSQLParseNode & rParseNode)1616 OSQLParseNode::OSQLParseNode(const OSQLParseNode& rParseNode)
1617 {
1618     // Set the getParent to NULL
1619     m_pParent = nullptr;
1620 
1621     // Copy the members
1622     m_aNodeValue = rParseNode.m_aNodeValue;
1623     m_eNodeType  = rParseNode.m_eNodeType;
1624     m_nNodeID    = rParseNode.m_nNodeID;
1625 
1626 
1627     // Remember that we derived from Container. According to SV-Help the Container's
1628     // copy ctor creates a new Container with the same pointers for content.
1629     // This means after copying the Container, for all non-NULL pointers a copy is
1630     // created and reattached instead of the old pointer.
1631 
1632     // If not a leaf, then process SubTrees
1633     for (auto const& child : rParseNode.m_aChildren)
1634         append(new OSQLParseNode(*child));
1635 }
1636 
1637 
operator =(const OSQLParseNode & rParseNode)1638 OSQLParseNode& OSQLParseNode::operator=(const OSQLParseNode& rParseNode)
1639 {
1640     if (this != &rParseNode)
1641     {
1642         // Copy the members - pParent remains the same
1643         m_aNodeValue = rParseNode.m_aNodeValue;
1644         m_eNodeType  = rParseNode.m_eNodeType;
1645         m_nNodeID    = rParseNode.m_nNodeID;
1646 
1647         m_aChildren.clear();
1648 
1649         for (auto const& child : rParseNode.m_aChildren)
1650             append(new OSQLParseNode(*child));
1651     }
1652     return *this;
1653 }
1654 
1655 
operator ==(OSQLParseNode const & rParseNode) const1656 bool OSQLParseNode::operator==(OSQLParseNode const & rParseNode) const
1657 {
1658     // The members must be equal
1659     bool bResult = (m_nNodeID  == rParseNode.m_nNodeID) &&
1660                    (m_eNodeType == rParseNode.m_eNodeType) &&
1661                    (m_aNodeValue == rParseNode.m_aNodeValue) &&
1662                     count() == rParseNode.count();
1663 
1664     // Parameters are not equal!
1665     bResult = bResult && !SQL_ISRULE(this, parameter);
1666 
1667     // compare children
1668     for (size_t i=0; bResult && i < count(); i++)
1669         bResult = *getChild(i) == *rParseNode.getChild(i);
1670 
1671     return bResult;
1672 }
1673 
1674 
~OSQLParseNode()1675 OSQLParseNode::~OSQLParseNode()
1676 {
1677 }
1678 
append(OSQLParseNode * pNewNode)1679 void OSQLParseNode::append(OSQLParseNode* pNewNode)
1680 {
1681     assert(pNewNode != nullptr && "OSQLParseNode: invalid NewSubTree");
1682     OSL_ENSURE(pNewNode->getParent() == nullptr, "OSQLParseNode: Node is not an orphan");
1683     OSL_ENSURE(std::none_of(m_aChildren.begin(), m_aChildren.end(),
1684                    [&] (std::unique_ptr<OSQLParseNode> const & r) { return r.get() == pNewNode; }),
1685                "OSQLParseNode::append() Node already element of parent");
1686 
1687     // Create connection to getParent
1688     pNewNode->setParent( this );
1689     // and attach the SubTree at the end
1690     m_aChildren.emplace_back(pNewNode);
1691 }
1692 
addDateValue(OUStringBuffer & rString,const SQLParseNodeParameter & rParam) const1693 bool OSQLParseNode::addDateValue(OUStringBuffer& rString, const SQLParseNodeParameter& rParam) const
1694 {
1695     // special display for date/time values
1696     if (!SQL_ISRULE(this,set_fct_spec) || !SQL_ISPUNCTUATION(m_aChildren[0],"{"))
1697         return false;
1698 
1699     const OSQLParseNode* pODBCNode = m_aChildren[1].get();
1700     const OSQLParseNode* pODBCNodeChild = pODBCNode->m_aChildren[0].get();
1701 
1702     if (pODBCNodeChild->getNodeType() != SQLNodeType::Keyword || !(
1703         SQL_ISTOKEN(pODBCNodeChild, D) ||
1704         SQL_ISTOKEN(pODBCNodeChild, T) ||
1705         SQL_ISTOKEN(pODBCNodeChild, TS) ))
1706         return false;
1707 
1708     OUString suQuote(u"'"_ustr);
1709     if (rParam.bPredicate)
1710     {
1711          if (rParam.aMetaData.shouldEscapeDateTime())
1712          {
1713              suQuote = "#";
1714          }
1715     }
1716     else
1717     {
1718          if (rParam.aMetaData.shouldEscapeDateTime())
1719          {
1720              // suQuote = "'";
1721              return false;
1722          }
1723     }
1724 
1725     if (!rString.isEmpty())
1726         rString.append(" ");
1727     rString.append(suQuote);
1728     const OUString sTokenValue = pODBCNode->m_aChildren[1]->getTokenValue();
1729     if (SQL_ISTOKEN(pODBCNodeChild, D))
1730     {
1731         rString.append(rParam.bPredicate ? convertDateString(rParam, sTokenValue) : sTokenValue);
1732     }
1733     else if (SQL_ISTOKEN(pODBCNodeChild, T))
1734     {
1735         rString.append(rParam.bPredicate ? convertTimeString(rParam, sTokenValue) : sTokenValue);
1736     }
1737     else
1738     {
1739         rString.append(rParam.bPredicate ? convertDateTimeString(rParam, sTokenValue) : sTokenValue);
1740     }
1741     rString.append(suQuote);
1742     return true;
1743 }
1744 
replaceNodeValue(const OUString & rTableAlias,const OUString & rColumnName)1745 void OSQLParseNode::replaceNodeValue(const OUString& rTableAlias, const OUString& rColumnName)
1746 {
1747     for (size_t i=0;i<count();++i)
1748     {
1749         if (SQL_ISRULE(this,column_ref) && count() == 1 && getChild(0)->getTokenValue() == rColumnName)
1750         {
1751             OSQLParseNode * pCol = removeAt(sal_uInt32(0));
1752             append(new OSQLParseNode(rTableAlias,SQLNodeType::Name));
1753             append(new OSQLParseNode(".",SQLNodeType::Punctuation));
1754             append(pCol);
1755         }
1756         else
1757             getChild(i)->replaceNodeValue(rTableAlias,rColumnName);
1758     }
1759 }
1760 
getByRule(OSQLParseNode::Rule eRule) const1761 OSQLParseNode* OSQLParseNode::getByRule(OSQLParseNode::Rule eRule) const
1762 {
1763     OSQLParseNode* pRetNode = nullptr;
1764     if (isRule() && OSQLParser::RuleID(eRule) == getRuleID())
1765         pRetNode = const_cast<OSQLParseNode*>(this);
1766     else
1767     {
1768         for (auto const& child : m_aChildren)
1769         {
1770             pRetNode = child->getByRule(eRule);
1771             if (pRetNode)
1772                 break;
1773         }
1774     }
1775     return pRetNode;
1776 }
1777 
MakeANDNode(OSQLParseNode * pLeftLeaf,OSQLParseNode * pRightLeaf)1778 static OSQLParseNode* MakeANDNode(OSQLParseNode *pLeftLeaf,OSQLParseNode *pRightLeaf)
1779 {
1780     OSQLParseNode* pNewNode = new OSQLParseNode(OUString(),SQLNodeType::Rule,OSQLParser::RuleID(OSQLParseNode::boolean_term));
1781     pNewNode->append(pLeftLeaf);
1782     pNewNode->append(new OSQLParseNode("AND",SQLNodeType::Keyword,SQL_TOKEN_AND));
1783     pNewNode->append(pRightLeaf);
1784     return pNewNode;
1785 }
1786 
MakeORNode(OSQLParseNode * pLeftLeaf,OSQLParseNode * pRightLeaf)1787 static OSQLParseNode* MakeORNode(OSQLParseNode *pLeftLeaf,OSQLParseNode *pRightLeaf)
1788 {
1789     OSQLParseNode* pNewNode = new OSQLParseNode(OUString(),SQLNodeType::Rule,OSQLParser::RuleID(OSQLParseNode::search_condition));
1790     pNewNode->append(pLeftLeaf);
1791     pNewNode->append(new OSQLParseNode("OR",SQLNodeType::Keyword,SQL_TOKEN_OR));
1792     pNewNode->append(pRightLeaf);
1793     return pNewNode;
1794 }
1795 
disjunctiveNormalForm(OSQLParseNode * & pSearchCondition)1796 void OSQLParseNode::disjunctiveNormalForm(OSQLParseNode*& pSearchCondition)
1797 {
1798     if(!pSearchCondition) // no where condition at entry point
1799         return;
1800 
1801     OSQLParseNode::absorptions(pSearchCondition);
1802     // '(' search_condition ')'
1803     if (SQL_ISRULE(pSearchCondition,boolean_primary))
1804     {
1805         OSQLParseNode* pLeft    = pSearchCondition->getChild(1);
1806         disjunctiveNormalForm(pLeft);
1807     }
1808     // search_condition SQL_TOKEN_OR boolean_term
1809     else if (SQL_ISRULE(pSearchCondition,search_condition))
1810     {
1811         OSQLParseNode* pLeft    = pSearchCondition->getChild(0);
1812         disjunctiveNormalForm(pLeft);
1813 
1814         OSQLParseNode* pRight = pSearchCondition->getChild(2);
1815         disjunctiveNormalForm(pRight);
1816     }
1817     // boolean_term SQL_TOKEN_AND boolean_factor
1818     else if (SQL_ISRULE(pSearchCondition,boolean_term))
1819     {
1820         OSQLParseNode* pLeft    = pSearchCondition->getChild(0);
1821         disjunctiveNormalForm(pLeft);
1822 
1823         OSQLParseNode* pRight = pSearchCondition->getChild(2);
1824         disjunctiveNormalForm(pRight);
1825 
1826         OSQLParseNode* pNewNode = nullptr;
1827         // '(' search_condition ')' on left side
1828         if(pLeft->count() == 3 && SQL_ISRULE(pLeft,boolean_primary) && SQL_ISRULE(pLeft->getChild(1),search_condition))
1829         {
1830             // and-or tree  on left side
1831             OSQLParseNode* pOr = pLeft->getChild(1);
1832             OSQLParseNode* pNewLeft = nullptr;
1833             OSQLParseNode* pNewRight = nullptr;
1834 
1835             // cut right from parent
1836             OSQLParseNode* pOldRight = pSearchCondition->removeAt(2);
1837             assert(pOldRight == pRight);
1838 
1839             pNewRight   = MakeANDNode(pOr->removeAt(2), pOldRight);
1840             pNewLeft    = MakeANDNode(pOr->removeAt(sal_uInt32(0)), new OSQLParseNode(*pOldRight));
1841             pNewNode    = MakeORNode(pNewLeft,pNewRight);
1842             // and append new Node
1843             replaceAndReset(pSearchCondition,pNewNode);
1844 
1845             disjunctiveNormalForm(pSearchCondition);
1846         }
1847         else if(pRight->count() == 3 && SQL_ISRULE(pRight,boolean_primary) && SQL_ISRULE(pRight->getChild(1),search_condition))
1848         {   // '(' search_condition ')' on right side
1849             // and-or tree  on right side
1850             // a and (b or c)
1851             OSQLParseNode* pOr = pRight->getChild(1);
1852             OSQLParseNode* pNewLeft = nullptr;
1853             OSQLParseNode* pNewRight = nullptr;
1854 
1855             // cut left from parent
1856             OSQLParseNode* pOldLeft = pSearchCondition->removeAt(sal_uInt32(0));
1857             assert(pOldLeft == pLeft);
1858 
1859             pNewRight   = MakeANDNode(pOldLeft, pOr->removeAt(2));
1860             pNewLeft    = MakeANDNode(new OSQLParseNode(*pOldLeft), pOr->removeAt(sal_uInt32(0)));
1861             pNewNode    = MakeORNode(pNewLeft,pNewRight);
1862 
1863             // and append new Node
1864             replaceAndReset(pSearchCondition,pNewNode);
1865             disjunctiveNormalForm(pSearchCondition);
1866         }
1867         else if(SQL_ISRULE(pLeft,boolean_primary) && (!SQL_ISRULE(pLeft->getChild(1),search_condition) || !SQL_ISRULE(pLeft->getChild(1),boolean_term)))
1868             pSearchCondition->replaceAndDelete(pLeft, pLeft->removeAt(1));
1869         else if(SQL_ISRULE(pRight,boolean_primary) && (!SQL_ISRULE(pRight->getChild(1),search_condition) || !SQL_ISRULE(pRight->getChild(1),boolean_term)))
1870             pSearchCondition->replaceAndDelete(pRight, pRight->removeAt(1));
1871     }
1872 }
1873 
negateSearchCondition(OSQLParseNode * & pSearchCondition,bool bNegate)1874 void OSQLParseNode::negateSearchCondition(OSQLParseNode*& pSearchCondition, bool bNegate)
1875 {
1876     if(!pSearchCondition) // no where condition at entry point
1877         return;
1878     // '(' search_condition ')'
1879     if (pSearchCondition->count() == 3 && SQL_ISRULE(pSearchCondition,boolean_primary))
1880     {
1881         OSQLParseNode* pRight = pSearchCondition->getChild(1);
1882         negateSearchCondition(pRight,bNegate);
1883     }
1884     // search_condition SQL_TOKEN_OR boolean_term
1885     else if (SQL_ISRULE(pSearchCondition,search_condition))
1886     {
1887         OSQLParseNode* pLeft    = pSearchCondition->getChild(0);
1888         OSQLParseNode* pRight = pSearchCondition->getChild(2);
1889         if(bNegate)
1890         {
1891             OSQLParseNode* pNewNode = new OSQLParseNode(OUString(),SQLNodeType::Rule,OSQLParser::RuleID(OSQLParseNode::boolean_term));
1892             pNewNode->append(pSearchCondition->removeAt(sal_uInt32(0)));
1893             pNewNode->append(new OSQLParseNode("AND",SQLNodeType::Keyword,SQL_TOKEN_AND));
1894             pNewNode->append(pSearchCondition->removeAt(sal_uInt32(1)));
1895             replaceAndReset(pSearchCondition,pNewNode);
1896 
1897             pLeft   = pNewNode->getChild(0);
1898             pRight  = pNewNode->getChild(2);
1899         }
1900 
1901         negateSearchCondition(pLeft,bNegate);
1902         negateSearchCondition(pRight,bNegate);
1903     }
1904     // boolean_term SQL_TOKEN_AND boolean_factor
1905     else if (SQL_ISRULE(pSearchCondition,boolean_term))
1906     {
1907         OSQLParseNode* pLeft    = pSearchCondition->getChild(0);
1908         OSQLParseNode* pRight = pSearchCondition->getChild(2);
1909         if(bNegate)
1910         {
1911             OSQLParseNode* pNewNode = new OSQLParseNode(OUString(),SQLNodeType::Rule,OSQLParser::RuleID(OSQLParseNode::search_condition));
1912             pNewNode->append(pSearchCondition->removeAt(sal_uInt32(0)));
1913             pNewNode->append(new OSQLParseNode("OR",SQLNodeType::Keyword,SQL_TOKEN_OR));
1914             pNewNode->append(pSearchCondition->removeAt(sal_uInt32(1)));
1915             replaceAndReset(pSearchCondition,pNewNode);
1916 
1917             pLeft   = pNewNode->getChild(0);
1918             pRight  = pNewNode->getChild(2);
1919         }
1920 
1921         negateSearchCondition(pLeft,bNegate);
1922         negateSearchCondition(pRight,bNegate);
1923     }
1924     // SQL_TOKEN_NOT ( boolean_primary )
1925     else if (SQL_ISRULE(pSearchCondition,boolean_factor))
1926     {
1927         OSQLParseNode *pNot = pSearchCondition->removeAt(sal_uInt32(0));
1928         delete pNot;
1929         OSQLParseNode *pBooleanTest = pSearchCondition->removeAt(sal_uInt32(0));
1930         // TODO is this needed // pBooleanTest->setParent(NULL);
1931         replaceAndReset(pSearchCondition,pBooleanTest);
1932 
1933         if (!bNegate)
1934             negateSearchCondition(pSearchCondition, true); // negate all deeper values
1935     }
1936     // row_value_constructor comparison row_value_constructor
1937     // row_value_constructor comparison any_all_some subquery
1938     else if(bNegate && (SQL_ISRULE(pSearchCondition,comparison_predicate) || SQL_ISRULE(pSearchCondition,all_or_any_predicate)))
1939     {
1940         assert(pSearchCondition->count() == 3);
1941         OSQLParseNode* pComparison = pSearchCondition->getChild(1);
1942         if(SQL_ISRULE(pComparison, comparison))
1943         {
1944             assert(pComparison->count() == 2 ||
1945                    pComparison->count() == 4);
1946             assert(SQL_ISTOKEN(pComparison->getChild(0), IS));
1947 
1948             OSQLParseNode* pNot = pComparison->getChild(1);
1949             OSQLParseNode* pNotNot = nullptr;
1950             if(pNot->isRule()) // no NOT token (empty rule)
1951                 pNotNot = new OSQLParseNode("NOT",SQLNodeType::Keyword,SQL_TOKEN_NOT);
1952             else
1953             {
1954                 assert(SQL_ISTOKEN(pNot,NOT));
1955                 pNotNot = new OSQLParseNode(OUString(),SQLNodeType::Rule,OSQLParser::RuleID(OSQLParseNode::sql_not));
1956             }
1957             pComparison->replaceAndDelete(pNot, pNotNot);
1958         }
1959         else
1960         {
1961             OSQLParseNode* pNewComparison;
1962             switch(pComparison->getNodeType())
1963             {
1964             default:
1965             case SQLNodeType::Equal:
1966                 assert(pComparison->getNodeType() == SQLNodeType::Equal &&
1967                        "OSQLParseNode::negateSearchCondition: unexpected node type!");
1968                 pNewComparison = new OSQLParseNode("<>",SQLNodeType::NotEqual,SQL_NOTEQUAL);
1969                 break;
1970             case SQLNodeType::Less:
1971                 pNewComparison = new OSQLParseNode(">=",SQLNodeType::GreatEq,SQL_GREATEQ);
1972                 break;
1973             case SQLNodeType::Great:
1974                 pNewComparison = new OSQLParseNode("<=",SQLNodeType::LessEq,SQL_LESSEQ);
1975                 break;
1976             case SQLNodeType::LessEq:
1977                 pNewComparison = new OSQLParseNode(">",SQLNodeType::Great,SQL_GREAT);
1978                 break;
1979             case SQLNodeType::GreatEq:
1980                 pNewComparison = new OSQLParseNode("<",SQLNodeType::Less,SQL_LESS);
1981                 break;
1982             case SQLNodeType::NotEqual:
1983                 pNewComparison = new OSQLParseNode("=",SQLNodeType::Equal,SQL_EQUAL);
1984                 break;
1985             }
1986             pSearchCondition->replaceAndDelete(pComparison, pNewComparison);
1987         }
1988     }
1989 
1990     else if(bNegate && (SQL_ISRULE(pSearchCondition,test_for_null) ||
1991                         SQL_ISRULE(pSearchCondition,in_predicate)  ||
1992                         SQL_ISRULE(pSearchCondition,between_predicate) ))
1993     {
1994         OSQLParseNode* pPart2 = pSearchCondition->getChild(1);
1995         sal_uInt32 nNotPos = 0;
1996         if  ( SQL_ISRULE( pSearchCondition, test_for_null ) )
1997             nNotPos = 1;
1998 
1999         OSQLParseNode* pNot = pPart2->getChild(nNotPos);
2000         OSQLParseNode* pNotNot = nullptr;
2001         if(pNot->isRule()) // no NOT token (empty rule)
2002             pNotNot = new OSQLParseNode("NOT",SQLNodeType::Keyword,SQL_TOKEN_NOT);
2003         else
2004         {
2005             assert(SQL_ISTOKEN(pNot,NOT));
2006             pNotNot = new OSQLParseNode(OUString(),SQLNodeType::Rule,OSQLParser::RuleID(OSQLParseNode::sql_not));
2007         }
2008         pPart2->replaceAndDelete(pNot, pNotNot);
2009     }
2010     else if(bNegate && SQL_ISRULE(pSearchCondition,like_predicate))
2011     {
2012         OSQLParseNode* pNot = pSearchCondition->getChild( 1 )->getChild( 0 );
2013         OSQLParseNode* pNotNot = nullptr;
2014         if(pNot->isRule())
2015             pNotNot = new OSQLParseNode("NOT",SQLNodeType::Keyword,SQL_TOKEN_NOT);
2016         else
2017             pNotNot = new OSQLParseNode(OUString(),SQLNodeType::Rule,OSQLParser::RuleID(OSQLParseNode::sql_not));
2018         pSearchCondition->getChild( 1 )->replaceAndDelete(pNot, pNotNot);
2019     }
2020 }
2021 
eraseBraces(OSQLParseNode * & pSearchCondition)2022 void OSQLParseNode::eraseBraces(OSQLParseNode*& pSearchCondition)
2023 {
2024     if (!(pSearchCondition && (SQL_ISRULE(pSearchCondition,boolean_primary) || (pSearchCondition->count() == 3 && SQL_ISPUNCTUATION(pSearchCondition->getChild(0),"(") &&
2025          SQL_ISPUNCTUATION(pSearchCondition->getChild(2),")")))))
2026         return;
2027 
2028     OSQLParseNode* pRight = pSearchCondition->getChild(1);
2029     absorptions(pRight);
2030     // if child is not an or and tree then delete () around child
2031     if(!(SQL_ISRULE(pSearchCondition->getChild(1),boolean_term) || SQL_ISRULE(pSearchCondition->getChild(1),search_condition)) ||
2032         SQL_ISRULE(pSearchCondition->getChild(1),boolean_term) || // and can always stand without ()
2033         (SQL_ISRULE(pSearchCondition->getChild(1),search_condition) && SQL_ISRULE(pSearchCondition->getParent(),search_condition)))
2034     {
2035         OSQLParseNode* pNode = pSearchCondition->removeAt(1);
2036         replaceAndReset(pSearchCondition,pNode);
2037     }
2038 }
2039 
absorptions(OSQLParseNode * & pSearchCondition)2040 void OSQLParseNode::absorptions(OSQLParseNode*& pSearchCondition)
2041 {
2042     if(!pSearchCondition) // no where condition at entry point
2043         return;
2044 
2045     eraseBraces(pSearchCondition);
2046 
2047     if(SQL_ISRULE(pSearchCondition,boolean_term) || SQL_ISRULE(pSearchCondition,search_condition))
2048     {
2049         OSQLParseNode* pLeft = pSearchCondition->getChild(0);
2050         absorptions(pLeft);
2051         OSQLParseNode* pRight = pSearchCondition->getChild(2);
2052         absorptions(pRight);
2053     }
2054 
2055     sal_uInt32 nPos = 0;
2056     // a and a || a or a
2057     OSQLParseNode* pNewNode = nullptr;
2058     if(( SQL_ISRULE(pSearchCondition,boolean_term) || SQL_ISRULE(pSearchCondition,search_condition))
2059         && *pSearchCondition->getChild(0) == *pSearchCondition->getChild(2))
2060     {
2061         pNewNode = pSearchCondition->removeAt(sal_uInt32(0));
2062         replaceAndReset(pSearchCondition,pNewNode);
2063     }
2064     // ( a or b ) and a || ( b or c ) and a
2065     // a and ( a or b ) || a and ( b or c )
2066     else if (   SQL_ISRULE(pSearchCondition,boolean_term)
2067             &&  (
2068                     (       SQL_ISRULE(pSearchCondition->getChild(nPos = 0),boolean_primary)
2069                         ||  SQL_ISRULE(pSearchCondition->getChild(nPos),search_condition)
2070                     )
2071                 ||  (       SQL_ISRULE(pSearchCondition->getChild(nPos = 2),boolean_primary)
2072                         ||  SQL_ISRULE(pSearchCondition->getChild(nPos),search_condition)
2073                     )
2074                 )
2075             )
2076     {
2077         OSQLParseNode* p2ndSearch = pSearchCondition->getChild(nPos);
2078         if ( SQL_ISRULE(p2ndSearch,boolean_primary) )
2079             p2ndSearch = p2ndSearch->getChild(1);
2080 
2081         if ( *p2ndSearch->getChild(0) == *pSearchCondition->getChild(2-nPos) ) // a and ( a or b) -> a or b
2082         {
2083             pNewNode = pSearchCondition->removeAt(sal_uInt32(0));
2084             replaceAndReset(pSearchCondition,pNewNode);
2085 
2086         }
2087         else if ( *p2ndSearch->getChild(2) == *pSearchCondition->getChild(2-nPos) ) // a and ( b or a) -> a or b
2088         {
2089             pNewNode = pSearchCondition->removeAt(sal_uInt32(2));
2090             replaceAndReset(pSearchCondition,pNewNode);
2091         }
2092         else if ( p2ndSearch->getByRule(OSQLParseNode::search_condition) )
2093         {
2094             // a and ( b or c ) -> ( a and b ) or ( a and c )
2095             // ( b or c ) and a -> ( a and b ) or ( a and c )
2096             OSQLParseNode* pC = p2ndSearch->removeAt(sal_uInt32(2));
2097             OSQLParseNode* pB = p2ndSearch->removeAt(sal_uInt32(0));
2098             OSQLParseNode* pA = pSearchCondition->removeAt(sal_uInt32(2)-nPos);
2099 
2100             OSQLParseNode* p1stAnd = MakeANDNode(pA,pB);
2101             OSQLParseNode* p2ndAnd = MakeANDNode(new OSQLParseNode(*pA),pC);
2102             pNewNode = MakeORNode(p1stAnd,p2ndAnd);
2103             OSQLParseNode* pNode = new OSQLParseNode(OUString(),SQLNodeType::Rule,OSQLParser::RuleID(OSQLParseNode::boolean_primary));
2104             pNode->append(new OSQLParseNode("(",SQLNodeType::Punctuation));
2105             pNode->append(pNewNode);
2106             pNode->append(new OSQLParseNode(")",SQLNodeType::Punctuation));
2107             OSQLParseNode::eraseBraces(p1stAnd);
2108             OSQLParseNode::eraseBraces(p2ndAnd);
2109             replaceAndReset(pSearchCondition,pNode);
2110         }
2111     }
2112     // a or a and b || a or b and a
2113     else if(SQL_ISRULE(pSearchCondition,search_condition) && SQL_ISRULE(pSearchCondition->getChild(2),boolean_term))
2114     {
2115         if(*pSearchCondition->getChild(2)->getChild(0) == *pSearchCondition->getChild(0))
2116         {
2117             pNewNode = pSearchCondition->removeAt(sal_uInt32(0));
2118             replaceAndReset(pSearchCondition,pNewNode);
2119         }
2120         else if(*pSearchCondition->getChild(2)->getChild(2) == *pSearchCondition->getChild(0))
2121         {
2122             pNewNode = pSearchCondition->removeAt(sal_uInt32(0));
2123             replaceAndReset(pSearchCondition,pNewNode);
2124         }
2125     }
2126     // a and b or a || b and a or a
2127     else if(SQL_ISRULE(pSearchCondition,search_condition) && SQL_ISRULE(pSearchCondition->getChild(0),boolean_term))
2128     {
2129         if(*pSearchCondition->getChild(0)->getChild(0) == *pSearchCondition->getChild(2))
2130         {
2131             pNewNode = pSearchCondition->removeAt(sal_uInt32(2));
2132             replaceAndReset(pSearchCondition,pNewNode);
2133         }
2134         else if(*pSearchCondition->getChild(0)->getChild(2) == *pSearchCondition->getChild(2))
2135         {
2136             pNewNode = pSearchCondition->removeAt(sal_uInt32(2));
2137             replaceAndReset(pSearchCondition,pNewNode);
2138         }
2139     }
2140     eraseBraces(pSearchCondition);
2141 }
2142 
compress(OSQLParseNode * & pSearchCondition)2143 void OSQLParseNode::compress(OSQLParseNode *&pSearchCondition)
2144 {
2145     if(!pSearchCondition) // no WHERE condition at entry point
2146         return;
2147 
2148     OSQLParseNode::eraseBraces(pSearchCondition);
2149 
2150     if(SQL_ISRULE(pSearchCondition,boolean_term) || SQL_ISRULE(pSearchCondition,search_condition))
2151     {
2152         OSQLParseNode* pLeft = pSearchCondition->getChild(0);
2153         compress(pLeft);
2154 
2155         OSQLParseNode* pRight = pSearchCondition->getChild(2);
2156         compress(pRight);
2157     }
2158     else if( SQL_ISRULE(pSearchCondition,boolean_primary) || (pSearchCondition->count() == 3 && SQL_ISPUNCTUATION(pSearchCondition->getChild(0),"(") &&
2159              SQL_ISPUNCTUATION(pSearchCondition->getChild(2),")")))
2160     {
2161         OSQLParseNode* pRight = pSearchCondition->getChild(1);
2162         compress(pRight);
2163         // if child is not an or and tree then delete () around child
2164         if(!(SQL_ISRULE(pSearchCondition->getChild(1),boolean_term) || SQL_ISRULE(pSearchCondition->getChild(1),search_condition)) ||
2165             (SQL_ISRULE(pSearchCondition->getChild(1),boolean_term) && SQL_ISRULE(pSearchCondition->getParent(),boolean_term)) ||
2166             (SQL_ISRULE(pSearchCondition->getChild(1),search_condition) && SQL_ISRULE(pSearchCondition->getParent(),search_condition)))
2167         {
2168             OSQLParseNode* pNode = pSearchCondition->removeAt(1);
2169             replaceAndReset(pSearchCondition,pNode);
2170         }
2171     }
2172 
2173     // or with two and trees where one element of the and trees are equal
2174     if(!(SQL_ISRULE(pSearchCondition,search_condition) && SQL_ISRULE(pSearchCondition->getChild(0),boolean_term) && SQL_ISRULE(pSearchCondition->getChild(2),boolean_term)))
2175         return;
2176 
2177     if(*pSearchCondition->getChild(0)->getChild(0) == *pSearchCondition->getChild(2)->getChild(0))
2178     {
2179         OSQLParseNode* pLeft    = pSearchCondition->getChild(0)->removeAt(2);
2180         OSQLParseNode* pRight = pSearchCondition->getChild(2)->removeAt(2);
2181         OSQLParseNode* pNode    = MakeORNode(pLeft,pRight);
2182 
2183         OSQLParseNode* pNewRule = new OSQLParseNode(OUString(),SQLNodeType::Rule,OSQLParser::RuleID(OSQLParseNode::boolean_primary));
2184         pNewRule->append(new OSQLParseNode("(",SQLNodeType::Punctuation));
2185         pNewRule->append(pNode);
2186         pNewRule->append(new OSQLParseNode(")",SQLNodeType::Punctuation));
2187 
2188         OSQLParseNode::eraseBraces(pLeft);
2189         OSQLParseNode::eraseBraces(pRight);
2190 
2191         pNode = MakeANDNode(pSearchCondition->getChild(0)->removeAt(sal_uInt32(0)),pNewRule);
2192         replaceAndReset(pSearchCondition,pNode);
2193     }
2194     else if(*pSearchCondition->getChild(0)->getChild(2) == *pSearchCondition->getChild(2)->getChild(0))
2195     {
2196         OSQLParseNode* pLeft = pSearchCondition->getChild(0)->removeAt(sal_uInt32(0));
2197         OSQLParseNode* pRight = pSearchCondition->getChild(2)->removeAt(2);
2198         OSQLParseNode* pNode = MakeORNode(pLeft,pRight);
2199 
2200         OSQLParseNode* pNewRule = new OSQLParseNode(OUString(),SQLNodeType::Rule,OSQLParser::RuleID(OSQLParseNode::boolean_primary));
2201         pNewRule->append(new OSQLParseNode("(",SQLNodeType::Punctuation));
2202         pNewRule->append(pNode);
2203         pNewRule->append(new OSQLParseNode(")",SQLNodeType::Punctuation));
2204 
2205         OSQLParseNode::eraseBraces(pLeft);
2206         OSQLParseNode::eraseBraces(pRight);
2207 
2208         pNode = MakeANDNode(pSearchCondition->getChild(0)->removeAt(1),pNewRule);
2209         replaceAndReset(pSearchCondition,pNode);
2210     }
2211     else if(*pSearchCondition->getChild(0)->getChild(0) == *pSearchCondition->getChild(2)->getChild(2))
2212     {
2213         OSQLParseNode* pLeft    = pSearchCondition->getChild(0)->removeAt(2);
2214         OSQLParseNode* pRight = pSearchCondition->getChild(2)->removeAt(sal_uInt32(0));
2215         OSQLParseNode* pNode    = MakeORNode(pLeft,pRight);
2216 
2217         OSQLParseNode* pNewRule = new OSQLParseNode(OUString(),SQLNodeType::Rule,OSQLParser::RuleID(OSQLParseNode::boolean_primary));
2218         pNewRule->append(new OSQLParseNode("(",SQLNodeType::Punctuation));
2219         pNewRule->append(pNode);
2220         pNewRule->append(new OSQLParseNode(")",SQLNodeType::Punctuation));
2221 
2222         OSQLParseNode::eraseBraces(pLeft);
2223         OSQLParseNode::eraseBraces(pRight);
2224 
2225         pNode = MakeANDNode(pSearchCondition->getChild(0)->removeAt(sal_uInt32(0)),pNewRule);
2226         replaceAndReset(pSearchCondition,pNode);
2227     }
2228     else if(*pSearchCondition->getChild(0)->getChild(2) == *pSearchCondition->getChild(2)->getChild(2))
2229     {
2230         OSQLParseNode* pLeft    = pSearchCondition->getChild(0)->removeAt(sal_uInt32(0));
2231         OSQLParseNode* pRight = pSearchCondition->getChild(2)->removeAt(sal_uInt32(0));
2232         OSQLParseNode* pNode    = MakeORNode(pLeft,pRight);
2233 
2234         OSQLParseNode* pNewRule = new OSQLParseNode(OUString(),SQLNodeType::Rule,OSQLParser::RuleID(OSQLParseNode::boolean_primary));
2235         pNewRule->append(new OSQLParseNode("(",SQLNodeType::Punctuation));
2236         pNewRule->append(pNode);
2237         pNewRule->append(new OSQLParseNode(")",SQLNodeType::Punctuation));
2238 
2239         OSQLParseNode::eraseBraces(pLeft);
2240         OSQLParseNode::eraseBraces(pRight);
2241 
2242         pNode = MakeANDNode(pSearchCondition->getChild(0)->removeAt(1),pNewRule);
2243         replaceAndReset(pSearchCondition,pNode);
2244     }
2245 }
2246 #if OSL_DEBUG_LEVEL > 1
2247 
showParseTree(OUString & rString) const2248 void OSQLParseNode::showParseTree( OUString& rString ) const
2249 {
2250     OUStringBuffer aBuf;
2251     showParseTree( aBuf, 0 );
2252     rString = aBuf.makeStringAndClear();
2253 }
2254 
2255 
showParseTree(OUStringBuffer & _inout_rBuffer,sal_uInt32 nLevel) const2256 void OSQLParseNode::showParseTree( OUStringBuffer& _inout_rBuffer, sal_uInt32 nLevel ) const
2257 {
2258     for ( sal_uInt32 j=0; j<nLevel; ++j)
2259         _inout_rBuffer.appendAscii( "  " );
2260 
2261     if ( !isToken() )
2262     {
2263         // Rule name as rule
2264         _inout_rBuffer.appendAscii( "RULE_ID: " );
2265         _inout_rBuffer.append( (sal_Int32)getRuleID() );
2266         _inout_rBuffer.append( '(' );
2267         _inout_rBuffer.append( OSQLParser::RuleIDToStr( getRuleID() ) );
2268         _inout_rBuffer.append( ')' );
2269         _inout_rBuffer.append( '\n' );
2270 
2271         // Get the first sub tree
2272         for (auto const& child : m_aChildren)
2273             child->showParseTree( _inout_rBuffer, nLevel+1 );
2274     }
2275     else
2276     {
2277         // Found a token
2278         switch (m_eNodeType)
2279         {
2280 
2281         case SQLNodeType::Keyword:
2282             _inout_rBuffer.appendAscii( "SQL_KEYWORD: " );
2283             _inout_rBuffer.append( OStringToOUString( OSQLParser::TokenIDToStr( getTokenID() ), RTL_TEXTENCODING_UTF8 ) );
2284             _inout_rBuffer.append( '\n' );
2285             break;
2286 
2287         case SQLNodeType::Name:
2288             _inout_rBuffer.appendAscii( "SQL_NAME: " );
2289             _inout_rBuffer.append( '"' );
2290             _inout_rBuffer.append( m_aNodeValue );
2291             _inout_rBuffer.append( '"' );
2292             _inout_rBuffer.append( '\n' );
2293              break;
2294 
2295         case SQLNodeType::String:
2296             _inout_rBuffer.appendAscii( "SQL_STRING: " );
2297             _inout_rBuffer.append( '\'' );
2298             _inout_rBuffer.append( m_aNodeValue );
2299             _inout_rBuffer.append( '\'' );
2300             _inout_rBuffer.append( '\n' );
2301             break;
2302 
2303         case SQLNodeType::IntNum:
2304             _inout_rBuffer.appendAscii( "SQL_INTNUM: " );
2305             _inout_rBuffer.append( m_aNodeValue );
2306             _inout_rBuffer.append( '\n' );
2307             break;
2308 
2309         case SQLNodeType::ApproxNum:
2310             _inout_rBuffer.appendAscii( "SQL_APPROXNUM: " );
2311             _inout_rBuffer.append( m_aNodeValue );
2312             _inout_rBuffer.append( '\n' );
2313              break;
2314 
2315         case SQLNodeType::Punctuation:
2316             _inout_rBuffer.appendAscii( "SQL_PUNCTUATION: " );
2317             _inout_rBuffer.append( m_aNodeValue );
2318             _inout_rBuffer.append( '\n' );
2319             break;
2320 
2321         case SQLNodeType::Equal:
2322         case SQLNodeType::Less:
2323         case SQLNodeType::Great:
2324         case SQLNodeType::LessEq:
2325         case SQLNodeType::GreatEq:
2326         case SQLNodeType::NotEqual:
2327             _inout_rBuffer.append( m_aNodeValue );
2328             _inout_rBuffer.append( '\n' );
2329             break;
2330 
2331         case SQLNodeType::AccessDate:
2332             _inout_rBuffer.appendAscii( "SQL_ACCESS_DATE: " );
2333             _inout_rBuffer.append( m_aNodeValue );
2334             _inout_rBuffer.append( '\n' );
2335             break;
2336 
2337         case SQLNodeType::Concat:
2338             _inout_rBuffer.appendAscii( "||" );
2339             _inout_rBuffer.append( '\n' );
2340             break;
2341 
2342         default:
2343             SAL_INFO( "connectivity.parse", "-- " << int( m_eNodeType ) );
2344             SAL_WARN( "connectivity.parse", "OSQLParser::ShowParseTree: unzulaessiger NodeType" );
2345         }
2346     }
2347 }
2348 #endif // OSL_DEBUG_LEVEL > 0
2349 
2350 // Insert methods
2351 
insert(sal_uInt32 nPos,OSQLParseNode * pNewSubTree)2352 void OSQLParseNode::insert(sal_uInt32 nPos, OSQLParseNode* pNewSubTree)
2353 {
2354     assert(pNewSubTree != nullptr && "OSQLParseNode: invalid NewSubTree");
2355     OSL_ENSURE(pNewSubTree->getParent() == nullptr, "OSQLParseNode: Node is not an orphan");
2356 
2357     // Create connection to getParent
2358     pNewSubTree->setParent( this );
2359     m_aChildren.emplace(m_aChildren.begin() + nPos, pNewSubTree);
2360 }
2361 
2362 // removeAt methods
2363 
removeAt(sal_uInt32 nPos)2364 OSQLParseNode* OSQLParseNode::removeAt(sal_uInt32 nPos)
2365 {
2366     assert(nPos < m_aChildren.size() && "Illegal position for removeAt");
2367     auto aPos(m_aChildren.begin() + nPos);
2368     auto pNode = std::move(*aPos);
2369 
2370     // Set the getParent of the removed node to NULL
2371     pNode->setParent( nullptr );
2372 
2373     m_aChildren.erase(aPos);
2374     return pNode.release();
2375 }
2376 
2377 // Replace methods
2378 
replaceAndDelete(OSQLParseNode * pOldSubNode,OSQLParseNode * pNewSubNode)2379 void OSQLParseNode::replaceAndDelete(OSQLParseNode* pOldSubNode, OSQLParseNode* pNewSubNode )
2380 {
2381     assert(pOldSubNode != nullptr && pNewSubNode != nullptr && "OSQLParseNode: invalid nodes");
2382     assert(pOldSubNode != pNewSubNode && "OSQLParseNode: same node");
2383     assert(pNewSubNode->getParent() == nullptr && "OSQLParseNode: node already has getParent");
2384     assert(std::any_of(m_aChildren.begin(), m_aChildren.end(),
2385                    [&] (std::unique_ptr<OSQLParseNode> const & r) { return r.get() == pOldSubNode; })
2386                && "OSQLParseNode::Replace() Node not element of parent");
2387     assert(std::none_of(m_aChildren.begin(), m_aChildren.end(),
2388                    [&] (std::unique_ptr<OSQLParseNode> const & r) { return r.get() == pNewSubNode; })
2389                && "OSQLParseNode::Replace() Node already element of parent");
2390 
2391     pOldSubNode->setParent( nullptr );
2392     pNewSubNode->setParent( this );
2393     auto it = std::find_if(m_aChildren.begin(), m_aChildren.end(),
2394         [&pOldSubNode](const std::unique_ptr<OSQLParseNode>& rxChild) { return rxChild.get() == pOldSubNode; });
2395     assert(it != m_aChildren.end());
2396     it->reset(pNewSubNode);
2397 }
2398 
parseLeaf(OUStringBuffer & rString,const SQLParseNodeParameter & rParam) const2399 void OSQLParseNode::parseLeaf(OUStringBuffer& rString, const SQLParseNodeParameter& rParam) const
2400 {
2401     // Found a leaf
2402     // Append content to the output string
2403     switch (m_eNodeType)
2404     {
2405         case SQLNodeType::Keyword:
2406         {
2407             if (!rString.isEmpty())
2408                 rString.append(" ");
2409 
2410             const OString sT = OSQLParser::TokenIDToStr(m_nNodeID, rParam.bInternational ? &rParam.m_rContext :  nullptr);
2411             rString.append(OStringToOUString(sT,RTL_TEXTENCODING_UTF8));
2412         }   break;
2413         case SQLNodeType::String:
2414             if (!rString.isEmpty())
2415                 rString.append(" ");
2416             rString.append(SetQuotation(m_aNodeValue, u"\'", u"\'\'"));
2417             break;
2418         case SQLNodeType::Name:
2419             if (!rString.isEmpty())
2420             {
2421                 switch(rString[rString.getLength()-1])
2422                 {
2423                     case ' ' :
2424                     case '.' : break;
2425                     default  :
2426                         if  (   rParam.aMetaData.getCatalogSeparator().isEmpty()
2427                                 || rString[rString.getLength() - 1] != rParam.aMetaData.getCatalogSeparator().toChar()
2428                             )
2429                             rString.append(" ");
2430                         break;
2431                 }
2432             }
2433             if (rParam.bQuote)
2434             {
2435                 if (rParam.bPredicate)
2436                 {
2437                     rString.append("[");
2438                     rString.append(m_aNodeValue);
2439                     rString.append("]");
2440                 }
2441                 else
2442                     rString.append(SetQuotation(m_aNodeValue,
2443                         rParam.aMetaData.getIdentifierQuoteString(), rParam.aMetaData.getIdentifierQuoteString() ));
2444             }
2445             else
2446                 rString.append(m_aNodeValue);
2447             break;
2448         case SQLNodeType::AccessDate:
2449             if (!rString.isEmpty())
2450                 rString.append(" ");
2451             rString.append("#");
2452             rString.append(m_aNodeValue);
2453             rString.append("#");
2454             break;
2455 
2456         case SQLNodeType::IntNum:
2457         case SQLNodeType::ApproxNum:
2458             {
2459                 OUString aTmp = m_aNodeValue;
2460                 static constexpr OUString strPoint(u"."_ustr);
2461                 if (rParam.bInternational && rParam.bPredicate && rParam.sDecSep != strPoint)
2462                     aTmp = aTmp.replaceAll(strPoint, rParam.sDecSep);
2463 
2464                 if (!rString.isEmpty())
2465                     rString.append(" ");
2466                 rString.append(aTmp);
2467 
2468             }   break;
2469         case SQLNodeType::Punctuation:
2470             if ( getParent() && SQL_ISRULE(getParent(),cast_spec) && m_aNodeValue.toChar() == '(' ) // no spaces in front of '('
2471             {
2472                 rString.append(m_aNodeValue);
2473                 break;
2474             }
2475             [[fallthrough]];
2476         default:
2477             if (!rString.isEmpty() && m_aNodeValue.toChar() != '.' && m_aNodeValue.toChar() != ':' )
2478             {
2479                 switch( rString[rString.getLength() - 1] )
2480                 {
2481                     case ' ' :
2482                     case '.' : break;
2483                     default  :
2484                         if  (   rParam.aMetaData.getCatalogSeparator().isEmpty()
2485                             ||  rString[rString.getLength() - 1] != rParam.aMetaData.getCatalogSeparator().toChar()
2486                             )
2487                             rString.append(" ");
2488                         break;
2489                 }
2490             }
2491             rString.append(m_aNodeValue);
2492     }
2493 }
2494 
2495 
getFunctionReturnType(std::u16string_view _sFunctionName,const IParseContext * pContext)2496 sal_Int32 OSQLParser::getFunctionReturnType(std::u16string_view _sFunctionName, const IParseContext* pContext)
2497 {
2498     sal_Int32 nType = DataType::SQLNULL;
2499     OString sFunctionName(OUStringToOString(_sFunctionName,RTL_TEXTENCODING_UTF8));
2500 
2501     if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_ASCII,pContext)))                     nType = DataType::INTEGER;
2502     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_BIT_LENGTH,pContext)))           nType = DataType::INTEGER;
2503     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_CHAR,pContext)))                 nType = DataType::VARCHAR;
2504     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_CHAR_LENGTH,pContext)))          nType = DataType::INTEGER;
2505     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_CONCAT,pContext)))               nType = DataType::VARCHAR;
2506     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_DIFFERENCE,pContext)))           nType = DataType::VARCHAR;
2507     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_INSERT,pContext)))               nType = DataType::VARCHAR;
2508     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_LCASE,pContext)))                nType = DataType::VARCHAR;
2509     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_LEFT,pContext)))                 nType = DataType::VARCHAR;
2510     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_LENGTH,pContext)))               nType = DataType::INTEGER;
2511     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_LOCATE,pContext)))               nType = DataType::VARCHAR;
2512     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_LOCATE_2,pContext)))             nType = DataType::VARCHAR;
2513     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_LTRIM,pContext)))                nType = DataType::VARCHAR;
2514     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_OCTET_LENGTH,pContext)))         nType = DataType::INTEGER;
2515     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_POSITION,pContext)))             nType = DataType::INTEGER;
2516     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_REPEAT,pContext)))               nType = DataType::VARCHAR;
2517     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_REPLACE,pContext)))              nType = DataType::VARCHAR;
2518     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_RIGHT,pContext)))                nType = DataType::VARCHAR;
2519     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_RTRIM,pContext)))                nType = DataType::VARCHAR;
2520     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_SOUNDEX,pContext)))              nType = DataType::VARCHAR;
2521     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_SPACE,pContext)))                nType = DataType::VARCHAR;
2522     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_SUBSTRING,pContext)))            nType = DataType::VARCHAR;
2523     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_UCASE,pContext)))                nType = DataType::VARCHAR;
2524     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_CURRENT_DATE,pContext)))         nType = DataType::DATE;
2525     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_CURRENT_TIME,pContext)))         nType = DataType::TIME;
2526     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_CURRENT_TIMESTAMP,pContext)))    nType = DataType::TIMESTAMP;
2527     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_CURDATE,pContext)))              nType = DataType::DATE;
2528     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_DATEDIFF,pContext)))             nType = DataType::INTEGER;
2529     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_DATEVALUE,pContext)))            nType = DataType::DATE;
2530     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_CURTIME,pContext)))              nType = DataType::TIME;
2531     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_DAYNAME,pContext)))              nType = DataType::VARCHAR;
2532     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_DAYOFMONTH,pContext)))           nType = DataType::INTEGER;
2533     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_DAYOFWEEK,pContext)))            nType = DataType::INTEGER;
2534     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_DAYOFYEAR,pContext)))            nType = DataType::INTEGER;
2535     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_EXTRACT,pContext)))              nType = DataType::VARCHAR;
2536     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_HOUR,pContext)))                 nType = DataType::INTEGER;
2537     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_MINUTE,pContext)))               nType = DataType::INTEGER;
2538     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_MONTH,pContext)))                nType = DataType::INTEGER;
2539     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_MONTHNAME,pContext)))            nType = DataType::VARCHAR;
2540     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_NOW,pContext)))                  nType = DataType::TIMESTAMP;
2541     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_QUARTER,pContext)))              nType = DataType::INTEGER;
2542     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_SECOND,pContext)))               nType = DataType::INTEGER;
2543     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_TIMESTAMPADD,pContext)))         nType = DataType::TIMESTAMP;
2544     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_TIMESTAMPDIFF,pContext)))        nType = DataType::TIMESTAMP;
2545     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_TIMEVALUE,pContext)))            nType = DataType::TIMESTAMP;
2546     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_WEEK,pContext)))                 nType = DataType::INTEGER;
2547     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_YEAR,pContext)))                 nType = DataType::INTEGER;
2548     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_ABS,pContext)))                  nType = DataType::DOUBLE;
2549     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_ACOS,pContext)))                 nType = DataType::DOUBLE;
2550     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_ASIN,pContext)))                 nType = DataType::DOUBLE;
2551     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_ATAN,pContext)))                 nType = DataType::DOUBLE;
2552     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_ATAN2,pContext)))                nType = DataType::DOUBLE;
2553     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_CEILING,pContext)))              nType = DataType::DOUBLE;
2554     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_COS,pContext)))                  nType = DataType::DOUBLE;
2555     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_COT,pContext)))                  nType = DataType::DOUBLE;
2556     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_DEGREES,pContext)))              nType = DataType::DOUBLE;
2557     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_EXP,pContext)))                  nType = DataType::DOUBLE;
2558     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_FLOOR,pContext)))                nType = DataType::DOUBLE;
2559     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_LOGF,pContext)))                 nType = DataType::DOUBLE;
2560     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_LOG,pContext)))                  nType = DataType::DOUBLE;
2561     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_LOG10,pContext)))                nType = DataType::DOUBLE;
2562     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_LN,pContext)))                   nType = DataType::DOUBLE;
2563     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_MOD,pContext)))                  nType = DataType::DOUBLE;
2564     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_PI,pContext)))                   nType = DataType::DOUBLE;
2565     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_POWER,pContext)))                nType = DataType::DOUBLE;
2566     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_RADIANS,pContext)))              nType = DataType::DOUBLE;
2567     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_RAND,pContext)))                 nType = DataType::DOUBLE;
2568     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_ROUND,pContext)))                nType = DataType::DOUBLE;
2569     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_ROUNDMAGIC,pContext)))           nType = DataType::DOUBLE;
2570     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_SIGN,pContext)))                 nType = DataType::DOUBLE;
2571     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_SIN,pContext)))                  nType = DataType::DOUBLE;
2572     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_SQRT,pContext)))                 nType = DataType::DOUBLE;
2573     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_TAN,pContext)))                  nType = DataType::DOUBLE;
2574     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_TRUNCATE,pContext)))             nType = DataType::DOUBLE;
2575     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_COUNT,pContext)))                nType = DataType::INTEGER;
2576     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_MAX,pContext)))                  nType = DataType::DOUBLE;
2577     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_MIN,pContext)))                  nType = DataType::DOUBLE;
2578     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_AVG,pContext)))                  nType = DataType::DOUBLE;
2579     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_SUM,pContext)))                  nType = DataType::DOUBLE;
2580     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_LOWER,pContext)))                nType = DataType::VARCHAR;
2581     else if(sFunctionName.equalsIgnoreAsciiCase(TokenIDToStr(SQL_TOKEN_UPPER,pContext)))                nType = DataType::VARCHAR;
2582 
2583     return nType;
2584 }
2585 
getFunctionParameterType(sal_uInt32 _nTokenId,sal_uInt32 _nPos)2586 sal_Int32 OSQLParser::getFunctionParameterType(sal_uInt32 _nTokenId, sal_uInt32 _nPos)
2587 {
2588     sal_Int32 nType = DataType::VARCHAR;
2589 
2590     if(_nTokenId == SQL_TOKEN_CHAR)                 nType = DataType::INTEGER;
2591     else if(_nTokenId == SQL_TOKEN_INSERT)
2592     {
2593         if ( _nPos == 2 || _nPos == 3 )
2594             nType = DataType::INTEGER;
2595     }
2596     else if(_nTokenId == SQL_TOKEN_LEFT)
2597     {
2598         if ( _nPos == 2 )
2599             nType = DataType::INTEGER;
2600     }
2601     else if(_nTokenId == SQL_TOKEN_LOCATE)
2602     {
2603         if ( _nPos == 3 )
2604             nType = DataType::INTEGER;
2605     }
2606     else if(_nTokenId == SQL_TOKEN_LOCATE_2)
2607     {
2608         if ( _nPos == 3 )
2609             nType = DataType::INTEGER;
2610     }
2611     else if( _nTokenId == SQL_TOKEN_REPEAT || _nTokenId == SQL_TOKEN_RIGHT )
2612     {
2613         if ( _nPos == 2 )
2614             nType = DataType::INTEGER;
2615     }
2616     else if(_nTokenId == SQL_TOKEN_SPACE )
2617     {
2618         nType = DataType::INTEGER;
2619     }
2620     else if(_nTokenId == SQL_TOKEN_SUBSTRING)
2621     {
2622         if ( _nPos != 1 )
2623             nType = DataType::INTEGER;
2624     }
2625     else if(_nTokenId == SQL_TOKEN_DATEDIFF)
2626     {
2627         if ( _nPos != 1 )
2628             nType = DataType::TIMESTAMP;
2629     }
2630     else if(_nTokenId == SQL_TOKEN_DATEVALUE)
2631         nType = DataType::DATE;
2632     else if(_nTokenId == SQL_TOKEN_DAYNAME)
2633         nType = DataType::DATE;
2634     else if(_nTokenId == SQL_TOKEN_DAYOFMONTH)
2635         nType = DataType::DATE;
2636     else if(_nTokenId == SQL_TOKEN_DAYOFWEEK)
2637         nType = DataType::DATE;
2638     else if(_nTokenId == SQL_TOKEN_DAYOFYEAR)
2639         nType = DataType::DATE;
2640     else if(_nTokenId == SQL_TOKEN_EXTRACT)              nType = DataType::VARCHAR;
2641     else if(_nTokenId == SQL_TOKEN_HOUR)                 nType = DataType::TIME;
2642     else if(_nTokenId == SQL_TOKEN_MINUTE)               nType = DataType::TIME;
2643     else if(_nTokenId == SQL_TOKEN_MONTH)                nType = DataType::DATE;
2644     else if(_nTokenId == SQL_TOKEN_MONTHNAME)            nType = DataType::DATE;
2645     else if(_nTokenId == SQL_TOKEN_NOW)                  nType = DataType::TIMESTAMP;
2646     else if(_nTokenId == SQL_TOKEN_QUARTER)              nType = DataType::DATE;
2647     else if(_nTokenId == SQL_TOKEN_SECOND)               nType = DataType::TIME;
2648     else if(_nTokenId == SQL_TOKEN_TIMESTAMPADD)         nType = DataType::TIMESTAMP;
2649     else if(_nTokenId == SQL_TOKEN_TIMESTAMPDIFF)        nType = DataType::TIMESTAMP;
2650     else if(_nTokenId == SQL_TOKEN_TIMEVALUE)            nType = DataType::TIMESTAMP;
2651     else if(_nTokenId == SQL_TOKEN_WEEK)                 nType = DataType::DATE;
2652     else if(_nTokenId == SQL_TOKEN_YEAR)                 nType = DataType::DATE;
2653 
2654     else if(_nTokenId == SQL_TOKEN_ABS)                  nType = DataType::DOUBLE;
2655     else if(_nTokenId == SQL_TOKEN_ACOS)                 nType = DataType::DOUBLE;
2656     else if(_nTokenId == SQL_TOKEN_ASIN)                 nType = DataType::DOUBLE;
2657     else if(_nTokenId == SQL_TOKEN_ATAN)                 nType = DataType::DOUBLE;
2658     else if(_nTokenId == SQL_TOKEN_ATAN2)                nType = DataType::DOUBLE;
2659     else if(_nTokenId == SQL_TOKEN_CEILING)              nType = DataType::DOUBLE;
2660     else if(_nTokenId == SQL_TOKEN_COS)                  nType = DataType::DOUBLE;
2661     else if(_nTokenId == SQL_TOKEN_COT)                  nType = DataType::DOUBLE;
2662     else if(_nTokenId == SQL_TOKEN_DEGREES)              nType = DataType::DOUBLE;
2663     else if(_nTokenId == SQL_TOKEN_EXP)                  nType = DataType::DOUBLE;
2664     else if(_nTokenId == SQL_TOKEN_FLOOR)                nType = DataType::DOUBLE;
2665     else if(_nTokenId == SQL_TOKEN_LOGF)                 nType = DataType::DOUBLE;
2666     else if(_nTokenId == SQL_TOKEN_LOG)                  nType = DataType::DOUBLE;
2667     else if(_nTokenId == SQL_TOKEN_LOG10)                nType = DataType::DOUBLE;
2668     else if(_nTokenId == SQL_TOKEN_LN)                   nType = DataType::DOUBLE;
2669     else if(_nTokenId == SQL_TOKEN_MOD)                  nType = DataType::DOUBLE;
2670     else if(_nTokenId == SQL_TOKEN_PI)                   nType = DataType::DOUBLE;
2671     else if(_nTokenId == SQL_TOKEN_POWER)                nType = DataType::DOUBLE;
2672     else if(_nTokenId == SQL_TOKEN_RADIANS)              nType = DataType::DOUBLE;
2673     else if(_nTokenId == SQL_TOKEN_RAND)                 nType = DataType::DOUBLE;
2674     else if(_nTokenId == SQL_TOKEN_ROUND)                nType = DataType::DOUBLE;
2675     else if(_nTokenId == SQL_TOKEN_ROUNDMAGIC)           nType = DataType::DOUBLE;
2676     else if(_nTokenId == SQL_TOKEN_SIGN)                 nType = DataType::DOUBLE;
2677     else if(_nTokenId == SQL_TOKEN_SIN)                  nType = DataType::DOUBLE;
2678     else if(_nTokenId == SQL_TOKEN_SQRT)                 nType = DataType::DOUBLE;
2679     else if(_nTokenId == SQL_TOKEN_TAN)                  nType = DataType::DOUBLE;
2680     else if(_nTokenId == SQL_TOKEN_TRUNCATE)             nType = DataType::DOUBLE;
2681     else if(_nTokenId == SQL_TOKEN_COUNT)                nType = DataType::INTEGER;
2682     else if(_nTokenId == SQL_TOKEN_MAX)                  nType = DataType::DOUBLE;
2683     else if(_nTokenId == SQL_TOKEN_MIN)                  nType = DataType::DOUBLE;
2684     else if(_nTokenId == SQL_TOKEN_AVG)                  nType = DataType::DOUBLE;
2685     else if(_nTokenId == SQL_TOKEN_SUM)                  nType = DataType::DOUBLE;
2686 
2687     else if(_nTokenId == SQL_TOKEN_LOWER)                nType = DataType::VARCHAR;
2688     else if(_nTokenId == SQL_TOKEN_UPPER)                nType = DataType::VARCHAR;
2689 
2690     return nType;
2691 }
2692 
2693 
getErrorHelper() const2694 const SQLError& OSQLParser::getErrorHelper() const
2695 {
2696     return m_pData->aErrors;
2697 }
2698 
2699 
getKnownRuleID() const2700 OSQLParseNode::Rule OSQLParseNode::getKnownRuleID() const
2701 {
2702     if ( !isRule() )
2703         return UNKNOWN_RULE;
2704     return OSQLParser::RuleIDToRule( getRuleID() );
2705 }
2706 
getTableRange(const OSQLParseNode * _pTableRef)2707 OUString OSQLParseNode::getTableRange(const OSQLParseNode* _pTableRef)
2708 {
2709     assert(_pTableRef);
2710     OSL_ENSURE(_pTableRef->count() > 1 && _pTableRef->getKnownRuleID() == OSQLParseNode::table_ref,"Invalid node give, only table ref is allowed!");
2711     const sal_uInt32 nCount = _pTableRef->count();
2712     OUString sTableRange;
2713     if ( nCount == 2 || (nCount == 3 && !_pTableRef->getChild(0)->isToken()) )
2714     {
2715         const OSQLParseNode* pNode = _pTableRef->getChild(nCount - (nCount == 2 ? 1 : 2));
2716         assert(pNode);
2717         OSL_ENSURE(pNode->getKnownRuleID() == OSQLParseNode::table_primary_as_range_column ||
2718                    pNode->getKnownRuleID() == OSQLParseNode::range_variable, "SQL grammar changed!");
2719         if ( !pNode->isLeaf() )
2720             sTableRange = pNode->getChild(1)->getTokenValue();
2721     } // if ( nCount == 2 || nCount == 3 )
2722 
2723     return sTableRange;
2724 }
2725 
OSQLParseNodesContainer()2726 OSQLParseNodesContainer::OSQLParseNodesContainer()
2727 {
2728 }
2729 
~OSQLParseNodesContainer()2730 OSQLParseNodesContainer::~OSQLParseNodesContainer()
2731 {
2732 }
2733 
push_back(OSQLParseNode * _pNode)2734 void OSQLParseNodesContainer::push_back(OSQLParseNode* _pNode)
2735 {
2736     std::unique_lock aGuard(m_aMutex);
2737     m_aNodes.push_back(_pNode);
2738 }
2739 
erase(OSQLParseNode * _pNode)2740 void OSQLParseNodesContainer::erase(OSQLParseNode* _pNode)
2741 {
2742     std::unique_lock aGuard(m_aMutex);
2743     if ( !m_aNodes.empty() )
2744     {
2745         std::vector< OSQLParseNode* >::iterator aFind = std::find(m_aNodes.begin(), m_aNodes.end(),_pNode);
2746         if ( aFind != m_aNodes.end() )
2747             m_aNodes.erase(aFind);
2748     }
2749 }
2750 
clear()2751 void OSQLParseNodesContainer::clear()
2752 {
2753     std::unique_lock aGuard(m_aMutex);
2754     m_aNodes.clear();
2755 }
2756 
clearAndDelete()2757 void OSQLParseNodesContainer::clearAndDelete()
2758 {
2759     std::unique_lock aGuard(m_aMutex);
2760     // clear the garbage collector
2761     while ( !m_aNodes.empty() )
2762     {
2763         OSQLParseNode* pNode = m_aNodes[0];
2764         while ( pNode->getParent() )
2765         {
2766             pNode = pNode->getParent();
2767         }
2768         aGuard.unlock(); // can call back into this object during destruction
2769         delete pNode;
2770         aGuard.lock();
2771     }
2772 }
2773 }   // namespace connectivity
2774 
2775 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
2776