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 <file/fcomp.hxx>
21 #include <tools/debug.hxx>
22 #include <connectivity/sqlparse.hxx>
23 #include <file/fanalyzer.hxx>
24 #include <com/sun/star/sdbc/XColumnLocate.hpp>
25 #include <com/sun/star/util/DateTime.hpp>
26 #include <com/sun/star/util/Date.hpp>
27 #include <com/sun/star/util/Time.hpp>
28 #include <connectivity/dbexception.hxx>
29 #include <connectivity/dbconversion.hxx>
30 #include <com/sun/star/sdb/SQLFilterOperator.hpp>
31 #include <file/FStringFunctions.hxx>
32 #include <file/FDateFunctions.hxx>
33 #include <file/FNumericFunctions.hxx>
34 #include <file/FConnection.hxx>
35 #include <tools/diagnose_ex.h>
36 #include <sqlbison.hxx>
37 #include <strings.hrc>
38 
39 using namespace connectivity;
40 using namespace connectivity::file;
41 using namespace com::sun::star::uno;
42 using namespace com::sun::star::sdbc;
43 using namespace com::sun::star::sdb;
44 using namespace ::com::sun::star::container;
45 using namespace com::sun::star;
46 
OPredicateCompiler(OSQLAnalyzer * pAnalyzer)47 OPredicateCompiler::OPredicateCompiler(OSQLAnalyzer* pAnalyzer)//,OCursor& rCurs)
48                      : m_pAnalyzer(pAnalyzer)
49                      , m_nParamCounter(0)
50 {
51 }
52 
53 
~OPredicateCompiler()54 OPredicateCompiler::~OPredicateCompiler()
55 {
56     Clean();
57 }
58 
dispose()59 void OPredicateCompiler::dispose()
60 {
61     Clean();
62     m_orgColumns        = nullptr;
63 }
64 
start(OSQLParseNode const * pSQLParseNode)65 void OPredicateCompiler::start(OSQLParseNode const * pSQLParseNode)
66 {
67     if (!pSQLParseNode)
68         return;
69 
70     m_nParamCounter = 0;
71     // analyse Parse Tree (depending on Statement-type)
72     // and set pointer on WHERE-clause:
73     OSQLParseNode * pWhereClause = nullptr;
74 
75     if (SQL_ISRULE(pSQLParseNode,select_statement))
76     {
77         OSQLParseNode * pOrderbyClause = nullptr;
78         DBG_ASSERT(pSQLParseNode->count() >= 4,"OFILECursor: Error in Parse Tree");
79 
80         OSQLParseNode * pTableExp = pSQLParseNode->getChild(3);
81         DBG_ASSERT(pTableExp != nullptr,"Error in Parse Tree");
82         DBG_ASSERT(SQL_ISRULE(pTableExp,table_exp)," Error in Parse Tree");
83         DBG_ASSERT(pTableExp->count() == TABLE_EXPRESSION_CHILD_COUNT,"Error in Parse Tree");
84 
85         // check that we don't use anything other than count(*) as function
86         OSQLParseNode* pSelection = pSQLParseNode->getChild(2);
87         if ( SQL_ISRULE(pSelection,scalar_exp_commalist) )
88         {
89             for (size_t i = 0; i < pSelection->count(); i++)
90             {
91                 OSQLParseNode *pColumnRef = pSelection->getChild(i)->getChild(0);
92                 if ( SQL_ISRULE(pColumnRef,general_set_fct) && pColumnRef->count() != 4 )
93                 {
94                     m_pAnalyzer->getConnection()->throwGenericSQLException(STR_QUERY_COMPLEX_COUNT,nullptr);
95                 }
96             }
97         }
98 
99 
100         pWhereClause    = pTableExp->getChild(1);
101         pOrderbyClause  = pTableExp->getChild(ORDER_BY_CHILD_POS);
102         (void)pOrderbyClause;
103     }
104     else if (SQL_ISRULE(pSQLParseNode,update_statement_searched))
105     {
106         DBG_ASSERT(pSQLParseNode->count() == 5,"OFILECursor: Error in Parse Tree");
107         pWhereClause = pSQLParseNode->getChild(4);
108     }
109     else if (SQL_ISRULE(pSQLParseNode,delete_statement_searched))
110     {
111         DBG_ASSERT(pSQLParseNode->count() == 4,"Error in Parse Tree");
112         pWhereClause = pSQLParseNode->getChild(3);
113     }
114     else
115             // Other Statement. no selection-criteria
116         return;
117 
118     if (SQL_ISRULE(pWhereClause,where_clause))
119     {
120         // a where-clause is not allowed to be empty:
121         DBG_ASSERT(pWhereClause->count() == 2,"OFILECursor: Error in Parse Tree");
122 
123         OSQLParseNode * pComparisonPredicate = pWhereClause->getChild(1);
124         DBG_ASSERT(pComparisonPredicate != nullptr,"OFILECursor: Error in Parse Tree");
125 
126         execute( pComparisonPredicate );
127     }
128     else
129     {
130         // The where-clause is optionally in the majority of cases, i.e. it might be an "optional-where-clause".
131         DBG_ASSERT(SQL_ISRULE(pWhereClause,opt_where_clause),"OPredicateCompiler: Error in Parse Tree");
132     }
133 }
134 
135 
execute(OSQLParseNode const * pPredicateNode)136 OOperand* OPredicateCompiler::execute(OSQLParseNode const * pPredicateNode)
137 {
138     OOperand* pOperand = nullptr;
139     if (pPredicateNode->count() == 3 &&                         // Expression is bracketed
140         SQL_ISPUNCTUATION(pPredicateNode->getChild(0),"(") &&
141         SQL_ISPUNCTUATION(pPredicateNode->getChild(2),")"))
142     {
143         execute(pPredicateNode->getChild(1));
144     }
145     else if ((SQL_ISRULE(pPredicateNode,search_condition) || SQL_ISRULE(pPredicateNode,boolean_term))
146                             &&          // AND/OR-linkage:
147                             pPredicateNode->count() == 3)
148     {
149         execute(pPredicateNode->getChild(0));                           // process the left branch
150         execute(pPredicateNode->getChild(2));                           // process the right branch
151 
152         if (SQL_ISTOKEN(pPredicateNode->getChild(1),OR))                // OR-Operator
153         {
154             m_aCodeList.emplace_back(new OOp_OR);
155         }
156         else if (SQL_ISTOKEN(pPredicateNode->getChild(1),AND))      // AND-Operator
157             m_aCodeList.emplace_back(new OOp_AND);
158         else
159         {
160             OSL_FAIL("OPredicateCompiler: Error in Parse Tree");
161         }
162     }
163     else if (SQL_ISRULE(pPredicateNode,boolean_factor))
164     {
165         execute(pPredicateNode->getChild(1));
166         m_aCodeList.emplace_back(new OOp_NOT);
167     }
168     else if (SQL_ISRULE(pPredicateNode,comparison_predicate))
169     {
170         execute_COMPARE(pPredicateNode);
171     }
172     else if (SQL_ISRULE(pPredicateNode,like_predicate))
173     {
174         execute_LIKE(pPredicateNode);
175     }
176     else if (SQL_ISRULE(pPredicateNode,between_predicate))
177     {
178         execute_BETWEEN(pPredicateNode);
179     }
180     else if (SQL_ISRULE(pPredicateNode,test_for_null))
181     {
182         execute_ISNULL(pPredicateNode);
183     }
184     else if(SQL_ISRULE(pPredicateNode,num_value_exp))
185     {
186         execute(pPredicateNode->getChild(0));                           // process the left branch
187         execute(pPredicateNode->getChild(2));                           // process the right branch
188         if (SQL_ISPUNCTUATION(pPredicateNode->getChild(1),"+"))
189         {
190             m_aCodeList.emplace_back(new OOp_ADD);
191         }
192         else if (SQL_ISPUNCTUATION(pPredicateNode->getChild(1),"-"))
193             m_aCodeList.emplace_back(new OOp_SUB);
194         else
195         {
196             OSL_FAIL("OPredicateCompiler: Error in Parse Tree num_value_exp");
197         }
198     }
199     else if(SQL_ISRULE(pPredicateNode,term))
200     {
201         execute(pPredicateNode->getChild(0));                           // process the left branch
202         execute(pPredicateNode->getChild(2));                           // process the right branch
203         if (SQL_ISPUNCTUATION(pPredicateNode->getChild(1),"*"))
204         {
205             m_aCodeList.emplace_back(new OOp_MUL);
206         }
207         else if (SQL_ISPUNCTUATION(pPredicateNode->getChild(1),"/"))
208             m_aCodeList.emplace_back(new OOp_DIV);
209         else
210         {
211             OSL_FAIL("OPredicateCompiler: Error in Parse Tree num_value_exp");
212         }
213     }
214     else
215         pOperand = execute_Operand(pPredicateNode);                     // now only simple operands will be processed
216 
217     return pOperand;
218 }
219 
220 
execute_COMPARE(OSQLParseNode const * pPredicateNode)221 void OPredicateCompiler::execute_COMPARE(OSQLParseNode const * pPredicateNode)
222 {
223     DBG_ASSERT(pPredicateNode->count() == 3,"OFILECursor: Error in Parse Tree");
224 
225     if ( !(SQL_ISRULE(pPredicateNode->getChild(0),column_ref)               ||
226           pPredicateNode->getChild(2)->getNodeType() == SQLNodeType::String     ||
227           pPredicateNode->getChild(2)->getNodeType() == SQLNodeType::IntNum     ||
228           pPredicateNode->getChild(2)->getNodeType() == SQLNodeType::ApproxNum  ||
229           SQL_ISTOKEN(pPredicateNode->getChild(2),TRUE)                     ||
230           SQL_ISTOKEN(pPredicateNode->getChild(2),FALSE)                    ||
231           SQL_ISRULE(pPredicateNode->getChild(2),parameter)                 ||
232           // odbc date
233           SQL_ISRULE(pPredicateNode->getChild(2),set_fct_spec)              ||
234           SQL_ISRULE(pPredicateNode->getChild(2),position_exp)              ||
235           SQL_ISRULE(pPredicateNode->getChild(2),char_substring_fct)        ||
236           // upper, lower etc.
237           SQL_ISRULE(pPredicateNode->getChild(2),fold)) )
238     {
239         m_pAnalyzer->getConnection()->throwGenericSQLException(STR_QUERY_TOO_COMPLEX,nullptr);
240         return;
241     }
242 
243     sal_Int32 ePredicateType( SQLFilterOperator::EQUAL );
244     OSQLParseNode *pPrec = pPredicateNode->getChild(1);
245 
246     if (pPrec->getNodeType() == SQLNodeType::Equal)
247         ePredicateType = SQLFilterOperator::EQUAL;
248     else if (pPrec->getNodeType() == SQLNodeType::NotEqual)
249         ePredicateType = SQLFilterOperator::NOT_EQUAL;
250     else if (pPrec->getNodeType() == SQLNodeType::Less)
251         ePredicateType = SQLFilterOperator::LESS;
252     else if (pPrec->getNodeType() == SQLNodeType::LessEq)
253         ePredicateType = SQLFilterOperator::LESS_EQUAL;
254     else if (pPrec->getNodeType() == SQLNodeType::GreatEq)
255         ePredicateType = SQLFilterOperator::GREATER_EQUAL;
256     else if (pPrec->getNodeType() == SQLNodeType::Great)
257         ePredicateType = SQLFilterOperator::GREATER;
258     else
259         OSL_FAIL( "OPredicateCompiler::execute_COMPARE: unexpected node type!" );
260 
261     execute(pPredicateNode->getChild(0));
262     execute(pPredicateNode->getChild(2));
263     m_aCodeList.emplace_back( new OOp_COMPARE(ePredicateType) );
264 }
265 
266 
execute_LIKE(OSQLParseNode const * pPredicateNode)267 void OPredicateCompiler::execute_LIKE(OSQLParseNode const * pPredicateNode)
268 {
269     DBG_ASSERT(pPredicateNode->count() == 2,"OFILECursor: Error in Parse Tree");
270     const OSQLParseNode* pPart2 = pPredicateNode->getChild(1);
271 
272     sal_Unicode cEscape = L'\0';
273     const bool bNotLike = pPart2->getChild(0)->isToken();
274 
275     OSQLParseNode* pAtom        = pPart2->getChild(pPart2->count()-2);
276     OSQLParseNode* pOptEscape   = pPart2->getChild(pPart2->count()-1);
277 
278     if (!(pAtom->getNodeType() == SQLNodeType::String   ||
279           SQL_ISRULE(pAtom,parameter)               ||
280           // odbc date
281           SQL_ISRULE(pAtom,set_fct_spec)            ||
282           SQL_ISRULE(pAtom,position_exp)            ||
283           SQL_ISRULE(pAtom,char_substring_fct)      ||
284           // upper, lower etc.
285           SQL_ISRULE(pAtom,fold)) )
286     {
287         m_pAnalyzer->getConnection()->throwGenericSQLException(STR_QUERY_TOO_COMPLEX,nullptr);
288         return;
289     }
290 
291     if (pOptEscape->count() != 0)
292     {
293         if (pOptEscape->count() != 2)
294         {
295             m_pAnalyzer->getConnection()->throwGenericSQLException(STR_QUERY_INVALID_LIKE_STRING,nullptr);
296         }
297         OSQLParseNode *pEscNode = pOptEscape->getChild(1);
298         if (pEscNode->getNodeType() != SQLNodeType::String)
299         {
300             m_pAnalyzer->getConnection()->throwGenericSQLException(STR_QUERY_INVALID_LIKE_STRING,nullptr);
301         }
302         else
303             cEscape = pEscNode->getTokenValue().toChar();
304     }
305 
306     execute(pPredicateNode->getChild(0));
307     execute(pAtom);
308 
309     OBoolOperator* pOperator = bNotLike
310                                     ? new OOp_NOTLIKE(cEscape)
311                                     : new OOp_LIKE(cEscape);
312     m_aCodeList.emplace_back(pOperator);
313 }
314 
execute_BETWEEN(OSQLParseNode const * pPredicateNode)315 void OPredicateCompiler::execute_BETWEEN(OSQLParseNode const * pPredicateNode)
316 {
317     DBG_ASSERT(pPredicateNode->count() == 2,"OFILECursor: Error in Parse Tree");
318 
319     OSQLParseNode* pColumn = pPredicateNode->getChild(0);
320     const OSQLParseNode* pPart2 = pPredicateNode->getChild(1);
321     OSQLParseNode* p1stValue = pPart2->getChild(2);
322     OSQLParseNode* p2ndtValue = pPart2->getChild(4);
323 
324     if (
325             !(p1stValue->getNodeType() == SQLNodeType::String || SQL_ISRULE(p1stValue,parameter))
326         &&  !(p2ndtValue->getNodeType() == SQLNodeType::String || SQL_ISRULE(p2ndtValue,parameter))
327         )
328     {
329         m_pAnalyzer->getConnection()->throwGenericSQLException(STR_QUERY_INVALID_BETWEEN,nullptr);
330     }
331 
332     bool bNot = SQL_ISTOKEN(pPart2->getChild(0),NOT);
333 
334     OOperand* pColumnOp = execute(pColumn);
335     OOperand* pOb1 = execute(p1stValue);
336     OBoolOperator* pOperator = new OOp_COMPARE(bNot ? SQLFilterOperator::LESS_EQUAL : SQLFilterOperator::GREATER);
337     m_aCodeList.emplace_back(pOperator);
338 
339     execute(pColumn);
340     OOperand* pOb2 = execute(p2ndtValue);
341     pOperator = new OOp_COMPARE(bNot ? SQLFilterOperator::GREATER_EQUAL : SQLFilterOperator::LESS);
342     m_aCodeList.emplace_back(pOperator);
343 
344     if ( pColumnOp && pOb1 && pOb2 )
345     {
346         switch(pColumnOp->getDBType())
347         {
348             case DataType::CHAR:
349             case DataType::VARCHAR:
350             case DataType::LONGVARCHAR:
351                 pOb1->setValue(pOb1->getValue().getString());
352                 pOb2->setValue(pOb2->getValue().getString());
353                 break;
354             case DataType::DECIMAL:
355             case DataType::NUMERIC:
356                 pOb1->setValue(static_cast<double>(pOb1->getValue()));
357                 pOb2->setValue(static_cast<double>(pOb2->getValue()));
358                 break;
359             case DataType::FLOAT:
360                 pOb1->setValue(static_cast<float>(pOb1->getValue()));
361                 pOb2->setValue(static_cast<float>(pOb2->getValue()));
362                 break;
363             case DataType::DOUBLE:
364             case DataType::REAL:
365                 pOb1->setValue(static_cast<double>(pOb1->getValue()));
366                 pOb2->setValue(static_cast<double>(pOb2->getValue()));
367                 break;
368             case DataType::DATE:
369                 pOb1->setValue(static_cast<util::Date>(pOb1->getValue()));
370                 pOb2->setValue(static_cast<util::Date>(pOb2->getValue()));
371                 break;
372             case DataType::TIME:
373                 pOb1->setValue(static_cast<util::Time>(pOb1->getValue()));
374                 pOb2->setValue(static_cast<util::Time>(pOb2->getValue()));
375                 break;
376             case DataType::TIMESTAMP:
377                 pOb1->setValue(static_cast<util::DateTime>(pOb1->getValue()));
378                 pOb2->setValue(static_cast<util::DateTime>(pOb2->getValue()));
379                 break;
380         }
381     }
382 
383 
384     OBoolOperator* pBoolOp = nullptr;
385     if ( bNot )
386         pBoolOp = new OOp_OR;
387     else
388         pBoolOp = new OOp_AND;
389     m_aCodeList.emplace_back(pBoolOp);
390 }
391 
execute_ISNULL(OSQLParseNode const * pPredicateNode)392 void OPredicateCompiler::execute_ISNULL(OSQLParseNode const * pPredicateNode)
393 {
394     DBG_ASSERT(pPredicateNode->count() == 2,"OFILECursor: Error in Parse Tree");
395     const OSQLParseNode* pPart2 = pPredicateNode->getChild(1);
396     DBG_ASSERT(SQL_ISTOKEN(pPart2->getChild(0),IS),"OFILECursor: Error in Parse Tree");
397 
398     sal_Int32 ePredicateType;
399     if (SQL_ISTOKEN(pPart2->getChild(1),NOT))
400         ePredicateType = SQLFilterOperator::NOT_SQLNULL;
401     else
402         ePredicateType = SQLFilterOperator::SQLNULL;
403 
404     execute(pPredicateNode->getChild(0));
405     OBoolOperator* pOperator = (ePredicateType == SQLFilterOperator::SQLNULL) ?
406                                 new OOp_ISNULL : new OOp_ISNOTNULL;
407     m_aCodeList.emplace_back(pOperator);
408 }
409 
execute_Operand(OSQLParseNode const * pPredicateNode)410 OOperand* OPredicateCompiler::execute_Operand(OSQLParseNode const * pPredicateNode)
411 {
412     OOperand* pOperand = nullptr;
413 
414     if (SQL_ISRULE(pPredicateNode,column_ref))
415     {
416         OUString aColumnName;
417         if (pPredicateNode->count() == 1)
418         {
419             aColumnName = pPredicateNode->getChild(0)->getTokenValue();
420         }
421         else if (pPredicateNode->count() == 3)
422         {
423             if(SQL_ISRULE(pPredicateNode->getChild(2),column_val))
424                 aColumnName = pPredicateNode->getChild(2)->getChild(0)->getTokenValue();
425             else
426                 aColumnName = pPredicateNode->getChild(2)->getTokenValue();
427         }
428 
429         if(!m_orgColumns->hasByName(aColumnName))
430         {
431             const OUString sError( m_pAnalyzer->getConnection()->getResources().getResourceStringWithSubstitution(
432                     STR_INVALID_COLUMNNAME,
433                     "$columnname$", aColumnName
434                  ) );
435             ::dbtools::throwGenericSQLException( sError, nullptr );
436         }
437         css::uno::Reference< css::beans::XPropertySet> xCol;
438         try
439         {
440             if (m_orgColumns->getByName(aColumnName) >>= xCol)
441             {
442                 pOperand = OSQLAnalyzer::createOperandAttr(Reference< XColumnLocate>(m_orgColumns,UNO_QUERY_THROW)->findColumn(aColumnName),xCol);
443             }
444             else
445             {// Column doesn't exist in the Result-set
446                 const OUString sError( m_pAnalyzer->getConnection()->getResources().getResourceStringWithSubstitution(
447                     STR_INVALID_COLUMNNAME,
448                     "$columnname$", aColumnName
449                  ) );
450                 ::dbtools::throwGenericSQLException( sError, nullptr );
451             }
452         }
453         catch(Exception &)
454         {
455             TOOLS_WARN_EXCEPTION( "connectivity.drivers", "OPredicateCompiler::execute_Operand Exception");
456         }
457     }
458     else if (SQL_ISRULE(pPredicateNode,parameter))
459     {
460         pOperand = new OOperandParam(++m_nParamCounter);
461     }
462     else if (pPredicateNode->getNodeType() == SQLNodeType::String ||
463              pPredicateNode->getNodeType() == SQLNodeType::IntNum ||
464              pPredicateNode->getNodeType() == SQLNodeType::ApproxNum ||
465              pPredicateNode->getNodeType() == SQLNodeType::Name ||
466              SQL_ISTOKEN(pPredicateNode,TRUE) ||
467              SQL_ISTOKEN(pPredicateNode,FALSE) ||
468              SQL_ISRULE(pPredicateNode,parameter))
469     {
470         pOperand = new OOperandConst(*pPredicateNode, pPredicateNode->getTokenValue());
471     }
472     else if((pPredicateNode->count() == 2) &&
473             (SQL_ISPUNCTUATION(pPredicateNode->getChild(0),"+") || SQL_ISPUNCTUATION(pPredicateNode->getChild(0),"-")) &&
474             pPredicateNode->getChild(1)->getNodeType() == SQLNodeType::IntNum)
475     { // if -1 or +1 is there
476         OUString aValue = pPredicateNode->getChild(0)->getTokenValue() + pPredicateNode->getChild(1)->getTokenValue();
477         pOperand = new OOperandConst(*pPredicateNode->getChild(1), aValue);
478     }
479     else if( SQL_ISRULE(pPredicateNode,set_fct_spec) && SQL_ISPUNCTUATION(pPredicateNode->getChild(0),"{") )
480     {
481         const OSQLParseNode* pODBCNode = pPredicateNode->getChild(1);
482         const OSQLParseNode* pODBCNodeChild = pODBCNode->getChild(0);
483 
484         // Odbc Date or time
485         if (pODBCNodeChild->getNodeType() == SQLNodeType::Keyword && (
486             SQL_ISTOKEN(pODBCNodeChild,D) ||
487             SQL_ISTOKEN(pODBCNodeChild,T) ||
488             SQL_ISTOKEN(pODBCNodeChild,TS) ))
489         {
490             OUString sDateTime = pODBCNode->getChild(1)->getTokenValue();
491             pOperand = new OOperandConst(*pODBCNode->getChild(1), sDateTime);
492             if(SQL_ISTOKEN(pODBCNodeChild,D))
493             {
494                 pOperand->setValue(::dbtools::DBTypeConversion::toDouble(::dbtools::DBTypeConversion::toDate(sDateTime)));
495             }
496             else if(SQL_ISTOKEN(pODBCNodeChild,T))
497             {
498                 pOperand->setValue(::dbtools::DBTypeConversion::toDouble(::dbtools::DBTypeConversion::toTime(sDateTime)));
499             }
500             else if(SQL_ISTOKEN(pODBCNodeChild,TS))
501             {
502                 pOperand->setValue(::dbtools::DBTypeConversion::toDouble(::dbtools::DBTypeConversion::toDateTime(sDateTime)));
503             }
504         }
505         else
506             m_pAnalyzer->getConnection()->throwGenericSQLException(STR_QUERY_TOO_COMPLEX,nullptr);
507 
508     }
509     else if( SQL_ISRULE(pPredicateNode,fold) )
510     {
511         execute_Fold(pPredicateNode);
512     }
513     else if(    SQL_ISRULE(pPredicateNode,set_fct_spec)
514             ||  SQL_ISRULE(pPredicateNode,position_exp)
515             ||  SQL_ISRULE(pPredicateNode,char_substring_fct)
516             )
517     {
518         executeFunction(pPredicateNode);
519     }
520     else if( SQL_ISRULE(pPredicateNode,length_exp) )
521     {
522         executeFunction(pPredicateNode->getChild(0));
523     }
524     else
525     {
526         m_pAnalyzer->getConnection()->throwGenericSQLException(STR_QUERY_TOO_COMPLEX,nullptr);
527     }
528     if (pOperand)
529         m_aCodeList.emplace_back(pOperand);
530     return pOperand;
531 }
532 
533 
evaluate(OCodeList & rCodeList)534 bool OPredicateInterpreter::evaluate(OCodeList& rCodeList)
535 {
536     if (!(rCodeList[0]))
537         return true;        // no Predicate
538 
539     for (auto const& code : rCodeList)
540     {
541         OOperand* pOperand = dynamic_cast<OOperand* >(code.get());
542         if (pOperand)
543             m_aStack.push(pOperand);
544         else
545             static_cast<OOperator *>(code.get())->Exec(m_aStack);
546     }
547 
548     OOperand* pOperand = m_aStack.top();
549     m_aStack.pop();
550 
551     DBG_ASSERT(m_aStack.empty(), "Stack error");
552     DBG_ASSERT(pOperand, "Stack error");
553 
554     const bool bResult = pOperand->isValid();
555     if (typeid(OOperandResult) == typeid(*pOperand))
556         delete pOperand;
557     return bResult;
558 }
559 
evaluateSelection(OCodeList & rCodeList,ORowSetValueDecoratorRef const & _rVal)560 void OPredicateInterpreter::evaluateSelection(OCodeList& rCodeList, ORowSetValueDecoratorRef const & _rVal)
561 {
562     if (!(rCodeList[0]))
563         return ;        // no Predicate
564 
565     for (auto const& code : rCodeList)
566     {
567         OOperand* pOperand = dynamic_cast<OOperand* >(code.get());
568         if (pOperand)
569             m_aStack.push(pOperand);
570         else
571             static_cast<OOperator *>(code.get())->Exec(m_aStack);
572     }
573 
574     OOperand* pOperand = m_aStack.top();
575     m_aStack.pop();
576 
577     DBG_ASSERT(m_aStack.empty(), "Stack error");
578     DBG_ASSERT(pOperand, "Stack error");
579 
580     (*_rVal) = pOperand->getValue();
581     if (typeid(OOperandResult) == typeid(*pOperand))
582         delete pOperand;
583 }
584 
execute_Fold(OSQLParseNode const * pPredicateNode)585 void OPredicateCompiler::execute_Fold(OSQLParseNode const * pPredicateNode)
586 {
587     DBG_ASSERT(pPredicateNode->count() >= 4,"OFILECursor: Error in Parse Tree");
588 
589     bool bUpper = SQL_ISTOKEN(pPredicateNode->getChild(0),UPPER);
590 
591     execute(pPredicateNode->getChild(2));
592     OOperator* pOperator = nullptr;
593     if ( bUpper )
594         pOperator = new OOp_Upper;
595     else
596         pOperator = new OOp_Lower;
597 
598     m_aCodeList.emplace_back(pOperator);
599 }
600 
executeFunction(OSQLParseNode const * pPredicateNode)601 void OPredicateCompiler::executeFunction(OSQLParseNode const * pPredicateNode)
602 {
603     OOperator* pOperator = nullptr;
604 
605     OSL_ENSURE(pPredicateNode->getChild(0)->isToken(),"The first one must be the name of the function!");
606     sal_Int32 nTokenId = pPredicateNode->getChild(0)->getTokenID();
607     switch ( nTokenId )
608     {
609         case SQL_TOKEN_CHAR_LENGTH:
610         case SQL_TOKEN_LENGTH:
611         case SQL_TOKEN_OCTET_LENGTH:
612         case SQL_TOKEN_ASCII:
613         case SQL_TOKEN_LCASE:
614         case SQL_TOKEN_LTRIM:
615         case SQL_TOKEN_RTRIM:
616         case SQL_TOKEN_SPACE:
617         case SQL_TOKEN_UCASE:
618         case SQL_TOKEN_ABS:
619         case SQL_TOKEN_ACOS:
620         case SQL_TOKEN_ASIN:
621         case SQL_TOKEN_ATAN:
622         case SQL_TOKEN_CEILING:
623         case SQL_TOKEN_COS:
624         case SQL_TOKEN_DEGREES:
625         case SQL_TOKEN_EXP:
626         case SQL_TOKEN_FLOOR:
627         case SQL_TOKEN_LOG10:
628         case SQL_TOKEN_LN:
629         case SQL_TOKEN_RADIANS:
630         case SQL_TOKEN_SIGN:
631         case SQL_TOKEN_SIN:
632         case SQL_TOKEN_SQRT:
633         case SQL_TOKEN_TAN:
634         case SQL_TOKEN_DAYNAME:
635         case SQL_TOKEN_DAYOFMONTH:
636         case SQL_TOKEN_DAYOFWEEK:
637         case SQL_TOKEN_DAYOFYEAR:
638         case SQL_TOKEN_HOUR:
639         case SQL_TOKEN_MINUTE:
640         case SQL_TOKEN_MONTH:
641         case SQL_TOKEN_MONTHNAME:
642         case SQL_TOKEN_QUARTER:
643         case SQL_TOKEN_SECOND:
644         case SQL_TOKEN_YEAR:
645 
646             execute(pPredicateNode->getChild(2));
647 
648             switch( nTokenId )
649             {
650                 case SQL_TOKEN_CHAR_LENGTH:
651                 case SQL_TOKEN_LENGTH:
652                 case SQL_TOKEN_OCTET_LENGTH:
653                     pOperator = new OOp_CharLength;
654                     break;
655                 case SQL_TOKEN_ASCII:
656                     pOperator = new OOp_Ascii;
657                     break;
658                 case SQL_TOKEN_LCASE:
659                     pOperator = new OOp_Lower;
660                     break;
661 
662                 case SQL_TOKEN_LTRIM:
663                     pOperator = new OOp_LTrim;
664                     break;
665                 case SQL_TOKEN_RTRIM:
666                     pOperator = new OOp_RTrim;
667                     break;
668                 case SQL_TOKEN_SPACE:
669                     pOperator = new OOp_Space;
670                     break;
671                 case SQL_TOKEN_UCASE:
672                     pOperator = new OOp_Upper;
673                     break;
674                 case SQL_TOKEN_ABS:
675                     pOperator = new OOp_Abs;
676                     break;
677                 case SQL_TOKEN_ACOS:
678                     pOperator = new OOp_ACos;
679                     break;
680                 case SQL_TOKEN_ASIN:
681                     pOperator = new OOp_ASin;
682                     break;
683                 case SQL_TOKEN_ATAN:
684                     pOperator = new OOp_ATan;
685                     break;
686                 case SQL_TOKEN_CEILING:
687                     pOperator = new OOp_Ceiling;
688                     break;
689                 case SQL_TOKEN_COS:
690                     pOperator = new OOp_Cos;
691                     break;
692                 case SQL_TOKEN_DEGREES:
693                     pOperator = new OOp_Degrees;
694                     break;
695                 case SQL_TOKEN_EXP:
696                     pOperator = new OOp_Exp;
697                     break;
698                 case SQL_TOKEN_FLOOR:
699                     pOperator = new OOp_Floor;
700                     break;
701                 case SQL_TOKEN_LOG10:
702                     pOperator = new OOp_Log10;
703                     break;
704                 case SQL_TOKEN_LN:
705                     pOperator = new OOp_Ln;
706                     break;
707                 case SQL_TOKEN_RADIANS:
708                     pOperator = new OOp_Radians;
709                     break;
710                 case SQL_TOKEN_SIGN:
711                     pOperator = new OOp_Sign;
712                     break;
713                 case SQL_TOKEN_SIN:
714                     pOperator = new OOp_Sin;
715                     break;
716                 case SQL_TOKEN_SQRT:
717                     pOperator = new OOp_Sqrt;
718                     break;
719                 case SQL_TOKEN_TAN:
720                     pOperator = new OOp_Tan;
721                     break;
722                 case SQL_TOKEN_DAYOFWEEK:
723                     pOperator = new OOp_DayOfWeek;
724                     break;
725                 case SQL_TOKEN_DAYOFMONTH:
726                     pOperator = new OOp_DayOfMonth;
727                     break;
728                 case SQL_TOKEN_DAYOFYEAR:
729                     pOperator = new OOp_DayOfYear;
730                     break;
731                 case SQL_TOKEN_MONTH:
732                     pOperator = new OOp_Month;
733                     break;
734                 case SQL_TOKEN_DAYNAME:
735                     pOperator = new OOp_DayName;
736                     break;
737                 case SQL_TOKEN_MONTHNAME:
738                     pOperator = new OOp_MonthName;
739                     break;
740                 case SQL_TOKEN_QUARTER:
741                     pOperator = new OOp_Quarter;
742                     break;
743                 case SQL_TOKEN_YEAR:
744                     pOperator = new OOp_Year;
745                     break;
746                 case SQL_TOKEN_HOUR:
747                     pOperator = new OOp_Hour;
748                     break;
749                 case SQL_TOKEN_MINUTE:
750                     pOperator = new OOp_Minute;
751                     break;
752                 case SQL_TOKEN_SECOND:
753                     pOperator = new OOp_Second;
754                     break;
755                 default:
756                     OSL_FAIL("Error in switch!");
757             }
758             break;
759         case SQL_TOKEN_CHAR:
760         case SQL_TOKEN_CONCAT:
761         case SQL_TOKEN_INSERT:
762         case SQL_TOKEN_LEFT:
763         case SQL_TOKEN_LOCATE:
764         case SQL_TOKEN_LOCATE_2:
765         case SQL_TOKEN_REPEAT:
766         case SQL_TOKEN_REPLACE:
767         case SQL_TOKEN_RIGHT:
768         case SQL_TOKEN_MOD:
769         case SQL_TOKEN_ROUND:
770         case SQL_TOKEN_LOGF:
771         case SQL_TOKEN_LOG:
772         case SQL_TOKEN_POWER:
773         case SQL_TOKEN_ATAN2:
774         case SQL_TOKEN_PI:
775         case SQL_TOKEN_CURDATE:
776         case SQL_TOKEN_CURTIME:
777         case SQL_TOKEN_NOW:
778         case SQL_TOKEN_WEEK:
779             {
780                 m_aCodeList.emplace_back(new OStopOperand);
781                 OSQLParseNode* pList = pPredicateNode->getChild(2);
782                 for (size_t i=0; i < pList->count(); ++i)
783                     execute(pList->getChild(i));
784 
785                 switch( nTokenId )
786                 {
787                     case SQL_TOKEN_CHAR:
788                         pOperator = new OOp_Char;
789                         break;
790                     case SQL_TOKEN_CONCAT:
791                         pOperator = new OOp_Concat;
792                         break;
793                     case SQL_TOKEN_INSERT:
794                         pOperator = new OOp_Insert;
795                         break;
796                     case SQL_TOKEN_LEFT:
797                         pOperator = new OOp_Left;
798                         break;
799                     case SQL_TOKEN_LOCATE:
800                     case SQL_TOKEN_LOCATE_2:
801                         pOperator = new OOp_Locate;
802                         break;
803                     case SQL_TOKEN_REPEAT:
804                         pOperator = new OOp_Repeat;
805                         break;
806                     case SQL_TOKEN_REPLACE:
807                         pOperator = new OOp_Replace;
808                         break;
809                     case SQL_TOKEN_RIGHT:
810                         pOperator = new OOp_Right;
811                         break;
812                     case SQL_TOKEN_MOD:
813                         pOperator = new OOp_Mod;
814                         break;
815                     case SQL_TOKEN_ROUND:
816                         pOperator = new OOp_Round;
817                         break;
818                     case SQL_TOKEN_LOGF:
819                     case SQL_TOKEN_LOG:
820                         pOperator = new OOp_Log;
821                         break;
822                     case SQL_TOKEN_POWER:
823                         pOperator = new OOp_Pow;
824                         break;
825                     case SQL_TOKEN_ATAN2:
826                         pOperator = new OOp_ATan2;
827                         break;
828                     case SQL_TOKEN_PI:
829                         pOperator = new OOp_Pi;
830                         break;
831                     case SQL_TOKEN_CURDATE:
832                         pOperator = new OOp_CurDate;
833                         break;
834                     case SQL_TOKEN_CURTIME:
835                         pOperator = new OOp_CurTime;
836                         break;
837                     case SQL_TOKEN_NOW:
838                         pOperator = new OOp_Now;
839                         break;
840                     case SQL_TOKEN_WEEK:
841                         pOperator = new OOp_Week;
842                         break;
843                     default:
844                         OSL_FAIL("Error in switch!");
845                 }
846             }
847             break;
848 
849         case SQL_TOKEN_SUBSTRING:
850             m_aCodeList.emplace_back(new OStopOperand);
851             if ( pPredicateNode->count() == 4 ) //char_substring_fct
852             {
853                 OSQLParseNode* pList = pPredicateNode->getChild(2);
854                 for (size_t i=0; i < pList->count(); ++i)
855                     execute(pList->getChild(i));
856             }
857             else
858             {
859                 execute(pPredicateNode->getChild(2));
860                 execute(pPredicateNode->getChild(4));
861                 execute(pPredicateNode->getChild(5)->getChild(1));
862             }
863             pOperator = new OOp_SubString;
864             break;
865 
866         case SQL_TOKEN_POSITION:
867             m_aCodeList.emplace_back(new OStopOperand);
868             if ( pPredicateNode->count() == 4 ) //position_exp
869             {
870                 OSQLParseNode* pList = pPredicateNode->getChild(2);
871                 for (size_t i=0; i < pList->count(); ++i)
872                     execute(pList->getChild(i));
873             }
874             else
875             {
876                 execute(pPredicateNode->getChild(2));
877                 execute(pPredicateNode->getChild(4));
878             }
879             pOperator = new OOp_Locate;
880             break;
881         default:
882             m_pAnalyzer->getConnection()->throwGenericSQLException(STR_QUERY_FUNCTION_NOT_SUPPORTED,nullptr);
883     }
884 
885     m_aCodeList.emplace_back(pOperator);
886 }
887 
888 
889 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
890