Commit 3b47587f authored by Alexander Barkov's avatar Alexander Barkov

MDEV-18789 Port "MDEV-7773 Aggregate stored functions" to sql_yacc_ora.yy

parent 01d7727b
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;
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 @@ struct LEX: public Query_tables_list
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);
}
;
......
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