MySQL内核技术之“SQL语法修改”

在本例中,我们添加一个hint:

select /*+ PARALLEL(4) */ * from t1;

注意,这里的 /*+ PARALLEL(4) */ 就是hint。 这个是MySQL 5.7之后的新特性,语法规则和Oracle一致。


为了支持这个语法需要改动yacc相关的文件。具体包括:

sql/lex.h

sql/sql_hints.yacc

sql/opt_hints.h

sql/opt_hints.cc

sql/parse_tree_hints.h

sql/parse_tree_hints.cc


1. 在lex.h中,增加关键字:

{ SYM_H("PARALLEL",               PARALLEL_EXECUTION_HINT)},


2. 在opt_hint.h中添加对应的class:

/**
  Parse tree hint object for table level hints.
*/

class PT_table_level_hint : public PT_hint
{
  const LEX_CSTRING qb_name;
  Hint_param_table_list table_list;

  typedef PT_hint super;
public:
  PT_table_level_hint(const LEX_CSTRING qb_name_arg,
                      const Hint_param_table_list &table_list_arg,
                      bool switch_state_arg,
                      opt_hints_enum hint_type_arg)
    : PT_hint(hint_type_arg, switch_state_arg),
      qb_name(qb_name_arg), table_list(table_list_arg)
  {}

  /**
    Function handles table level hint. It also creates
    table hint object (Opt_hints_table) if it does not
    exist.

    @param pc  Pointer to Parse_context object

    @return  true in case of error,
             false otherwise
  */
  virtual bool contextualize(Parse_context *pc);
};

3. 在opt_hints.cc中,添加新的class的处理函数:

bool PT_hint_parallel_execution::contextualize(Parse_context *pc)
{
  if (super::contextualize(pc))
    return true;

  if (pc->thd->lex->sql_command != SQLCOM_SELECT || // not a SELECT statement
      pc->thd->lex->sphead ||                       // or in a SP/trigger/event
      pc->select != pc->thd->lex->select_lex)       // or in a subquery
  {
    push_warning(pc->thd, Sql_condition::SL_WARNING,
                 ER_WARN_UNSUPPORTED_PARALLEL_EXECUTION,
                 ER_THD(pc->thd, ER_WARN_UNSUPPORTED_PARALLEL_EXECUTION));
    return false;
  }

  Opt_hints_global *global_hint= get_global_hints(pc);
  if (global_hint->is_specified(type()))
  {
    // Hint duplication: /*+ PARALLEL ... PARALLEL */
    print_warn(pc->thd, ER_WARN_CONFLICTING_HINT,
               NULL, NULL, NULL, this);
    return false;
  }

  pc->thd->lex->degree_of_parallel= m_degree_of_parallel;
  global_hint->set_switch(switch_on(), type(), false);
  global_hint->parallel_execution= this;
  return false;
}

该函数的目的是把PARALLEL关键字中的参数拿出来。


4. 修改sql_hints.yy文件,添加token和解析方法:

%token PARALLEL_EXECUTION_HINT

%type 
  hint
  max_execution_time_hint
  parallel_execution_hint

hint:
          index_level_hint
        | table_level_hint
        | qb_level_hint
        | qb_name_hint
        | max_execution_time_hint
        | parallel_execution_hint
        ;

parallel_execution_hint:
          PARALLEL_EXECUTION_HINT '(' HINT_ARG_NUMBER ')'
          {
            int error;
            char *end= const_cast($3.str + $3.length);
            longlong n= my_strtoll10($3.str, &end, &error);
            if (error != 0 || end != $3.str + $3.length || n > UINT_MAX32)
            {
              scanner->syntax_warning(ER_THD(thd,
                                             ER_WARN_BAD_PARALLEL_EXECUTION));
              $$= NULL;
            }
            else
            {
              $$= NEW_PTN PT_hint_parallel_execution(n);
              if ($$ == NULL)
                YYABORT; // OOM
            }
          }
        ;


你可能感兴趣的:(MySQL内核技术之“SQL语法修改”)