Commit 9d9c60fb authored by Igor Babaev's avatar Igor Babaev

Initial patch for the implementation of window functions (MDEV-6115):

- All parsing problems look like resolved
- Stub performing name resolution of window functions
in simplest queries has been added.
parent 2cfc450b
......@@ -109,6 +109,7 @@ SET(SQL_EMBEDDED_SOURCES emb_qcache.cc libmysqld.c lib_sql.cc
../sql/table_cache.cc ../sql/mf_iocache_encr.cc
../sql/item_inetfunc.cc
../sql/wsrep_dummy.cc ../sql/encryption.cc
../sql/item_windowfunc.cc ../sql/sql_window.cc
${GEN_SOURCES}
${MYSYS_LIBWRAP_SOURCE}
)
......
......@@ -137,6 +137,7 @@ SET (SQL_SOURCE
my_json_writer.cc my_json_writer.h
rpl_gtid.cc rpl_parallel.cc
sql_type.cc sql_type.h
item_windowfunc.cc sql_window.cc
${WSREP_SOURCES}
table_cache.cc encryption.cc
${CMAKE_CURRENT_BINARY_DIR}/sql_builtin.cc
......
......@@ -628,7 +628,8 @@ class Item: public Value_source,
static void operator delete(void *ptr,size_t size) { TRASH(ptr, size); }
static void operator delete(void *ptr, MEM_ROOT *mem_root) {}
enum Type {FIELD_ITEM= 0, FUNC_ITEM, SUM_FUNC_ITEM, STRING_ITEM,
enum Type {FIELD_ITEM= 0, FUNC_ITEM, SUM_FUNC_ITEM,
WINDOW_FUNC_ITEM, STRING_ITEM,
INT_ITEM, REAL_ITEM, NULL_ITEM, VARBIN_ITEM,
COPY_STR_ITEM, FIELD_AVG_ITEM, DEFAULT_VALUE_ITEM,
PROC_ITEM,COND_ITEM, REF_ITEM, FIELD_STD_ITEM,
......
......@@ -347,7 +347,9 @@ class Item_sum :public Item_func_or_sum
enum Sumfunctype
{ COUNT_FUNC, COUNT_DISTINCT_FUNC, SUM_FUNC, SUM_DISTINCT_FUNC, AVG_FUNC,
AVG_DISTINCT_FUNC, MIN_FUNC, MAX_FUNC, STD_FUNC,
VARIANCE_FUNC, SUM_BIT_FUNC, UDF_SUM_FUNC, GROUP_CONCAT_FUNC
VARIANCE_FUNC, SUM_BIT_FUNC, UDF_SUM_FUNC, GROUP_CONCAT_FUNC,
ROW_NUMBER_FUNC, RANK_FUNC, DENSE_RANK_FUNC, PERCENT_RANK_FUNC,
CUME_DIST_FUNC
};
Item **ref_by; /* pointer to a ref to the object used to register it */
......@@ -712,6 +714,7 @@ class Item_sum_num :public Item_sum
class Item_sum_int :public Item_sum_num
{
public:
Item_sum_int(THD *thd): Item_sum_num(thd) {}
Item_sum_int(THD *thd, Item *item_par): Item_sum_num(thd, item_par) {}
Item_sum_int(THD *thd, List<Item> &list): Item_sum_num(thd, list) {}
Item_sum_int(THD *thd, Item_sum_int *item) :Item_sum_num(thd, item) {}
......
#include "item_windowfunc.h"
bool
Item_window_func::fix_fields(THD *thd, Item **ref)
{
DBUG_ASSERT(fixed == 0);
if (window_func->fix_fields(thd, ref))
return TRUE;
fixed= 1;
return FALSE;
}
#ifndef ITEM_WINDOWFUNC_INCLUDED
#define ITEM_WINDOWFUNC_INCLUDED
#include "my_global.h"
#include "item.h"
class Window_spec;
class Item_sum_row_number: public Item_sum_int
{
longlong count;
void clear() {}
bool add() { return false; }
void update_field() {}
public:
Item_sum_row_number(THD *thd)
: Item_sum_int(thd), count(0) {}
enum Sumfunctype sum_func () const
{
return ROW_NUMBER_FUNC;
}
const char*func_name() const
{
return "row_number";
}
};
class Item_sum_rank: public Item_sum_int
{
longlong rank;
void clear() {}
bool add() { return false; }
void update_field() {}
public:
Item_sum_rank(THD *thd)
: Item_sum_int(thd), rank(0) {}
enum Sumfunctype sum_func () const
{
return RANK_FUNC;
}
const char*func_name() const
{
return "rank";
}
};
class Item_sum_dense_rank: public Item_sum_int
{
longlong dense_rank;
void clear() {}
bool add() { return false; }
void update_field() {}
public:
Item_sum_dense_rank(THD *thd)
: Item_sum_int(thd), dense_rank(0) {}
enum Sumfunctype sum_func () const
{
return DENSE_RANK_FUNC;
}
const char*func_name() const
{
return "dense_rank";
}
};
class Item_sum_percent_rank: public Item_sum_num
{
longlong rank;
longlong partition_rows;
void clear() {}
bool add() { return false; }
void update_field() {}
public:
Item_sum_percent_rank(THD *thd)
: Item_sum_num(thd), rank(0), partition_rows(0) {}
double val_real() { return 0; }
enum Sumfunctype sum_func () const
{
return PERCENT_RANK_FUNC;
}
const char*func_name() const
{
return "percent_rank";
}
enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
};
class Item_sum_cume_dist: public Item_sum_num
{
longlong count;
longlong partition_rows;
void clear() {}
bool add() { return false; }
void update_field() {}
public:
Item_sum_cume_dist(THD *thd)
: Item_sum_num(thd), count(0), partition_rows(0) {}
double val_real() { return 0; }
enum Sumfunctype sum_func () const
{
return CUME_DIST_FUNC;
}
const char*func_name() const
{
return "cume_dist";
}
enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
};
class Item_window_func : public Item_result_field
{
private:
Item_sum *window_func;
LEX_STRING *window_name;
Window_spec *window_spec;
public:
Item_window_func(THD *thd, Item_sum *win_func, LEX_STRING *win_name)
: Item_result_field(thd), window_func(win_func),
window_name(win_name), window_spec(NULL) {}
Item_window_func(THD *thd, Item_sum *win_func, Window_spec *win_spec)
: Item_result_field(thd), window_func(win_func),
window_name(NULL), window_spec(win_spec) {}
enum Item::Type type() const { return Item::WINDOW_FUNC_ITEM; }
enum_field_types field_type() const { return window_func->field_type(); }
double val_real() { return window_func->val_real(); }
longlong val_int() { return window_func->val_int(); }
String* val_str(String* str) { return window_func->val_str(str); }
my_decimal* val_decimal(my_decimal* dec)
{ return window_func->val_decimal(dec); }
void fix_length_and_dec() { }
const char* func_name() const { return "WF"; }
bool fix_fields(THD *thd, Item **ref);
};
#endif /* ITEM_WINDOWFUNC_INCLUDED */
......@@ -221,6 +221,7 @@ static SYMBOL symbols[] = {
{ "EVERY", SYM(EVERY_SYM)},
{ "EXAMINED", SYM(EXAMINED_SYM)},
{ "EXCHANGE", SYM(EXCHANGE_SYM)},
{ "EXCLUDE", SYM(EXCLUDE_SYM)},
{ "EXECUTE", SYM(EXECUTE_SYM)},
{ "EXISTS", SYM(EXISTS)},
{ "EXIT", SYM(EXIT_SYM)},
......@@ -241,6 +242,7 @@ static SYMBOL symbols[] = {
{ "FLOAT4", SYM(FLOAT_SYM)},
{ "FLOAT8", SYM(DOUBLE_SYM)},
{ "FLUSH", SYM(FLUSH_SYM)},
{ "FOLLOWING", SYM(FOLLOWING_SYM)},
{ "FOR", SYM(FOR_SYM)},
{ "FORCE", SYM(FORCE_SYM)},
{ "FOREIGN", SYM(FOREIGN)},
......@@ -425,9 +427,11 @@ static SYMBOL symbols[] = {
{ "OPTIONALLY", SYM(OPTIONALLY)},
{ "OR", SYM(OR_SYM)},
{ "ORDER", SYM(ORDER_SYM)},
{ "OTHERS", SYM(OTHERS_SYM)},
{ "OUT", SYM(OUT_SYM)},
{ "OUTER", SYM(OUTER)},
{ "OUTFILE", SYM(OUTFILE)},
{ "OVER", SYM(OVER_SYM)},
{ "OWNER", SYM(OWNER_SYM)},
{ "PACK_KEYS", SYM(PACK_KEYS_SYM)},
{ "PAGE", SYM(PAGE_SYM)},
......@@ -446,6 +450,7 @@ static SYMBOL symbols[] = {
{ "POINT", SYM(POINT_SYM)},
{ "POLYGON", SYM(POLYGON)},
{ "PORT", SYM(PORT_SYM)},
{ "PRECEDING", SYM(PRECEDING_SYM)},
{ "PRECISION", SYM(PRECISION)},
{ "PREPARE", SYM(PREPARE_SYM)},
{ "PRESERVE", SYM(PRESERVE_SYM)},
......@@ -601,6 +606,7 @@ static SYMBOL symbols[] = {
{ "TEXT", SYM(TEXT_SYM)},
{ "THAN", SYM(THAN_SYM)},
{ "THEN", SYM(THEN_SYM)},
{ "TIES", SYM(TIES_SYM)},
{ "TIME", SYM(TIME_SYM)},
{ "TIMESTAMP", SYM(TIMESTAMP)},
{ "TIMESTAMPADD", SYM(TIMESTAMP_ADD)},
......@@ -618,6 +624,7 @@ static SYMBOL symbols[] = {
{ "TRUNCATE", SYM(TRUNCATE_SYM)},
{ "TYPE", SYM(TYPE_SYM)},
{ "TYPES", SYM(TYPES_SYM)},
{ "UNBOUNDED", SYM(UNBOUNDED_SYM)},
{ "UNCOMMITTED", SYM(UNCOMMITTED_SYM)},
{ "UNDEFINED", SYM(UNDEFINED_SYM)},
{ "UNDO_BUFFER_SIZE", SYM(UNDO_BUFFER_SIZE_SYM)},
......@@ -659,6 +666,7 @@ static SYMBOL symbols[] = {
{ "WHEN", SYM(WHEN_SYM)},
{ "WHERE", SYM(WHERE)},
{ "WHILE", SYM(WHILE_SYM)},
{ "WINDOW", SYM(WINDOW_SYM)},
{ "WITH", SYM(WITH)},
{ "WORK", SYM(WORK_SYM)},
{ "WRAPPER", SYM(WRAPPER_SYM)},
......@@ -681,10 +689,12 @@ static SYMBOL sql_functions[] = {
{ "BIT_XOR", SYM(BIT_XOR)},
{ "CAST", SYM(CAST_SYM)},
{ "COUNT", SYM(COUNT_SYM)},
{ "CUME_DIST", SYM(CUME_DIST_SYM)},
{ "CURDATE", SYM(CURDATE)},
{ "CURTIME", SYM(CURTIME)},
{ "DATE_ADD", SYM(DATE_ADD_INTERVAL)},
{ "DATE_SUB", SYM(DATE_SUB_INTERVAL)},
{ "DENSE_RANK", SYM(DENSE_RANK_SYM)},
{ "EXTRACT", SYM(EXTRACT_SYM)},
{ "GROUP_CONCAT", SYM(GROUP_CONCAT_SYM)},
{ "MAX", SYM(MAX_SYM)},
......@@ -692,6 +702,9 @@ static SYMBOL sql_functions[] = {
{ "MIN", SYM(MIN_SYM)},
{ "NOW", SYM(NOW_SYM)},
{ "POSITION", SYM(POSITION_SYM)},
{ "PERCENT_RANK", SYM(PERCENT_RANK_SYM)},
{ "RANK", SYM(RANK_SYM)},
{ "ROW_NUMBER", SYM(ROW_NUMBER_SYM)},
{ "SESSION_USER", SYM(USER)},
{ "STD", SYM(STD_SYM)},
{ "STDDEV", SYM(STD_SYM)},
......
......@@ -7136,3 +7136,14 @@ ER_KILL_QUERY_DENIED_ERROR
eng "You are not owner of query %lu"
ger "Sie sind nicht Eigentümer von Abfrage %lu"
rus "Вы не являетесь владельцем запроса %lu"
ER_WRONG_WINDOW_SPEC_NAME
eng "Window specification with name '%s' is not defined"
ER_DUP_WINDOW_NAME
eng "Multiple window specifications with the same name '%s'"
ER_PARTITION_LIST_IN_REFERENCING_WINDOW_SPEC
eng "Window specification referencing another one '%s' cannot contain partition list"
ER_ORDER_LIST_IN_REFERENCING_WINDOW_SPEC
eng "Referenced window specification '%s' already contains order list"
ER_WINDOW_FRAME_IN_REFERENCED_WINDOW_SPEC
eng "Referenced window specification '%s' cannot contain window frame"
......@@ -546,6 +546,14 @@ void lex_start(THD *thd)
lex->stmt_var_list.empty();
lex->proc_list.elements=0;
lex->save_group_list.empty();
lex->save_order_list.empty();
lex->win_ref= NULL;
lex->win_frame= NULL;
lex->frame_top_bound= NULL;
lex->frame_bottom_bound= NULL;
lex->win_spec= NULL;
lex->is_lex_started= TRUE;
DBUG_VOID_RETURN;
}
......@@ -1926,6 +1934,7 @@ void st_select_lex::init_query()
select_list_tables= 0;
m_non_agg_field_used= false;
m_agg_func_used= false;
window_specs.empty();
}
void st_select_lex::init_select()
......
......@@ -28,6 +28,7 @@
#include "mem_root_array.h"
#include "sql_cmd.h"
#include "sql_alter.h" // Alter_info
#include "sql_window.h"
/* YACC and LEX Definitions */
......@@ -1070,6 +1071,17 @@ class st_select_lex: public st_select_lex_node
void set_non_agg_field_used(bool val) { m_non_agg_field_used= val; }
void set_agg_func_used(bool val) { m_agg_func_used= val; }
List<Window_spec> window_specs;
void prepare_add_window_spec(THD *thd);
bool add_window_def(THD *thd, LEX_STRING *win_name, LEX_STRING *win_ref,
SQL_I_List<ORDER> win_partition_list,
SQL_I_List<ORDER> win_order_list,
Window_frame *win_frame);
bool add_window_spec(THD *thd, LEX_STRING *win_ref,
SQL_I_List<ORDER> win_partition_list,
SQL_I_List<ORDER> win_order_list,
Window_frame *win_frame);
private:
bool m_non_agg_field_used;
bool m_agg_func_used;
......@@ -2706,6 +2718,14 @@ struct LEX: public Query_tables_list
}
SQL_I_List<ORDER> save_group_list;
SQL_I_List<ORDER> save_order_list;
LEX_STRING *win_ref;
Window_frame *win_frame;
Window_frame_bound *frame_top_bound;
Window_frame_bound *frame_bottom_bound;
Window_spec *win_spec;
inline void free_set_stmt_mem_root()
{
DBUG_ASSERT(!is_arena_for_set_stmt());
......
......@@ -7816,6 +7816,53 @@ TABLE_LIST *st_select_lex::convert_right_join()
DBUG_RETURN(tab1);
}
void st_select_lex::prepare_add_window_spec(THD *thd)
{
LEX *lex= thd->lex;
lex->save_group_list= group_list;
lex->save_order_list= order_list;
lex->win_ref= NULL;
lex->win_frame= NULL;
lex->frame_top_bound= NULL;
lex->frame_bottom_bound= NULL;
group_list.empty();
order_list.empty();
}
bool st_select_lex::add_window_def(THD *thd,
LEX_STRING *win_name,
LEX_STRING *win_ref,
SQL_I_List<ORDER> win_partition_list,
SQL_I_List<ORDER> win_order_list,
Window_frame *win_frame)
{
Window_def *win_def= new (thd->mem_root) Window_def(win_name,
win_ref,
win_partition_list,
win_order_list,
win_frame);
group_list= thd->lex->save_group_list;
order_list= thd->lex->save_order_list;
return (win_def == NULL || window_specs.push_back(win_def));
}
bool st_select_lex::add_window_spec(THD *thd,
LEX_STRING *win_ref,
SQL_I_List<ORDER> win_partition_list,
SQL_I_List<ORDER> win_order_list,
Window_frame *win_frame)
{
Window_spec *win_spec= new (thd->mem_root) Window_spec(win_ref,
win_partition_list,
win_order_list,
win_frame);
group_list= thd->lex->save_group_list;
order_list= thd->lex->save_order_list;
thd->lex->win_spec= win_spec;
return (win_spec == NULL || window_specs.push_back(win_spec));
}
/**
Set lock for all tables in current select level.
......
......@@ -53,6 +53,7 @@
#include "log_slow.h"
#include "sql_derived.h"
#include "sql_statistics.h"
#include "sql_window.h"
#include "debug_sync.h" // DEBUG_SYNC
#include <m_ctype.h>
......@@ -621,6 +622,7 @@ setup_without_group(THD *thd, Ref_ptr_array ref_pointer_array,
COND **conds,
ORDER *order,
ORDER *group,
List<Window_spec> &win_specs,
bool *hidden_group_fields,
uint *reserved)
{
......@@ -654,6 +656,8 @@ setup_without_group(THD *thd, Ref_ptr_array ref_pointer_array,
res= res || setup_group(thd, ref_pointer_array, tables, fields, all_fields,
group, hidden_group_fields);
thd->lex->allow_sum_func= save_allow_sum_func;
res= res || setup_windows(thd, ref_pointer_array, tables, fields, all_fields,
win_specs);
DBUG_RETURN(res);
}
......@@ -794,6 +798,7 @@ JOIN::prepare(TABLE_LIST *tables_init,
if (setup_without_group(thd, ref_ptrs, tables_list,
select_lex->leaf_tables, fields_list,
all_fields, &conds, order, group_list,
select_lex->window_specs,
&hidden_group_fields,
&select_lex->select_n_reserved))
DBUG_RETURN(-1);
......
#include "sql_select.h"
#include "sql_window.h"
bool
Window_spec::check_window_names(List_iterator_fast<Window_spec> &it)
{
char *name= this->name();
char *ref_name= window_reference();
bool win_ref_is_resolved= false;
it.rewind();
Window_spec *win_spec;
while((win_spec= it++) && win_spec != this)
{
char *win_spec_name= win_spec->name();
if (win_spec_name)
{
if (name && my_strcasecmp(system_charset_info, name, win_spec_name) == 0)
{
my_error(ER_DUP_WINDOW_NAME, MYF(0), name);
return true;
}
if (ref_name &&
my_strcasecmp(system_charset_info, ref_name, win_spec_name) == 0)
{
if (win_spec->partition_list.elements)
{
my_error(ER_PARTITION_LIST_IN_REFERENCING_WINDOW_SPEC, MYF(0),
ref_name);
return true;
}
if (win_spec->order_list.elements && order_list.elements)
{
my_error(ER_ORDER_LIST_IN_REFERENCING_WINDOW_SPEC, MYF(0), ref_name);
return true;
}
if (win_spec->window_frame)
{
my_error(ER_WINDOW_FRAME_IN_REFERENCED_WINDOW_SPEC, MYF(0), ref_name);
return true;
}
referenced_win_spec=win_spec;
win_ref_is_resolved= true;
}
}
}
if (ref_name && !win_ref_is_resolved)
{
my_error(ER_WRONG_WINDOW_SPEC_NAME, MYF(0), ref_name);
return true;
}
return false;
}
int
setup_windows(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables,
List<Item> &fields, List<Item> &all_fields,
List<Window_spec> win_specs)
{
Window_spec *win_spec;
DBUG_ENTER("setup_windows");
List_iterator<Window_spec> it(win_specs);
List_iterator_fast<Window_spec> itp(win_specs);
while ((win_spec= it++))
{
bool hidden_group_fields;
if (win_spec->check_window_names(itp) ||
setup_group(thd, ref_pointer_array, tables, fields, all_fields,
win_spec->partition_list.first, &hidden_group_fields) ||
setup_order(thd, ref_pointer_array, tables, fields, all_fields,
win_spec->order_list.first))
{
DBUG_RETURN(1);
}
}
DBUG_RETURN(0);
}
#ifndef SQL_WINDOW_INCLUDED
#define SQL_WINDOW_INCLUDED
#include "my_global.h"
#include "item.h"
class Window_frame_bound : public Sql_alloc
{
public:
enum Bound_precedence_type
{
PRECEDING,
CURRENT, // Used for CURRENT ROW window frame bounds
FOLLOWING
};
Bound_precedence_type precedence_type;
/*
For UNBOUNDED PRECEDING / UNBOUNDED FOLLOWING window frame bounds
precedence type is seto to PRECEDING / FOLLOWING and
offset is set to NULL.
The offset is not meaningful with precedence type CURRENT
*/
Item *offset;
Window_frame_bound(Bound_precedence_type prec_type,
Item *offset_val)
: precedence_type(prec_type), offset(offset_val) {}
};
class Window_frame : public Sql_alloc
{
public:
enum Frame_units
{
UNITS_ROWS,
UNITS_RANGE
};
enum Frame_exclusion
{
EXCL_NONE,
EXCL_CURRENT_ROW,
EXCL_GROUP,
EXCL_TIES
};
Frame_units units;
Window_frame_bound *top_bound;
Window_frame_bound *bottom_bound;
Frame_exclusion exclusion;
Window_frame(Frame_units win_frame_units,
Window_frame_bound *win_frame_top_bound,
Window_frame_bound *win_frame_bottom_bound,
Frame_exclusion win_frame_exclusion)
: units(win_frame_units), top_bound(win_frame_top_bound),
bottom_bound(win_frame_bottom_bound), exclusion(win_frame_exclusion) {}
};
class Window_spec : public Sql_alloc
{
public:
LEX_STRING *window_ref;
SQL_I_List<ORDER> partition_list;
SQL_I_List<ORDER> order_list;
Window_frame *window_frame;
Window_spec *referenced_win_spec;
Window_spec(LEX_STRING *win_ref,
SQL_I_List<ORDER> part_list,
SQL_I_List<ORDER> ord_list,
Window_frame *win_frame)
: window_ref(win_ref), partition_list(part_list), order_list(ord_list),
window_frame(win_frame), referenced_win_spec(NULL) {}
virtual char *name() { return NULL; }
bool check_window_names(List_iterator_fast<Window_spec> &it);
char *window_reference() { return window_ref ? window_ref->str : NULL; }
};
class Window_def : public Window_spec
{
public:
LEX_STRING *window_name;
Window_def(LEX_STRING *win_name,
LEX_STRING *win_ref,
SQL_I_List<ORDER> part_list,
SQL_I_List<ORDER> ord_list,
Window_frame *win_frame)
: Window_spec(win_ref, part_list, ord_list, win_frame),
window_name(win_name) {}
char *name() { return window_name->str; }
};
int setup_windows(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables,
List<Item> &fields, List<Item> &all_fields,
List<Window_spec> win_specs);
#endif /* SQL_WINDOW_INCLUDED */
......@@ -54,6 +54,8 @@
#include "sql_handler.h" // Sql_cmd_handler_*
#include "sql_signal.h"
#include "sql_get_diagnostics.h" // Sql_cmd_get_diagnostics
#include "sql_window.h"
#include "item_windowfunc.h"
#include "event_parse_data.h"
#include "create_options.h"
#include <myisam.h>
......@@ -962,6 +964,8 @@ bool LEX::set_bincmp(CHARSET_INFO *cs, bool bin)
handlerton *db_type;
st_select_lex *select_lex;
struct p_elem_val *p_elem_value;
class Window_frame *window_frame;
class Window_frame_bound *window_frame_bound;
udf_func *udf;
/* enums */
......@@ -987,6 +991,9 @@ bool LEX::set_bincmp(CHARSET_INFO *cs, bool bin)
enum sp_variable::enum_mode spvar_mode;
enum thr_lock_type lock_type;
enum enum_mysql_timestamp_type date_time_type;
enum Window_frame_bound::Bound_precedence_type bound_precedence_type;
enum Window_frame::Frame_units frame_units;
enum Window_frame::Frame_exclusion frame_exclusion;
DDL_options_st object_ddl_options;
}
......@@ -998,10 +1005,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%parse-param { THD *thd }
%lex-param { THD *thd }
/*
Currently there are 121 shift/reduce conflicts.
Currently there are 124 shift/reduce conflicts.
We should not introduce new conflicts any more.
*/
%expect 121
%expect 124
/*
Comments for TOKENS.
......@@ -1124,6 +1131,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token CREATE /* SQL-2003-R */
%token CROSS /* SQL-2003-R */
%token CUBE_SYM /* SQL-2003-R */
%token CUME_DIST_SYM
%token CURDATE /* MYSQL-FUNC */
%token CURRENT_SYM /* SQL-2003-R */
%token CURRENT_USER /* SQL-2003-R */
......@@ -1154,6 +1162,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token DELAYED_SYM
%token DELAY_KEY_WRITE_SYM
%token DELETE_SYM /* SQL-2003-R */
%token DENSE_RANK_SYM
%token DESC /* SQL-2003-N */
%token DESCRIBE /* SQL-2003-R */
%token DES_KEY_FILE
......@@ -1195,6 +1204,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token EVERY_SYM /* SQL-2003-N */
%token EXCHANGE_SYM
%token EXAMINED_SYM
%token EXCLUDE_SYM
%token EXECUTE_SYM /* SQL-2003-R */
%token EXISTS /* SQL-2003-R */
%token EXIT_SYM
......@@ -1213,6 +1223,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token FLOAT_NUM
%token FLOAT_SYM /* SQL-2003-R */
%token FLUSH_SYM
%token FOLLOWING_SYM
%token FORCE_SYM
%token FOREIGN /* SQL-2003-R */
%token FOR_SYM /* SQL-2003-R */
......@@ -1409,9 +1420,11 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token ORDER_SYM /* SQL-2003-R */
%token OR_OR_SYM /* OPERATOR */
%token OR_SYM /* SQL-2003-R */
%token OTHERS_SYM
%token OUTER
%token OUTFILE
%token OUT_SYM /* SQL-2003-R */
%token OVER_SYM
%token OWNER_SYM
%token PACK_KEYS_SYM
%token PAGE_SYM
......@@ -1424,6 +1437,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token PARTITIONS_SYM
%token PARTITIONING_SYM
%token PASSWORD_SYM
%token PERCENT_RANK_SYM
%token PERSISTENT_SYM
%token PHASE_SYM
%token PLUGINS_SYM
......@@ -1432,6 +1446,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token POLYGON
%token PORT_SYM
%token POSITION_SYM /* SQL-2003-N */
%token PRECEDING_SYM
%token PRECISION /* SQL-2003-R */
%token PREPARE_SYM /* SQL-2003-R */
%token PRESERVE_SYM
......@@ -1449,6 +1464,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token QUERY_SYM
%token QUICK
%token RANGE_SYM /* SQL-2003-R */
%token RANK_SYM
%token READS_SYM /* SQL-2003-R */
%token READ_ONLY_SYM
%token READ_SYM /* SQL-2003-N */
......@@ -1498,6 +1514,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token ROW_FORMAT_SYM
%token ROW_SYM /* SQL-2003-R */
%token ROW_COUNT_SYM /* SQL-2003-N */
%token ROW_NUMBER_SYM
%token RTREE_SYM
%token SAVEPOINT_SYM /* SQL-2003-R */
%token SCHEDULE_SYM
......@@ -1588,6 +1605,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token TEXT_SYM
%token THAN_SYM
%token THEN_SYM /* SQL-2003-R */
%token TIES_SYM
%token TIMESTAMP /* SQL-2003-R */
%token TIMESTAMP_ADD
%token TIMESTAMP_DIFF
......@@ -1608,6 +1626,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token TYPE_SYM /* SQL-2003-N */
%token UDF_RETURNS_SYM
%token ULONGLONG_NUM
%token UNBOUNDED_SYM
%token UNCOMMITTED_SYM /* SQL-2003-N */
%token UNDEFINED_SYM
%token UNDERSCORE_CHARSET
......@@ -1649,6 +1668,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token WEIGHT_STRING_SYM
%token WHEN_SYM /* SQL-2003-R */
%token WHERE /* SQL-2003-R */
%token WINDOW_SYM
%token WHILE_SYM
%token WITH /* SQL-2003-R */
%token WITH_CUBE_SYM /* INTERNAL */
......@@ -1787,6 +1807,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
simple_ident_nospvar simple_ident_q
field_or_var limit_option
part_func_expr
window_func_expr
window_func
simple_window_func
function_call_keyword
function_call_nonkeyword
function_call_generic
......@@ -1975,6 +1998,15 @@ END_OF_INPUT
%type <cond_info_item_name> condition_information_item_name;
%type <cond_info_list> condition_information;
%type <NONE> opt_window_clause window_def_list window_def window_spec
%type <lex_str_ptr> window_name
%type <NONE> opt_window_ref opt_window_frame_clause
%type <frame_units> window_frame_units;
%type <NONE> window_frame_extent;
%type <frame_exclusion> opt_window_frame_exclusion;
%type <window_frame_bound> window_frame_start window_frame_bound;
%type <NONE>
'-' '+' '*' '/' '%' '(' ')'
',' '!' '{' '}' '&' '|' AND_SYM OR_SYM OR_OR_SYM BETWEEN_SYM CASE_SYM
......@@ -8497,6 +8529,7 @@ table_expression:
opt_where_clause
opt_group_clause
opt_having_clause
opt_window_clause
opt_order_clause
opt_limit_clause
opt_procedure_clause
......@@ -9221,6 +9254,7 @@ simple_expr:
| param_marker { $$= $1; }
| variable
| sum_expr
| window_func_expr
| simple_expr OR_OR_SYM simple_expr
{
$$= new (thd->mem_root) Item_func_concat(thd, $1, $3);
......@@ -10356,6 +10390,81 @@ sum_expr:
}
;
window_func_expr:
window_func OVER_SYM window_name
{
$$= new (thd->mem_root) Item_window_func(thd, (Item_sum *) $1, $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
|
window_func OVER_SYM window_spec
{
LEX *lex= Lex;
if (Select->add_window_spec(thd, lex->win_ref,
Select->group_list,
Select->order_list,
lex->win_frame))
MYSQL_YYABORT;
$$= new (thd->mem_root) Item_window_func(thd, (Item_sum *) $1,
thd->lex->win_spec);
if ($$ == NULL)
MYSQL_YYABORT;
}
;
window_func:
simple_window_func
|
sum_expr
;
simple_window_func:
ROW_NUMBER_SYM '(' ')'
{
$$= new (thd->mem_root) Item_sum_row_number(thd);
if ($$ == NULL)
MYSQL_YYABORT;
}
|
RANK_SYM '(' ')'
{
$$= new (thd->mem_root) Item_sum_rank(thd);
if ($$ == NULL)
MYSQL_YYABORT;
}
|
DENSE_RANK_SYM '(' ')'
{
$$= new (thd->mem_root) Item_sum_dense_rank(thd);
if ($$ == NULL)
MYSQL_YYABORT;
}
|
PERCENT_RANK_SYM '(' ')'
{
$$= new (thd->mem_root) Item_sum_percent_rank(thd);
if ($$ == NULL)
MYSQL_YYABORT;
}
|
CUME_DIST_SYM '(' ')'
{
$$= new (thd->mem_root) Item_sum_cume_dist(thd);
if ($$ == NULL)
MYSQL_YYABORT;
}
;
window_name:
ident
{
$$= (LEX_STRING *) thd->memdup(&$1, sizeof(LEX_STRING));
if ($$ == NULL)
MYSQL_YYABORT;
}
;
variable:
'@'
{
......@@ -11289,6 +11398,155 @@ olap_opt:
}
;
/*
optional window clause in select
*/
opt_window_clause:
/* empty */
{}
| WINDOW_SYM
window_def_list
{}
;
window_def_list:
window_def_list ',' window_def
| window_def
;
window_def:
window_name AS window_spec
{
LEX *lex= Lex;
if (Select->add_window_def(thd, $1, lex->win_ref,
Select->group_list,
Select->order_list,
lex->win_frame ))
MYSQL_YYABORT;
}
;
window_spec:
'('
{ Select->prepare_add_window_spec(thd); }
opt_window_ref opt_window_partition_clause
opt_window_order_clause opt_window_frame_clause
')'
;
opt_window_ref:
/* empty */ {}
| ident
{
thd->lex->win_ref= (LEX_STRING *) thd->memdup(&$1, sizeof(LEX_STRING));
if (thd->lex->win_ref == NULL)
MYSQL_YYABORT;
}
opt_window_partition_clause:
/* empty */ { }
| PARTITION_SYM BY group_list
;
opt_window_order_clause:
/* empty */ { }
| ORDER_SYM BY order_list
;
opt_window_frame_clause:
/* empty */ {}
| window_frame_units window_frame_extent opt_window_frame_exclusion
{
LEX *lex= Lex;
lex->win_frame=
new (thd->mem_root) Window_frame($1,
lex->frame_top_bound,
lex->frame_bottom_bound,
$3);
if (lex->win_frame == NULL)
MYSQL_YYABORT;
}
;
window_frame_units:
ROWS_SYM { $$= Window_frame::UNITS_ROWS; }
| RANGE_SYM { $$= Window_frame::UNITS_RANGE; }
;
window_frame_extent:
window_frame_start
{
LEX *lex= Lex;
lex->frame_top_bound= $1;
lex->frame_bottom_bound=
new (thd->mem_root)
Window_frame_bound(Window_frame_bound::CURRENT, NULL);
if (lex->frame_bottom_bound == NULL)
MYSQL_YYABORT;
}
| BETWEEN_SYM window_frame_bound AND_SYM window_frame_bound
{
LEX *lex= Lex;
lex->frame_top_bound= $2;
lex->frame_bottom_bound= $4;
}
;
window_frame_start:
UNBOUNDED_SYM PRECEDING_SYM
{
$$= new (thd->mem_root)
Window_frame_bound(Window_frame_bound::PRECEDING, NULL);
if ($$ == NULL)
MYSQL_YYABORT;
}
| CURRENT_SYM ROW_SYM
{
$$= new (thd->mem_root)
Window_frame_bound(Window_frame_bound::CURRENT, NULL);
if ($$ == NULL)
MYSQL_YYABORT;
}
| literal PRECEDING_SYM
{
$$= new (thd->mem_root)
Window_frame_bound(Window_frame_bound::PRECEDING, $1);
if ($$ == NULL)
MYSQL_YYABORT;
}
;
window_frame_bound:
window_frame_start { $$= $1; }
| UNBOUNDED_SYM FOLLOWING_SYM
{
$$= new (thd->mem_root)
Window_frame_bound(Window_frame_bound::FOLLOWING, NULL);
if ($$ == NULL)
MYSQL_YYABORT;
}
| literal FOLLOWING_SYM
{
$$= new (thd->mem_root)
Window_frame_bound(Window_frame_bound::FOLLOWING, $1);
if ($$ == NULL)
MYSQL_YYABORT;
}
;
opt_window_frame_exclusion:
/* empty */ { $$= Window_frame::EXCL_NONE; }
| EXCLUDE_SYM CURRENT_SYM ROW_SYM
{ $$= Window_frame::EXCL_CURRENT_ROW; }
| EXCLUDE_SYM GROUP_SYM
{ $$= Window_frame::EXCL_GROUP; }
| EXCLUDE_SYM TIES_SYM
{ $$= Window_frame::EXCL_TIES; }
| EXCLUDE_SYM NO_SYM OTHERS_SYM
{ $$= Window_frame::EXCL_NONE; }
;
/*
Order by statement in ALTER TABLE
*/
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment