mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 03:52:35 +01:00
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.
This commit is contained in:
parent
2cfc450bf7
commit
9d9c60fb12
15 changed files with 768 additions and 6 deletions
|
@ -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}
|
||||
)
|
||||
|
|
|
@ -122,7 +122,7 @@ SET (SQL_SOURCE
|
|||
sql_profile.cc event_parse_data.cc sql_alter.cc
|
||||
sql_signal.cc rpl_handler.cc mdl.cc sql_admin.cc
|
||||
transaction.cc sys_vars.cc sql_truncate.cc datadict.cc
|
||||
sql_reload.cc sql_cmd.h item_inetfunc.cc
|
||||
sql_reload.cc sql_cmd.h item_inetfunc.cc
|
||||
|
||||
# added in MariaDB:
|
||||
sql_explain.h sql_explain.cc
|
||||
|
@ -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 @@ public:
|
|||
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 @@ public:
|
|||
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 @@ public:
|
|||
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) {}
|
||||
|
@ -726,7 +729,7 @@ public:
|
|||
|
||||
|
||||
class Item_sum_sum :public Item_sum_num,
|
||||
public Type_handler_hybrid_field_type
|
||||
public Type_handler_hybrid_field_type
|
||||
{
|
||||
protected:
|
||||
double sum;
|
||||
|
|
13
sql/item_windowfunc.cc
Normal file
13
sql/item_windowfunc.cc
Normal file
|
@ -0,0 +1,13 @@
|
|||
#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;
|
||||
}
|
177
sql/item_windowfunc.h
Normal file
177
sql/item_windowfunc.h
Normal file
|
@ -0,0 +1,177 @@
|
|||
#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 */
|
13
sql/lex.h
13
sql/lex.h
|
@ -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 @@ public:
|
|||
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 @@ public:
|
|||
}
|
||||
|
||||
|
||||
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);
|
||||
|
|
79
sql/sql_window.cc
Normal file
79
sql/sql_window.cc
Normal file
|
@ -0,0 +1,79 @@
|
|||
#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);
|
||||
}
|
124
sql/sql_window.h
Normal file
124
sql/sql_window.h
Normal file
|
@ -0,0 +1,124 @@
|
|||
|
||||
#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 */
|
262
sql/sql_yacc.yy
262
sql/sql_yacc.yy
|
@ -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
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue