summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <kostja@bodhi.(none)>2007-07-05 11:34:04 +0400
committerunknown <kostja@bodhi.(none)>2007-07-05 11:34:04 +0400
commite8966deecc0eda77c5b94c6f0004cc2159dbd158 (patch)
tree8d7427787cd278a6b8772c821b5c2aa97df51b03
parentb1ec3b534d530807995955c1c249496b0912a906 (diff)
downloadmariadb-git-e8966deecc0eda77c5b94c6f0004cc2159dbd158.tar.gz
A fix and a test case for Bug#29050 Creation of a legal stored procedure
fails if a database is not selected prior. The problem manifested itself when a user tried to create a routine that had non-fully-qualified identifiers in its bodies and there was no current database selected. This is a regression introduced by the fix for Bug 19022: The patch for Bug 19022 changes the code to always produce a warning if we can't resolve the current database in the parser. In this case this was not necessary, since even though the produced parsed tree was incorrect, we never re-use sphead that was obtained at first parsing of CREATE PROCEDURE. The sphead that is anyhow used is always obtained through db_load_routine, and there we change the current database to sphead->m_db before calling yyparse. The idea of the fix is to resolve the current database directly using lex->sphead->m_db member when parsing a stored routine body, when such is present. This patch removes the need to reset the current database when loading a trigger or routine definition into SP cache. The redundant code will be removed in 5.1. mysql-test/r/sp.result: Update test results (Bug#29050) mysql-test/r/trigger.result: Update results. mysql-test/t/sp.test: Add a test case for Bug#29050 mysql-test/t/trigger.test: Fix wrong behavior covered with tests. sql/sql_lex.cc: Implement st_lex::copy_db_to(). sql/sql_lex.h: Declare st_lex::copy_db_to(). sql/sql_parse.cc: Use st_lex::copy_db_to() in add_table_to_list, rather than THD::copy_db_to(). The former will use the database of the sphead, if we're parsing a stored routine, not the default database in THD. The default database is needed to initialize tables->db when the database part was not explicitly specified in the identifier. sql/sql_yacc.yy: Use st_lex::copy_db_to() in the parser, rather than THD::copy_db_to(). The former will use the database of the sphead, if we're parsing a stored routine, not the default database in THD.
-rw-r--r--mysql-test/r/sp.result18
-rw-r--r--mysql-test/r/trigger.result4
-rw-r--r--mysql-test/t/sp.test25
-rw-r--r--mysql-test/t/trigger.test4
-rw-r--r--sql/sql_lex.cc37
-rw-r--r--sql/sql_lex.h2
-rw-r--r--sql/sql_parse.cc2
-rw-r--r--sql/sql_yacc.yy15
8 files changed, 93 insertions, 14 deletions
diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result
index 5d7371b0991..7a4deb3ea5f 100644
--- a/mysql-test/r/sp.result
+++ b/mysql-test/r/sp.result
@@ -6183,4 +6183,22 @@ call mysqltest_db1.sp_bug28551();
show warnings;
Level Code Message
drop database mysqltest_db1;
+drop database if exists mysqltest_db1;
+drop table if exists test.t1;
+create database mysqltest_db1;
+use mysqltest_db1;
+drop database mysqltest_db1;
+create table test.t1 (id int);
+insert into test.t1 (id) values (1);
+create procedure test.sp_bug29050() begin select * from t1; end//
+show warnings;
+Level Code Message
+call test.sp_bug29050();
+id
+1
+show warnings;
+Level Code Message
+use test;
+drop procedure sp_bug29050;
+drop table t1;
End of 5.0 tests
diff --git a/mysql-test/r/trigger.result b/mysql-test/r/trigger.result
index 5405a632aa4..290929d476d 100644
--- a/mysql-test/r/trigger.result
+++ b/mysql-test/r/trigger.result
@@ -351,7 +351,7 @@ create trigger trg1 before insert on mysqltest.t1 for each row set @a:= 1;
ERROR HY000: Trigger in wrong schema
use mysqltest;
create trigger test.trg1 before insert on t1 for each row set @a:= 1;
-ERROR HY000: Trigger in wrong schema
+ERROR 42S02: Table 'test.t1' doesn't exist
drop database mysqltest;
use test;
create table t1 (i int, j int default 10, k int not null, key (k));
@@ -842,7 +842,7 @@ drop table t1;
create trigger t1_bi before insert on test.t1 for each row set @a:=0;
ERROR 3D000: No database selected
create trigger test.t1_bi before insert on t1 for each row set @a:=0;
-ERROR 3D000: No database selected
+ERROR 42S02: Table 'test.t1' doesn't exist
drop trigger t1_bi;
ERROR 3D000: No database selected
create table t1 (id int);
diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test
index cfc97fab777..54dc84ad19d 100644
--- a/mysql-test/t/sp.test
+++ b/mysql-test/t/sp.test
@@ -7142,5 +7142,30 @@ create procedure mysqltest_db1.sp_bug28551() begin end;
call mysqltest_db1.sp_bug28551();
show warnings;
drop database mysqltest_db1;
+#
+# Bug#29050 Creation of a legal stored procedure fails if a database is not
+# selected prior
+#
+--disable_warnings
+drop database if exists mysqltest_db1;
+drop table if exists test.t1;
+--enable_warnings
+create database mysqltest_db1;
+use mysqltest_db1;
+# For the sake of its side effect
+drop database mysqltest_db1;
+# Now we have no current database selected.
+create table test.t1 (id int);
+insert into test.t1 (id) values (1);
+delimiter //;
+create procedure test.sp_bug29050() begin select * from t1; end//
+delimiter ;//
+show warnings;
+call test.sp_bug29050();
+show warnings;
+# Restore the old current database
+use test;
+drop procedure sp_bug29050;
+drop table t1;
--echo End of 5.0 tests
diff --git a/mysql-test/t/trigger.test b/mysql-test/t/trigger.test
index 7158d02956e..0fa92f33de2 100644
--- a/mysql-test/t/trigger.test
+++ b/mysql-test/t/trigger.test
@@ -406,7 +406,7 @@ create table mysqltest.t1 (i int);
--error ER_TRG_IN_WRONG_SCHEMA
create trigger trg1 before insert on mysqltest.t1 for each row set @a:= 1;
use mysqltest;
---error ER_TRG_IN_WRONG_SCHEMA
+--error ER_NO_SUCH_TABLE
create trigger test.trg1 before insert on t1 for each row set @a:= 1;
drop database mysqltest;
use test;
@@ -1040,7 +1040,7 @@ drop table t1;
connection addconwithoutdb;
--error ER_NO_DB_ERROR
create trigger t1_bi before insert on test.t1 for each row set @a:=0;
---error ER_NO_DB_ERROR
+--error ER_NO_SUCH_TABLE
create trigger test.t1_bi before insert on t1 for each row set @a:=0;
--error ER_NO_DB_ERROR
drop trigger t1_bi;
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index cbfba3d4d80..aefa3d43b14 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -1974,6 +1974,43 @@ uint8 st_lex::get_effective_with_check(st_table_list *view)
}
+/**
+ This method should be called only during parsing.
+ It is aware of compound statements (stored routine bodies)
+ and will initialize the destination with the default
+ database of the stored routine, rather than the default
+ database of the connection it is parsed in.
+ E.g. if one has no current database selected, or current database
+ set to 'bar' and then issues:
+
+ CREATE PROCEDURE foo.p1() BEGIN SELECT * FROM t1 END//
+
+ t1 is meant to refer to foo.t1, not to bar.t1.
+
+ This method is needed to support this rule.
+
+ @return TRUE in case of error (parsing should be aborted, FALSE in
+ case of success
+*/
+
+bool
+st_lex::copy_db_to(char **p_db, uint *p_db_length) const
+{
+ if (sphead)
+ {
+ DBUG_ASSERT(sphead->m_db.str && sphead->m_db.length);
+ /*
+ It is safe to assign the string by-pointer, both sphead and
+ its statements reside in the same memory root.
+ */
+ *p_db= sphead->m_db.str;
+ if (p_db_length)
+ *p_db_length= sphead->m_db.length;
+ return FALSE;
+ }
+ return thd->copy_db_to(p_db, p_db_length);
+}
+
/*
initialize limit counters
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index f8405ef14ca..3f55b3baae1 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -1237,6 +1237,8 @@ typedef struct st_lex : public Query_tables_list
context_stack.pop();
}
+ bool copy_db_to(char **p_db, uint *p_db_length) const;
+
Name_resolution_context *current_context()
{
return context_stack.head();
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index b65ad705a36..124fcff9517 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -6397,7 +6397,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
ptr->db= table->db.str;
ptr->db_length= table->db.length;
}
- else if (thd->copy_db_to(&ptr->db, &ptr->db_length))
+ else if (lex->copy_db_to(&ptr->db, &ptr->db_length))
DBUG_RETURN(0);
ptr->alias= alias_str;
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 6c146f77ed6..949f3ed4161 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -1565,14 +1565,14 @@ sp_name:
}
| ident
{
- THD *thd= YYTHD;
+ LEX *lex= Lex;
LEX_STRING db;
if (check_routine_name($1))
{
my_error(ER_SP_WRONG_NAME, MYF(0), $1.str);
MYSQL_YYABORT;
}
- if (thd->copy_db_to(&db.str, &db.length))
+ if (lex->copy_db_to(&db.str, &db.length))
MYSQL_YYABORT;
$$= new sp_name(db, $1, false);
if ($$)
@@ -3624,10 +3624,9 @@ alter:
opt_create_database_options
{
LEX *lex=Lex;
- THD *thd= Lex->thd;
lex->sql_command=SQLCOM_ALTER_DB;
lex->name= $3;
- if (lex->name == NULL && thd->copy_db_to(&lex->name, NULL))
+ if (lex->name == NULL && lex->copy_db_to(&lex->name, NULL))
MYSQL_YYABORT;
}
| ALTER PROCEDURE sp_name
@@ -3795,10 +3794,9 @@ alter_list_item:
| RENAME opt_to table_ident
{
LEX *lex=Lex;
- THD *thd= lex->thd;
lex->select_lex.db=$3->db.str;
if (lex->select_lex.db == NULL &&
- thd->copy_db_to(&lex->select_lex.db, NULL))
+ lex->copy_db_to(&lex->select_lex.db, NULL))
{
MYSQL_YYABORT;
}
@@ -5148,7 +5146,7 @@ simple_expr:
{
THD *thd= lex->thd;
LEX_STRING db;
- if (thd->copy_db_to(&db.str, &db.length))
+ if (lex->copy_db_to(&db.str, &db.length))
MYSQL_YYABORT;
sp_name *name= new sp_name(db, $1, false);
if (name)
@@ -9025,8 +9023,7 @@ grant_ident:
'*'
{
LEX *lex= Lex;
- THD *thd= lex->thd;
- if (thd->copy_db_to(&lex->current_select->db, NULL))
+ if (lex->copy_db_to(&lex->current_select->db, NULL))
MYSQL_YYABORT;
if (lex->grant == GLOBAL_ACLS)
lex->grant = DB_ACLS & ~GRANT_ACL;