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)
|
||||
{
|
||||
sql_command= SQLCOM_CREATE_VIEW;
|
||||
|
@ -4244,6 +4244,7 @@ public:
|
||||
return check_create_options(create_info);
|
||||
}
|
||||
bool sp_add_cfetch(THD *thd, const LEX_CSTRING *name);
|
||||
bool sp_add_agg_cfetch();
|
||||
|
||||
bool set_command_with_check(enum_sql_command command,
|
||||
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
|
||||
view_list_opt view_list view_select
|
||||
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
|
||||
normal_key_options normal_key_opts all_key_opt
|
||||
spatial_key_options fulltext_key_options normal_key_opt
|
||||
@ -2975,10 +2977,10 @@ create_function_tail:
|
||||
;
|
||||
|
||||
create_aggregate_function_tail:
|
||||
sf_tail_aggregate
|
||||
{ }
|
||||
sf_tail_aggregate { }
|
||||
| udf_tail { Lex->udf.type= UDFTYPE_AGGREGATE; }
|
||||
;
|
||||
|
||||
opt_sequence:
|
||||
/* empty */ { }
|
||||
| sequence_defs
|
||||
@ -4421,14 +4423,7 @@ sp_proc_stmt_fetch:
|
||||
sp_proc_stmt_fetch_head sp_fetch_list { }
|
||||
| FETCH_SYM GROUP_SYM NEXT_SYM ROW_SYM
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
sp_head *sp= lex->sphead;
|
||||
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)))
|
||||
if (unlikely(Lex->sp_add_agg_cfetch()))
|
||||
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
|
||||
view_list_opt view_list view_select
|
||||
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
|
||||
normal_key_options normal_key_opts all_key_opt
|
||||
spatial_key_options fulltext_key_options normal_key_opt
|
||||
@ -2403,13 +2405,23 @@ create:
|
||||
{
|
||||
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
|
||||
{
|
||||
if (Lex->main_select_push())
|
||||
MYSQL_YYABORT;
|
||||
Lex->create_info.set($1);
|
||||
}
|
||||
create_function_tail
|
||||
create_function_tail_standalone
|
||||
{
|
||||
Lex->pop_select(); //main select
|
||||
}
|
||||
@ -2418,9 +2430,8 @@ create:
|
||||
if (Lex->main_select_push())
|
||||
MYSQL_YYABORT;
|
||||
Lex->create_info.set($1);
|
||||
Lex->udf.type= UDFTYPE_AGGREGATE;
|
||||
}
|
||||
udf_tail
|
||||
create_aggregate_function_tail_standalone
|
||||
{
|
||||
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:
|
||||
END
|
||||
{
|
||||
@ -2696,10 +2740,6 @@ package_specification_element:
|
||||
}
|
||||
;
|
||||
|
||||
create_function_tail:
|
||||
sf_tail_standalone { }
|
||||
| udf_tail { Lex->udf.type= UDFTYPE_FUNCTION; }
|
||||
;
|
||||
|
||||
opt_sequence:
|
||||
/* empty */ { }
|
||||
@ -4282,6 +4322,11 @@ sp_proc_stmt_fetch_head:
|
||||
|
||||
sp_proc_stmt_fetch:
|
||||
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:
|
||||
@ -18008,11 +18053,6 @@ sf_tail:
|
||||
{
|
||||
if (unlikely(Lex->sp_body_finalize_function(thd)))
|
||||
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