mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
MDEV-18789 Port "MDEV-7773 Aggregate stored functions" to sql_yacc_ora.yy
This commit is contained in:
@ -0,0 +1,58 @@
|
|||||||
|
SET sql_mode=ORACLE;
|
||||||
|
create aggregate function f1(x INT) return INT AS
|
||||||
|
begin
|
||||||
|
insert into t1(sal) values (x);
|
||||||
|
return x;
|
||||||
|
end|
|
||||||
|
ERROR HY000: Aggregate specific instruction(FETCH GROUP NEXT ROW) missing from the aggregate function
|
||||||
|
create function f1(x INT) return INT AS
|
||||||
|
begin
|
||||||
|
set x=5;
|
||||||
|
fetch group next row;
|
||||||
|
return x+1;
|
||||||
|
end |
|
||||||
|
ERROR HY000: Non-aggregate function contains aggregate specific instructions: (FETCH GROUP NEXT ROW)
|
||||||
|
CREATE TABLE marks(stud_id INT, grade_count INT);
|
||||||
|
INSERT INTO marks VALUES (1,6), (2,4), (3,7), (4,5), (5,8);
|
||||||
|
SELECT * FROM marks;
|
||||||
|
stud_id grade_count
|
||||||
|
1 6
|
||||||
|
2 4
|
||||||
|
3 7
|
||||||
|
4 5
|
||||||
|
5 8
|
||||||
|
# Using PL/SQL syntax: EXCEPTION WHEN NO_DATA_FOUND
|
||||||
|
CREATE AGGREGATE FUNCTION IF NOT EXISTS aggregate_count(x INT) RETURN INT AS
|
||||||
|
count_students INT DEFAULT 0;
|
||||||
|
BEGIN
|
||||||
|
LOOP
|
||||||
|
FETCH GROUP NEXT ROW;
|
||||||
|
IF x THEN
|
||||||
|
count_students:= count_students + 1;
|
||||||
|
END IF;
|
||||||
|
END LOOP;
|
||||||
|
EXCEPTION
|
||||||
|
WHEN NO_DATA_FOUND THEN
|
||||||
|
RETURN count_students;
|
||||||
|
END aggregate_count //
|
||||||
|
SELECT aggregate_count(stud_id) FROM marks;
|
||||||
|
aggregate_count(stud_id)
|
||||||
|
5
|
||||||
|
DROP FUNCTION IF EXISTS aggregate_count;
|
||||||
|
# Using SQL/PSM systax: CONTINUE HANDLER
|
||||||
|
CREATE AGGREGATE FUNCTION IF NOT EXISTS aggregate_count(x INT) RETURN INT AS
|
||||||
|
count_students INT DEFAULT 0;
|
||||||
|
CONTINUE HANDLER FOR NOT FOUND RETURN count_students;
|
||||||
|
BEGIN
|
||||||
|
LOOP
|
||||||
|
FETCH GROUP NEXT ROW;
|
||||||
|
IF x THEN
|
||||||
|
SET count_students= count_students + 1;
|
||||||
|
END IF;
|
||||||
|
END LOOP;
|
||||||
|
END //
|
||||||
|
SELECT aggregate_count(stud_id) FROM marks;
|
||||||
|
aggregate_count(stud_id)
|
||||||
|
5
|
||||||
|
DROP FUNCTION IF EXISTS aggregate_count;
|
||||||
|
DROP TABLE marks;
|
@ -0,0 +1,66 @@
|
|||||||
|
SET sql_mode=ORACLE;
|
||||||
|
|
||||||
|
delimiter |;
|
||||||
|
--error ER_INVALID_AGGREGATE_FUNCTION
|
||||||
|
create aggregate function f1(x INT) return INT AS
|
||||||
|
begin
|
||||||
|
insert into t1(sal) values (x);
|
||||||
|
return x;
|
||||||
|
end|
|
||||||
|
|
||||||
|
--error ER_NOT_AGGREGATE_FUNCTION
|
||||||
|
create function f1(x INT) return INT AS
|
||||||
|
begin
|
||||||
|
set x=5;
|
||||||
|
fetch group next row;
|
||||||
|
return x+1;
|
||||||
|
end |
|
||||||
|
|
||||||
|
DELIMITER ;|
|
||||||
|
|
||||||
|
|
||||||
|
CREATE TABLE marks(stud_id INT, grade_count INT);
|
||||||
|
INSERT INTO marks VALUES (1,6), (2,4), (3,7), (4,5), (5,8);
|
||||||
|
SELECT * FROM marks;
|
||||||
|
|
||||||
|
--echo # Using PL/SQL syntax: EXCEPTION WHEN NO_DATA_FOUND
|
||||||
|
|
||||||
|
DELIMITER //;
|
||||||
|
CREATE AGGREGATE FUNCTION IF NOT EXISTS aggregate_count(x INT) RETURN INT AS
|
||||||
|
count_students INT DEFAULT 0;
|
||||||
|
BEGIN
|
||||||
|
LOOP
|
||||||
|
FETCH GROUP NEXT ROW;
|
||||||
|
IF x THEN
|
||||||
|
count_students:= count_students + 1;
|
||||||
|
END IF;
|
||||||
|
END LOOP;
|
||||||
|
EXCEPTION
|
||||||
|
WHEN NO_DATA_FOUND THEN
|
||||||
|
RETURN count_students;
|
||||||
|
END aggregate_count //
|
||||||
|
DELIMITER ;//
|
||||||
|
SELECT aggregate_count(stud_id) FROM marks;
|
||||||
|
DROP FUNCTION IF EXISTS aggregate_count;
|
||||||
|
|
||||||
|
|
||||||
|
--echo # Using SQL/PSM systax: CONTINUE HANDLER
|
||||||
|
|
||||||
|
DELIMITER //;
|
||||||
|
CREATE AGGREGATE FUNCTION IF NOT EXISTS aggregate_count(x INT) RETURN INT AS
|
||||||
|
count_students INT DEFAULT 0;
|
||||||
|
CONTINUE HANDLER FOR NOT FOUND RETURN count_students;
|
||||||
|
BEGIN
|
||||||
|
LOOP
|
||||||
|
FETCH GROUP NEXT ROW;
|
||||||
|
IF x THEN
|
||||||
|
SET count_students= count_students + 1;
|
||||||
|
END IF;
|
||||||
|
END LOOP;
|
||||||
|
END //
|
||||||
|
DELIMITER ;//
|
||||||
|
SELECT aggregate_count(stud_id) FROM marks;
|
||||||
|
DROP FUNCTION IF EXISTS aggregate_count;
|
||||||
|
|
||||||
|
|
||||||
|
DROP TABLE marks;
|
@ -8186,6 +8186,15 @@ bool LEX::sp_add_cfetch(THD *thd, const LEX_CSTRING *name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool LEX::sp_add_agg_cfetch()
|
||||||
|
{
|
||||||
|
sphead->m_flags|= sp_head::HAS_AGGREGATE_INSTR;
|
||||||
|
sp_instr_agg_cfetch *i=
|
||||||
|
new (thd->mem_root) sp_instr_agg_cfetch(sphead->instructions(), spcont);
|
||||||
|
return i == NULL || sphead->add_instr(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool LEX::create_or_alter_view_finalize(THD *thd, Table_ident *table_ident)
|
bool LEX::create_or_alter_view_finalize(THD *thd, Table_ident *table_ident)
|
||||||
{
|
{
|
||||||
sql_command= SQLCOM_CREATE_VIEW;
|
sql_command= SQLCOM_CREATE_VIEW;
|
||||||
|
@ -4244,6 +4244,7 @@ public:
|
|||||||
return check_create_options(create_info);
|
return check_create_options(create_info);
|
||||||
}
|
}
|
||||||
bool sp_add_cfetch(THD *thd, const LEX_CSTRING *name);
|
bool sp_add_cfetch(THD *thd, const LEX_CSTRING *name);
|
||||||
|
bool sp_add_agg_cfetch();
|
||||||
|
|
||||||
bool set_command_with_check(enum_sql_command command,
|
bool set_command_with_check(enum_sql_command command,
|
||||||
uint scope,
|
uint scope,
|
||||||
|
@ -2060,7 +2060,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
|
|||||||
opt_field_or_var_spec fields_or_vars opt_load_data_set_spec
|
opt_field_or_var_spec fields_or_vars opt_load_data_set_spec
|
||||||
view_list_opt view_list view_select
|
view_list_opt view_list view_select
|
||||||
trigger_tail sp_tail sf_tail event_tail
|
trigger_tail sp_tail sf_tail event_tail
|
||||||
udf_tail create_function_tail create_aggregate_function_tail
|
udf_tail
|
||||||
|
create_function_tail
|
||||||
|
create_aggregate_function_tail
|
||||||
install uninstall partition_entry binlog_base64_event
|
install uninstall partition_entry binlog_base64_event
|
||||||
normal_key_options normal_key_opts all_key_opt
|
normal_key_options normal_key_opts all_key_opt
|
||||||
spatial_key_options fulltext_key_options normal_key_opt
|
spatial_key_options fulltext_key_options normal_key_opt
|
||||||
@ -2975,10 +2977,10 @@ create_function_tail:
|
|||||||
;
|
;
|
||||||
|
|
||||||
create_aggregate_function_tail:
|
create_aggregate_function_tail:
|
||||||
sf_tail_aggregate
|
sf_tail_aggregate { }
|
||||||
{ }
|
|
||||||
| udf_tail { Lex->udf.type= UDFTYPE_AGGREGATE; }
|
| udf_tail { Lex->udf.type= UDFTYPE_AGGREGATE; }
|
||||||
;
|
;
|
||||||
|
|
||||||
opt_sequence:
|
opt_sequence:
|
||||||
/* empty */ { }
|
/* empty */ { }
|
||||||
| sequence_defs
|
| sequence_defs
|
||||||
@ -4421,15 +4423,8 @@ sp_proc_stmt_fetch:
|
|||||||
sp_proc_stmt_fetch_head sp_fetch_list { }
|
sp_proc_stmt_fetch_head sp_fetch_list { }
|
||||||
| FETCH_SYM GROUP_SYM NEXT_SYM ROW_SYM
|
| FETCH_SYM GROUP_SYM NEXT_SYM ROW_SYM
|
||||||
{
|
{
|
||||||
LEX *lex= Lex;
|
if (unlikely(Lex->sp_add_agg_cfetch()))
|
||||||
sp_head *sp= lex->sphead;
|
MYSQL_YYABORT;
|
||||||
lex->sphead->m_flags|= sp_head::HAS_AGGREGATE_INSTR;
|
|
||||||
sp_instr_agg_cfetch *i=
|
|
||||||
new (thd->mem_root) sp_instr_agg_cfetch(sp->instructions(),
|
|
||||||
lex->spcont);
|
|
||||||
if (unlikely(i == NULL) ||
|
|
||||||
unlikely(sp->add_instr(i)))
|
|
||||||
MYSQL_YYABORT;
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -1563,7 +1563,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
|
|||||||
opt_field_or_var_spec fields_or_vars opt_load_data_set_spec
|
opt_field_or_var_spec fields_or_vars opt_load_data_set_spec
|
||||||
view_list_opt view_list view_select
|
view_list_opt view_list view_select
|
||||||
trigger_tail sp_tail sf_tail event_tail
|
trigger_tail sp_tail sf_tail event_tail
|
||||||
udf_tail create_function_tail
|
udf_tail
|
||||||
|
create_function_tail_standalone
|
||||||
|
create_aggregate_function_tail_standalone
|
||||||
install uninstall partition_entry binlog_base64_event
|
install uninstall partition_entry binlog_base64_event
|
||||||
normal_key_options normal_key_opts all_key_opt
|
normal_key_options normal_key_opts all_key_opt
|
||||||
spatial_key_options fulltext_key_options normal_key_opt
|
spatial_key_options fulltext_key_options normal_key_opt
|
||||||
@ -2403,13 +2405,23 @@ create:
|
|||||||
{
|
{
|
||||||
Lex->pop_select(); //main select
|
Lex->pop_select(); //main select
|
||||||
}
|
}
|
||||||
|
| create_or_replace definer AGGREGATE_SYM FUNCTION_SYM
|
||||||
|
{
|
||||||
|
if (Lex->main_select_push())
|
||||||
|
MYSQL_YYABORT;
|
||||||
|
Lex->create_info.set($1);
|
||||||
|
}
|
||||||
|
sf_tail_aggregate_standalone
|
||||||
|
{
|
||||||
|
Lex->pop_select(); //main select
|
||||||
|
}
|
||||||
| create_or_replace no_definer FUNCTION_SYM
|
| create_or_replace no_definer FUNCTION_SYM
|
||||||
{
|
{
|
||||||
if (Lex->main_select_push())
|
if (Lex->main_select_push())
|
||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
Lex->create_info.set($1);
|
Lex->create_info.set($1);
|
||||||
}
|
}
|
||||||
create_function_tail
|
create_function_tail_standalone
|
||||||
{
|
{
|
||||||
Lex->pop_select(); //main select
|
Lex->pop_select(); //main select
|
||||||
}
|
}
|
||||||
@ -2418,9 +2430,8 @@ create:
|
|||||||
if (Lex->main_select_push())
|
if (Lex->main_select_push())
|
||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
Lex->create_info.set($1);
|
Lex->create_info.set($1);
|
||||||
Lex->udf.type= UDFTYPE_AGGREGATE;
|
|
||||||
}
|
}
|
||||||
udf_tail
|
create_aggregate_function_tail_standalone
|
||||||
{
|
{
|
||||||
Lex->pop_select(); //main select
|
Lex->pop_select(); //main select
|
||||||
}
|
}
|
||||||
@ -2502,6 +2513,39 @@ create:
|
|||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
sf_tail_not_aggregate_standalone:
|
||||||
|
sf_tail_standalone
|
||||||
|
{
|
||||||
|
if (unlikely(Lex->sphead->m_flags & sp_head::HAS_AGGREGATE_INSTR))
|
||||||
|
{
|
||||||
|
my_yyabort_error((ER_NOT_AGGREGATE_FUNCTION, MYF(0)));
|
||||||
|
}
|
||||||
|
Lex->sphead->set_chistics_agg_type(NOT_AGGREGATE);
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
sf_tail_aggregate_standalone:
|
||||||
|
sf_tail_standalone
|
||||||
|
{
|
||||||
|
if (unlikely(!(Lex->sphead->m_flags & sp_head::HAS_AGGREGATE_INSTR)))
|
||||||
|
{
|
||||||
|
my_yyabort_error((ER_INVALID_AGGREGATE_FUNCTION, MYF(0)));
|
||||||
|
}
|
||||||
|
Lex->sphead->set_chistics_agg_type(GROUP_AGGREGATE);
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
create_function_tail_standalone:
|
||||||
|
sf_tail_not_aggregate_standalone { }
|
||||||
|
| udf_tail { Lex->udf.type= UDFTYPE_FUNCTION; }
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
create_aggregate_function_tail_standalone:
|
||||||
|
sf_tail_aggregate_standalone { }
|
||||||
|
| udf_tail { Lex->udf.type= UDFTYPE_AGGREGATE; }
|
||||||
|
;
|
||||||
|
|
||||||
package_implementation_executable_section:
|
package_implementation_executable_section:
|
||||||
END
|
END
|
||||||
{
|
{
|
||||||
@ -2696,10 +2740,6 @@ package_specification_element:
|
|||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
create_function_tail:
|
|
||||||
sf_tail_standalone { }
|
|
||||||
| udf_tail { Lex->udf.type= UDFTYPE_FUNCTION; }
|
|
||||||
;
|
|
||||||
|
|
||||||
opt_sequence:
|
opt_sequence:
|
||||||
/* empty */ { }
|
/* empty */ { }
|
||||||
@ -4281,7 +4321,12 @@ sp_proc_stmt_fetch_head:
|
|||||||
;
|
;
|
||||||
|
|
||||||
sp_proc_stmt_fetch:
|
sp_proc_stmt_fetch:
|
||||||
sp_proc_stmt_fetch_head sp_fetch_list { }
|
sp_proc_stmt_fetch_head sp_fetch_list { }
|
||||||
|
| FETCH_SYM GROUP_SYM NEXT_SYM ROW_SYM
|
||||||
|
{
|
||||||
|
if (unlikely(Lex->sp_add_agg_cfetch()))
|
||||||
|
MYSQL_YYABORT;
|
||||||
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
sp_proc_stmt_close:
|
sp_proc_stmt_close:
|
||||||
@ -18008,11 +18053,6 @@ sf_tail:
|
|||||||
{
|
{
|
||||||
if (unlikely(Lex->sp_body_finalize_function(thd)))
|
if (unlikely(Lex->sp_body_finalize_function(thd)))
|
||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
if (unlikely(Lex->sphead->m_flags & sp_head::HAS_AGGREGATE_INSTR))
|
|
||||||
{
|
|
||||||
my_yyabort_error((ER_NOT_AGGREGATE_FUNCTION, MYF(0)));
|
|
||||||
}
|
|
||||||
Lex->sphead->set_chistics_agg_type(NOT_AGGREGATE);
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user