/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
void OPredicateCompiler::start(OSQLParseNode const * pSQLParseNode)
{ if (!pSQLParseNode) return;
m_nParamCounter = 0; // analyse Parse Tree (depending on Statement-type) // and set pointer on WHERE-clause:
OSQLParseNode * pWhereClause = nullptr;
if (SQL_ISRULE(pSQLParseNode,select_statement))
{
OSQLParseNode * pOrderbyClause = nullptr;
DBG_ASSERT(pSQLParseNode->count() >= 4,"OFILECursor: Error in Parse Tree");
OSQLParseNode * pTableExp = pSQLParseNode->getChild(3);
assert(pTableExp && "Error in Parse Tree");
DBG_ASSERT(SQL_ISRULE(pTableExp,table_exp)," Error in Parse Tree");
DBG_ASSERT(pTableExp->count() == TABLE_EXPRESSION_CHILD_COUNT,"Error in Parse Tree");
// check that we don't use anything other than count(*) as function
OSQLParseNode* pSelection = pSQLParseNode->getChild(2); if ( SQL_ISRULE(pSelection,scalar_exp_commalist) )
{ for (size_t i = 0; i < pSelection->count(); i++)
{
OSQLParseNode *pColumnRef = pSelection->getChild(i)->getChild(0); if ( SQL_ISRULE(pColumnRef,general_set_fct) && pColumnRef->count() != 4 )
{
m_pAnalyzer->getConnection()->throwGenericSQLException(STR_QUERY_COMPLEX_COUNT,nullptr);
}
}
}
if (SQL_ISRULE(pWhereClause,where_clause))
{ // a where-clause is not allowed to be empty:
DBG_ASSERT(pWhereClause->count() == 2,"OFILECursor: Error in Parse Tree");
execute( pComparisonPredicate );
} else
{ // The where-clause is optionally in the majority of cases, i.e. it might be an "optional-where-clause".
DBG_ASSERT(SQL_ISRULE(pWhereClause,opt_where_clause),"OPredicateCompiler: Error in Parse Tree");
}
}
OOperand* OPredicateCompiler::execute(OSQLParseNode const * pPredicateNode)
{
OOperand* pOperand = nullptr; if (pPredicateNode->count() == 3 && // Expression is bracketed
SQL_ISPUNCTUATION(pPredicateNode->getChild(0),"(") &&
SQL_ISPUNCTUATION(pPredicateNode->getChild(2),")"))
{
execute(pPredicateNode->getChild(1));
} elseif ((SQL_ISRULE(pPredicateNode,search_condition) || SQL_ISRULE(pPredicateNode,boolean_term))
&& // AND/OR-linkage:
pPredicateNode->count() == 3)
{
execute(pPredicateNode->getChild(0)); // process the left branch
execute(pPredicateNode->getChild(2)); // process the right branch
if (SQL_ISTOKEN(pPredicateNode->getChild(1),OR)) // OR-Operator
{
m_aCodeList.emplace_back(new OOp_OR);
} elseif (SQL_ISTOKEN(pPredicateNode->getChild(1),AND)) // AND-Operator
m_aCodeList.emplace_back(new OOp_AND); else
{
OSL_FAIL("OPredicateCompiler: Error in Parse Tree");
}
} elseif (SQL_ISRULE(pPredicateNode,boolean_factor))
{
execute(pPredicateNode->getChild(1));
m_aCodeList.emplace_back(new OOp_NOT);
} elseif (SQL_ISRULE(pPredicateNode,comparison_predicate))
{
execute_COMPARE(pPredicateNode);
} elseif (SQL_ISRULE(pPredicateNode,like_predicate))
{
execute_LIKE(pPredicateNode);
} elseif (SQL_ISRULE(pPredicateNode,between_predicate))
{
execute_BETWEEN(pPredicateNode);
} elseif (SQL_ISRULE(pPredicateNode,test_for_null))
{
execute_ISNULL(pPredicateNode);
} elseif(SQL_ISRULE(pPredicateNode,num_value_exp))
{
execute(pPredicateNode->getChild(0)); // process the left branch
execute(pPredicateNode->getChild(2)); // process the right branch if (SQL_ISPUNCTUATION(pPredicateNode->getChild(1),"+"))
{
m_aCodeList.emplace_back(new OOp_ADD);
} elseif (SQL_ISPUNCTUATION(pPredicateNode->getChild(1),"-"))
m_aCodeList.emplace_back(new OOp_SUB); else
{
OSL_FAIL("OPredicateCompiler: Error in Parse Tree num_value_exp");
}
} elseif(SQL_ISRULE(pPredicateNode,term))
{
execute(pPredicateNode->getChild(0)); // process the left branch
execute(pPredicateNode->getChild(2)); // process the right branch if (SQL_ISPUNCTUATION(pPredicateNode->getChild(1),"*"))
{
m_aCodeList.emplace_back(new OOp_MUL);
} elseif (SQL_ISPUNCTUATION(pPredicateNode->getChild(1),"/"))
m_aCodeList.emplace_back(new OOp_DIV); else
{
OSL_FAIL("OPredicateCompiler: Error in Parse Tree num_value_exp");
}
} else
pOperand = execute_Operand(pPredicateNode); // now only simple operands will be processed
if ( pColumnOp && pOb1 && pOb2 )
{ switch(pColumnOp->getDBType())
{ case DataType::CHAR: case DataType::VARCHAR: case DataType::LONGVARCHAR:
pOb1->setValue(pOb1->getValue().getString());
pOb2->setValue(pOb2->getValue().getString()); break; case DataType::DECIMAL: case DataType::NUMERIC: case DataType::DOUBLE: case DataType::REAL:
pOb1->setValue(pOb1->getValue().getDouble());
pOb2->setValue(pOb2->getValue().getDouble()); break; case DataType::FLOAT:
pOb1->setValue(pOb1->getValue().getFloat());
pOb2->setValue(pOb2->getValue().getFloat()); break; case DataType::DATE:
pOb1->setValue(pOb1->getValue().getDate());
pOb2->setValue(pOb2->getValue().getDate()); break; case DataType::TIME:
pOb1->setValue(pOb1->getValue().getTime());
pOb2->setValue(pOb2->getValue().getTime()); break; case DataType::TIMESTAMP:
pOb1->setValue(pOb1->getValue().getDateTime());
pOb2->setValue(pOb2->getValue().getDateTime()); break;
}
}
OBoolOperator* pBoolOp = nullptr; if ( bNot )
pBoolOp = new OOp_OR; else
pBoolOp = new OOp_AND;
m_aCodeList.emplace_back(pBoolOp);
}
OSL_ENSURE(pPredicateNode->getChild(0)->isToken(),"The first one must be the name of the function!");
sal_Int32 nTokenId = pPredicateNode->getChild(0)->getTokenID(); switch ( nTokenId )
{ case SQL_TOKEN_CHAR_LENGTH: case SQL_TOKEN_LENGTH: case SQL_TOKEN_OCTET_LENGTH: case SQL_TOKEN_ASCII: case SQL_TOKEN_LCASE: case SQL_TOKEN_LTRIM: case SQL_TOKEN_RTRIM: case SQL_TOKEN_SPACE: case SQL_TOKEN_UCASE: case SQL_TOKEN_ABS: case SQL_TOKEN_ACOS: case SQL_TOKEN_ASIN: case SQL_TOKEN_ATAN: case SQL_TOKEN_CEILING: case SQL_TOKEN_COS: case SQL_TOKEN_DEGREES: case SQL_TOKEN_EXP: case SQL_TOKEN_FLOOR: case SQL_TOKEN_LOG10: case SQL_TOKEN_LN: case SQL_TOKEN_RADIANS: case SQL_TOKEN_SIGN: case SQL_TOKEN_SIN: case SQL_TOKEN_SQRT: case SQL_TOKEN_TAN: case SQL_TOKEN_DAYNAME: case SQL_TOKEN_DAYOFMONTH: case SQL_TOKEN_DAYOFWEEK: case SQL_TOKEN_DAYOFYEAR: case SQL_TOKEN_HOUR: case SQL_TOKEN_MINUTE: case SQL_TOKEN_MONTH: case SQL_TOKEN_MONTHNAME: case SQL_TOKEN_QUARTER: case SQL_TOKEN_SECOND: case SQL_TOKEN_YEAR:
execute(pPredicateNode->getChild(2));
switch( nTokenId )
{ case SQL_TOKEN_CHAR_LENGTH: case SQL_TOKEN_LENGTH: case SQL_TOKEN_OCTET_LENGTH:
pOperator = new OOp_CharLength; break; case SQL_TOKEN_ASCII:
pOperator = new OOp_Ascii; break; case SQL_TOKEN_LCASE:
pOperator = new OOp_Lower; break;
case SQL_TOKEN_LTRIM:
pOperator = new OOp_LTrim; break; case SQL_TOKEN_RTRIM:
pOperator = new OOp_RTrim; break; case SQL_TOKEN_SPACE:
pOperator = new OOp_Space; break; case SQL_TOKEN_UCASE:
pOperator = new OOp_Upper; break; case SQL_TOKEN_ABS:
pOperator = new OOp_Abs; break; case SQL_TOKEN_ACOS:
pOperator = new OOp_ACos; break; case SQL_TOKEN_ASIN:
pOperator = new OOp_ASin; break; case SQL_TOKEN_ATAN:
pOperator = new OOp_ATan; break; case SQL_TOKEN_CEILING:
pOperator = new OOp_Ceiling; break; case SQL_TOKEN_COS:
pOperator = new OOp_Cos; break; case SQL_TOKEN_DEGREES:
pOperator = new OOp_Degrees; break; case SQL_TOKEN_EXP:
pOperator = new OOp_Exp; break; case SQL_TOKEN_FLOOR:
pOperator = new OOp_Floor; break; case SQL_TOKEN_LOG10:
pOperator = new OOp_Log10; break; case SQL_TOKEN_LN:
pOperator = new OOp_Ln; break; case SQL_TOKEN_RADIANS:
pOperator = new OOp_Radians; break; case SQL_TOKEN_SIGN:
pOperator = new OOp_Sign; break; case SQL_TOKEN_SIN:
pOperator = new OOp_Sin; break; case SQL_TOKEN_SQRT:
pOperator = new OOp_Sqrt; break; case SQL_TOKEN_TAN:
pOperator = new OOp_Tan; break; case SQL_TOKEN_DAYOFWEEK:
pOperator = new OOp_DayOfWeek; break; case SQL_TOKEN_DAYOFMONTH:
pOperator = new OOp_DayOfMonth; break; case SQL_TOKEN_DAYOFYEAR:
pOperator = new OOp_DayOfYear; break; case SQL_TOKEN_MONTH:
pOperator = new OOp_Month; break; case SQL_TOKEN_DAYNAME:
pOperator = new OOp_DayName; break; case SQL_TOKEN_MONTHNAME:
pOperator = new OOp_MonthName; break; case SQL_TOKEN_QUARTER:
pOperator = new OOp_Quarter; break; case SQL_TOKEN_YEAR:
pOperator = new OOp_Year; break; case SQL_TOKEN_HOUR:
pOperator = new OOp_Hour; break; case SQL_TOKEN_MINUTE:
pOperator = new OOp_Minute; break; case SQL_TOKEN_SECOND:
pOperator = new OOp_Second; break; default:
OSL_FAIL("Error in switch!");
} break; case SQL_TOKEN_CHAR: case SQL_TOKEN_CONCAT: case SQL_TOKEN_INSERT: case SQL_TOKEN_LEFT: case SQL_TOKEN_LOCATE: case SQL_TOKEN_LOCATE_2: case SQL_TOKEN_REPEAT: case SQL_TOKEN_REPLACE: case SQL_TOKEN_RIGHT: case SQL_TOKEN_MOD: case SQL_TOKEN_ROUND: case SQL_TOKEN_LOGF: case SQL_TOKEN_LOG: case SQL_TOKEN_POWER: case SQL_TOKEN_ATAN2: case SQL_TOKEN_PI: case SQL_TOKEN_CURDATE: case SQL_TOKEN_CURTIME: case SQL_TOKEN_NOW: case SQL_TOKEN_WEEK:
{
m_aCodeList.emplace_back(new OStopOperand);
OSQLParseNode* pList = pPredicateNode->getChild(2); for (size_t i=0; i < pList->count(); ++i)
execute(pList->getChild(i));
switch( nTokenId )
{ case SQL_TOKEN_CHAR:
pOperator = new OOp_Char; break; case SQL_TOKEN_CONCAT:
pOperator = new OOp_Concat; break; case SQL_TOKEN_INSERT:
pOperator = new OOp_Insert; break; case SQL_TOKEN_LEFT:
pOperator = new OOp_Left; break; case SQL_TOKEN_LOCATE: case SQL_TOKEN_LOCATE_2:
pOperator = new OOp_Locate; break; case SQL_TOKEN_REPEAT:
pOperator = new OOp_Repeat; break; case SQL_TOKEN_REPLACE:
pOperator = new OOp_Replace; break; case SQL_TOKEN_RIGHT:
pOperator = new OOp_Right; break; case SQL_TOKEN_MOD:
pOperator = new OOp_Mod; break; case SQL_TOKEN_ROUND:
pOperator = new OOp_Round; break; case SQL_TOKEN_LOGF: case SQL_TOKEN_LOG:
pOperator = new OOp_Log; break; case SQL_TOKEN_POWER:
pOperator = new OOp_Pow; break; case SQL_TOKEN_ATAN2:
pOperator = new OOp_ATan2; break; case SQL_TOKEN_PI:
pOperator = new OOp_Pi; break; case SQL_TOKEN_CURDATE:
pOperator = new OOp_CurDate; break; case SQL_TOKEN_CURTIME:
pOperator = new OOp_CurTime; break; case SQL_TOKEN_NOW:
pOperator = new OOp_Now; break; case SQL_TOKEN_WEEK:
pOperator = new OOp_Week; break; default:
OSL_FAIL("Error in switch!");
}
} break;
case SQL_TOKEN_SUBSTRING:
m_aCodeList.emplace_back(new OStopOperand); if ( pPredicateNode->count() == 4 ) //char_substring_fct
{
OSQLParseNode* pList = pPredicateNode->getChild(2); for (size_t i=0; i < pList->count(); ++i)
execute(pList->getChild(i));
} else
{
execute(pPredicateNode->getChild(2));
execute(pPredicateNode->getChild(4));
execute(pPredicateNode->getChild(5)->getChild(1));
}
pOperator = new OOp_SubString; break;
case SQL_TOKEN_POSITION:
m_aCodeList.emplace_back(new OStopOperand); if ( pPredicateNode->count() == 4 ) //position_exp
{
OSQLParseNode* pList = pPredicateNode->getChild(2); for (size_t i=0; i < pList->count(); ++i)
execute(pList->getChild(i));
} else
{
execute(pPredicateNode->getChild(2));
execute(pPredicateNode->getChild(4));
}
pOperator = new OOp_Locate; break; default:
m_pAnalyzer->getConnection()->throwGenericSQLException(STR_QUERY_FUNCTION_NOT_SUPPORTED,nullptr);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.