StoneDB/sql/parse_tree_helpers.h

208 lines
6.4 KiB
C++

/* Copyright (c) 2013, 2021, Oracle and/or its affiliates.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License, version 2.0,
as published by the Free Software Foundation.
This program is also distributed with certain software (including
but not limited to OpenSSL) that is licensed under separate terms,
as designated in a particular file or component or in included license
documentation. The authors of MySQL hereby grant you an additional
permission to link the program and your derivative works with the
separately licensed software that they have included with MySQL.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License, version 2.0, for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
#ifndef PARSE_TREE_HELPERS_INCLUDED
#define PARSE_TREE_HELPERS_INCLUDED
#include "item_func.h" // Item etc.
#include "set_var.h" // enum_var_type
typedef class st_select_lex SELECT_LEX;
/**
Base class for parse-time Item objects
Parse-time Item objects are placeholders for real Item objects: in some
cases it is not easy or even possible to decide what exact Item class object
we need to allocate in the parser. Parse-time Item objects are intended
to defer real Item object allocation to the contextualization phase (see
the Item::itemize() function).
This wrapper class overrides abstract virtual functions of the parent
class with dummy wrappers to make C++ compiler happy.
*/
class Parse_tree_item : public Item
{
public:
explicit Parse_tree_item(const POS &pos) : Item(pos) {}
virtual enum Type type() const { return INVALID_ITEM; }
virtual double val_real() { assert(0); return 0; }
virtual longlong val_int() { assert(0); return 0; }
virtual String *val_str(String *) { assert(0); return NULL; }
virtual my_decimal *val_decimal(my_decimal *) { assert(0); return NULL; }
virtual bool get_date(MYSQL_TIME *, uint) { assert(0); return false; }
virtual bool get_time(MYSQL_TIME *) { assert(0); return false; }
};
/**
Wrapper class for an Item list head, used to allocate Item lists in the parser
in a context-independent way
*/
class PT_item_list : public Parse_tree_node
{
typedef Parse_tree_node super;
public:
List<Item> value;
virtual bool contextualize(Parse_context *pc)
{
if (super::contextualize(pc))
return true;
List_iterator<Item> it(value);
Item *item;
while ((item= it++))
{
if (item->itemize(pc, &item))
return true;
it.replace(item);
}
return false;
}
bool is_empty() const { return value.is_empty(); }
uint elements() const { return value.elements; }
bool push_back(Item *item)
{
/*
Item may be NULL in case of OOM: just ignore it and check thd->is_error()
in the caller code.
*/
return item == NULL || value.push_back(item);
}
bool push_front(Item *item)
{
/*
Item may be NULL in case of OOM: just ignore it and check thd->is_error()
in the caller code.
*/
return item == NULL || value.push_front(item);
}
Item *pop_front()
{
assert(!is_empty());
return value.pop();
}
};
/**
Helper function to imitate dynamic_cast for Item_cond hierarchy
@param To destination type (Item_cond_and etc.)
@param Tag Functype tag to compare from->functype() with
@param from source item
@return typecasted item of the type To or NULL
*/
template<class To, Item_func::Functype Tag>
To *item_cond_cast(Item * const from)
{
return ((from->type() == Item::COND_ITEM &&
static_cast<Item_func *>(from)->functype() == Tag) ?
static_cast<To *>(from) : NULL);
}
/**
Flatten associative operators at parse time
This function flattens AND and OR operators at parse time if applicable,
otherwise it creates new Item_cond_and or Item_cond_or respectively.
@param Class Item_cond_and or Item_cond_or
@param Tag COND_AND_FUNC (for Item_cond_and) or COND_OR_FUNC otherwise
@param mem_root MEM_ROOT
@param pos parse location
@param left left argument of the operator
@param right right argument of the operator
@return resulting parse tree Item
*/
template<class Class, Item_func::Functype Tag>
Item *flatten_associative_operator(MEM_ROOT *mem_root, const POS &pos,
Item *left, Item *right)
{
if (left == NULL || right == NULL)
return NULL;
Class *left_func= item_cond_cast<Class, Tag>(left);
Class *right_func= item_cond_cast<Class, Tag>(right);
if (left_func)
{
if (right_func)
{
// (X1 op X2) op (Y1 op Y2) ==> op (X1, X2, Y1, Y2)
right_func->add_at_head(left_func->argument_list());
return right;
}
else
{
// (X1 op X2) op Y ==> op (X1, X2, Y)
left_func->add(right);
return left;
}
}
else if (right_func)
{
// X op (Y1 op Y2) ==> op (X, Y1, Y2)
right_func->add_at_head(left);
return right;
}
else
{
/* X op Y */
return new (mem_root) Class(pos, left, right);
}
}
Item_splocal* create_item_for_sp_var(THD *thd,
LEX_STRING name,
class sp_variable *spv,
const char *query_start_ptr,
const char *start,
const char *end);
bool setup_select_in_parentheses(SELECT_LEX *);
void my_syntax_error(const char *s);
bool find_sys_var_null_base(THD *thd, struct sys_var_with_base *tmp);
bool set_system_variable(THD *thd, struct sys_var_with_base *tmp,
enum enum_var_type var_type, Item *val);
LEX_STRING make_string(THD *thd, const char *start_ptr, const char *end_ptr);
bool set_trigger_new_row(Parse_context *pc,
LEX_STRING trigger_field_name,
Item *expr_item,
LEX_STRING expr_query);
void sp_create_assignment_lex(THD *thd, const char *option_ptr);
bool sp_create_assignment_instr(THD *thd, const char *expr_end_ptr);
#endif /* PARSE_TREE_HELPERS_INCLUDED */