Skip to content

Commit 7d0d934

Browse files
committed
MDEV-16473 WITH statement throws 'no database selected' error
Before this patch if no default database was set the server threw an error for any table name reference that was not fully qualified by database name. In particular it happened for table names referenced CTE tables. This was incorrect. The error message was thrown at the parser stage when the names referencing different tables were not resolved yet. Now if no default database is set and a with clause is used in the processed statement any table reference is just supplied with a dummy database name "*none*" at the parser stage. Later after a call of check_dependencies_in_with_clauses() when the names for CTE tables can be resolved error messages are thrown only for those names that refer to non-CTE tables. This is done in open_and_process_table().
1 parent 31e52b1 commit 7d0d934

File tree

6 files changed

+94
-5
lines changed

6 files changed

+94
-5
lines changed

mysql-test/r/cte_nonrecursive.result

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1478,3 +1478,37 @@ select 2 as f;
14781478
f
14791479
2
14801480
drop table t1;
1481+
#
1482+
# MDEV-16473: query with CTE when no database is set
1483+
#
1484+
create database db_mdev_16473;
1485+
use db_mdev_16473;
1486+
drop database db_mdev_16473;
1487+
# Now no default database is set
1488+
select database();
1489+
database()
1490+
NULL
1491+
with cte as (select 1 as a) select * from cte;
1492+
a
1493+
1
1494+
create database db_mdev_16473;
1495+
create table db_mdev_16473.t1 (a int);
1496+
insert into db_mdev_16473.t1 values (2), (7), (3), (1);
1497+
with cte as (select * from db_mdev_16473.t1) select * from cte;
1498+
a
1499+
2
1500+
7
1501+
3
1502+
1
1503+
with cte as (select * from db_mdev_16473.t1)
1504+
select * from cte, t1 as t where cte.a=t.a;
1505+
ERROR 3D000: No database selected
1506+
with cte as (select * from db_mdev_16473.t1)
1507+
select * from cte, db_mdev_16473.t1 as t where cte.a=t.a;
1508+
a a
1509+
2 2
1510+
7 7
1511+
3 3
1512+
1 1
1513+
drop database db_mdev_16473;
1514+
use test;

mysql-test/t/cte_nonrecursive.test

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1029,4 +1029,31 @@ with cte as
10291029
select 2 as f;
10301030

10311031
drop table t1;
1032-
1032+
1033+
--echo #
1034+
--echo # MDEV-16473: query with CTE when no database is set
1035+
--echo #
1036+
1037+
create database db_mdev_16473;
1038+
use db_mdev_16473;
1039+
drop database db_mdev_16473;
1040+
1041+
--echo # Now no default database is set
1042+
select database();
1043+
1044+
with cte as (select 1 as a) select * from cte;
1045+
1046+
create database db_mdev_16473;
1047+
create table db_mdev_16473.t1 (a int);
1048+
insert into db_mdev_16473.t1 values (2), (7), (3), (1);
1049+
with cte as (select * from db_mdev_16473.t1) select * from cte;
1050+
1051+
--error ER_NO_DB_ERROR
1052+
with cte as (select * from db_mdev_16473.t1)
1053+
select * from cte, t1 as t where cte.a=t.a;
1054+
with cte as (select * from db_mdev_16473.t1)
1055+
select * from cte, db_mdev_16473.t1 as t where cte.a=t.a;
1056+
1057+
drop database db_mdev_16473;
1058+
1059+
use test;

sql/sql_base.cc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3330,6 +3330,14 @@ open_and_process_table(THD *thd, LEX *lex, TABLE_LIST *tables,
33303330
/*
33313331
Not a placeholder: must be a base/temporary table or a view. Let us open it.
33323332
*/
3333+
3334+
if (tables->db == no_db)
3335+
{
3336+
my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
3337+
error= TRUE;
3338+
goto end;
3339+
}
3340+
33333341
if (tables->table)
33343342
{
33353343
/*

sql/sql_class.h

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3946,11 +3946,28 @@ class THD :public Statement,
39463946
{
39473947
if (db == NULL)
39483948
{
3949-
my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
3950-
return TRUE;
3949+
/*
3950+
No default database is set. In this case if it's guaranteed that
3951+
no CTE can be used in the statement then we can throw an error right
3952+
now at the parser stage. Otherwise the decision about throwing such
3953+
a message must be postponed until a post-parser stage when we are able
3954+
to resolve all CTE names as we don't need this message to be thrown
3955+
for any CTE references.
3956+
*/
3957+
if (!lex->with_clauses_list)
3958+
{
3959+
my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
3960+
return TRUE;
3961+
}
3962+
/* This will allow to throw an error later for non-CTE references */
3963+
*p_db= (char *) no_db;
3964+
*p_db_length= strlen(no_db);
3965+
}
3966+
else
3967+
{
3968+
*p_db= strmake(db, db_length);
3969+
*p_db_length= db_length;
39513970
}
3952-
*p_db= strmake(db, db_length);
3953-
*p_db_length= db_length;
39543971
return FALSE;
39553972
}
39563973
thd_scheduler event_scheduler;

sql/sql_lex.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,8 @@ struct LEX_TYPE
156156
extern const LEX_STRING null_lex_str;
157157
extern const LEX_STRING empty_lex_str;
158158

159+
extern const char *no_db;
160+
159161
enum enum_sp_suid_behaviour
160162
{
161163
SP_IS_DEFAULT_SUID= 0,

sql/sql_parse.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ static bool execute_show_status(THD *, TABLE_LIST *);
139139
static bool check_rename_table(THD *, TABLE_LIST *, TABLE_LIST *);
140140

141141
const char *any_db="*any*"; // Special symbol for check_access
142+
const char *no_db="*none*"; // Used when no default db is set
142143

143144
const LEX_STRING command_name[257]={
144145
{ C_STRING_WITH_LEN("Sleep") }, //0

0 commit comments

Comments
 (0)