Commit 75e7ca47 authored by bell@sanja.is.com.ua's avatar bell@sanja.is.com.ua

reverting table list to be able to use it in next PS call (BUG#2811)

parent 3b0bf66e
...@@ -1864,7 +1864,6 @@ mysql_execute_command(THD *thd) ...@@ -1864,7 +1864,6 @@ mysql_execute_command(THD *thd)
} }
#endif /* !HAVE_REPLICATION */ #endif /* !HAVE_REPLICATION */
if (&lex->select_lex != lex->all_selects_list && if (&lex->select_lex != lex->all_selects_list &&
lex->sql_command != SQLCOM_CREATE_TABLE &&
lex->unit.create_total_list(thd, lex, &tables)) lex->unit.create_total_list(thd, lex, &tables))
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
...@@ -2166,12 +2165,16 @@ mysql_execute_command(THD *thd) ...@@ -2166,12 +2165,16 @@ mysql_execute_command(THD *thd)
{ {
/* Skip first table, which is the table we are creating */ /* Skip first table, which is the table we are creating */
TABLE_LIST *create_table= tables; TABLE_LIST *create_table= tables;
TABLE_LIST *create_table_local=
(TABLE_LIST*)lex->select_lex.table_list.first;
// exclude from global table list
tables= tables->next; tables= tables->next;
lex->select_lex.table_list.first= (byte*) (tables); // and from local list if it is not the same
if (&lex->select_lex != lex->all_selects_list)
lex->select_lex.table_list.first= (gptr)create_table_local->next;
else
lex->select_lex.table_list.first= (gptr)tables;
create_table->next= 0; create_table->next= 0;
if (&lex->select_lex != lex->all_selects_list &&
lex->unit.create_total_list(thd, lex, &tables))
DBUG_VOID_RETURN;
ulong want_priv= ((lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) ? ulong want_priv= ((lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) ?
CREATE_TMP_ACL : CREATE_ACL); CREATE_TMP_ACL : CREATE_ACL);
...@@ -2181,10 +2184,10 @@ mysql_execute_command(THD *thd) ...@@ -2181,10 +2184,10 @@ mysql_execute_command(THD *thd)
check_merge_table_access(thd, create_table->db, check_merge_table_access(thd, create_table->db,
(TABLE_LIST *) (TABLE_LIST *)
lex->create_info.merge_list.first)) lex->create_info.merge_list.first))
goto error; /* purecov: inspected */ goto create_eror; /* purecov: inspected */
if (grant_option && want_priv != CREATE_TMP_ACL && if (grant_option && want_priv != CREATE_TMP_ACL &&
check_grant(thd, want_priv, create_table,0,0)) check_grant(thd, want_priv, create_table,0,0))
goto error; goto create_eror;
#ifndef HAVE_READLINK #ifndef HAVE_READLINK
lex->create_info.data_file_name=lex->create_info.index_file_name=0; lex->create_info.data_file_name=lex->create_info.index_file_name=0;
#else #else
...@@ -2195,7 +2198,7 @@ mysql_execute_command(THD *thd) ...@@ -2195,7 +2198,7 @@ mysql_execute_command(THD *thd)
create_table->real_name)) create_table->real_name))
{ {
res=-1; res=-1;
break; goto unsent_create_error;
} }
#endif #endif
/* /*
...@@ -2220,10 +2223,10 @@ mysql_execute_command(THD *thd) ...@@ -2220,10 +2223,10 @@ mysql_execute_command(THD *thd)
create_table->real_name)) create_table->real_name))
{ {
net_printf(thd,ER_UPDATE_TABLE_USED, create_table->real_name); net_printf(thd,ER_UPDATE_TABLE_USED, create_table->real_name);
DBUG_VOID_RETURN; goto create_eror;
} }
if (tables && check_table_access(thd, SELECT_ACL, tables,0)) if (tables && check_table_access(thd, SELECT_ACL, tables,0))
goto error; // Error message is given goto create_eror; // Error message is given
select_lex->options|= SELECT_NO_UNLOCK; select_lex->options|= SELECT_NO_UNLOCK;
unit->offset_limit_cnt= select_lex->offset_limit; unit->offset_limit_cnt= select_lex->offset_limit;
unit->select_limit_cnt= select_lex->select_limit+ unit->select_limit_cnt= select_lex->select_limit+
...@@ -2258,6 +2261,35 @@ mysql_execute_command(THD *thd) ...@@ -2258,6 +2261,35 @@ mysql_execute_command(THD *thd)
if (!res) if (!res)
send_ok(thd); send_ok(thd);
} }
// put tables back for PS rexecuting
create_table->next= tables;
tables= create_table;
if (&lex->select_lex != lex->all_selects_list)
{
/*
we do not touch local table 'next' field => we need just
put the table in the list
*/
lex->select_lex.table_list.first= (gptr) create_table_local;
}
else
lex->select_lex.table_list.first= (gptr) tables;
break;
create_eror:
res= 1; //error reported
unsent_create_error:
// put tables back for PS rexecuting
create_table->next= tables;
tables= create_table;
if (&lex->select_lex != lex->all_selects_list)
{
/*
we do not touch local table 'next' field => we need just
put the table in the list
*/
lex->select_lex.table_list.first= (gptr) create_table_local;
}
break; break;
} }
case SQLCOM_CREATE_INDEX: case SQLCOM_CREATE_INDEX:
...@@ -2617,13 +2649,8 @@ mysql_execute_command(THD *thd) ...@@ -2617,13 +2649,8 @@ mysql_execute_command(THD *thd)
{ {
ulong privilege= (lex->duplicates == DUP_REPLACE ? ulong privilege= (lex->duplicates == DUP_REPLACE ?
INSERT_ACL | DELETE_ACL : INSERT_ACL); INSERT_ACL | DELETE_ACL : INSERT_ACL);
TABLE_LIST *save_next=tables->next;
tables->next=0;
if (check_one_table_access(thd, privilege, tables, 0)) if (check_one_table_access(thd, privilege, tables, 0))
goto error; goto error;
tables->next=save_next;
if (check_table_access(thd, SELECT_ACL, save_next, 0))
goto error;
} }
/* Fix lock for first table */ /* Fix lock for first table */
...@@ -3479,7 +3506,10 @@ static int check_one_table_access(THD *thd, ulong privilege, ...@@ -3479,7 +3506,10 @@ static int check_one_table_access(THD *thd, ulong privilege,
TABLE_LIST *subselects_tables= tables->next; TABLE_LIST *subselects_tables= tables->next;
tables->next= 0; tables->next= 0;
if (grant_option && check_grant(thd, privilege, tables, 0, 0)) if (grant_option && check_grant(thd, privilege, tables, 0, 0))
{
tables->next= subselects_tables;
return 1; return 1;
}
// check rights on tables of subselect (if exists) // check rights on tables of subselect (if exists)
if (subselects_tables) if (subselects_tables)
......
...@@ -24,6 +24,8 @@ ...@@ -24,6 +24,8 @@
static TABLE_LIST *rename_tables(THD *thd, TABLE_LIST *table_list, static TABLE_LIST *rename_tables(THD *thd, TABLE_LIST *table_list,
bool skip_error); bool skip_error);
static TABLE_LIST *reverse_table_list(TABLE_LIST *table_list);
/* /*
Every second entry in the table_list is the original name and every Every second entry in the table_list is the original name and every
second entry is the new name. second entry is the new name.
...@@ -56,17 +58,10 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list) ...@@ -56,17 +58,10 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list)
if ((ren_table=rename_tables(thd,table_list,0))) if ((ren_table=rename_tables(thd,table_list,0)))
{ {
/* Rename didn't succeed; rename back the tables in reverse order */ /* Rename didn't succeed; rename back the tables in reverse order */
TABLE_LIST *prev=0,*table; TABLE_LIST *table;
/* Reverse the table list */
while (table_list) /* Reverse the table list */
{ table_list= reverse_table_list(table_list);
TABLE_LIST *next=table_list->next;
table_list->next=prev;
prev=table_list;
table_list=next;
}
table_list=prev;
/* Find the last renamed table */ /* Find the last renamed table */
for (table=table_list ; for (table=table_list ;
...@@ -75,6 +70,10 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list) ...@@ -75,6 +70,10 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list)
table=table->next->next; // Skip error table table=table->next->next; // Skip error table
/* Revert to old names */ /* Revert to old names */
rename_tables(thd, table, 1); rename_tables(thd, table, 1);
/* Revert the table list (for prepared statements) */
table_list= reverse_table_list(table_list);
error= 1; error= 1;
} }
...@@ -100,6 +99,31 @@ err: ...@@ -100,6 +99,31 @@ err:
} }
/*
reverse table list
SYNOPSIS
reverse_table_list()
table_list pointer to table _list
RETURN
pointer to new (reversed) list
*/
static TABLE_LIST *reverse_table_list(TABLE_LIST *table_list)
{
TABLE_LIST *prev= 0;
while (table_list)
{
TABLE_LIST *next= table_list->next;
table_list->next= prev;
prev= table_list;
table_list= next;
}
return (prev);
}
/* /*
Rename all tables in list; Return pointer to wrong entry if something goes Rename all tables in list; Return pointer to wrong entry if something goes
wrong. Note that the table_list may be empty! wrong. Note that the table_list may be empty!
......
...@@ -8495,7 +8495,7 @@ static void test_bug3117() ...@@ -8495,7 +8495,7 @@ static void test_bug3117()
} }
static void jest_join() static void test_join()
{ {
MYSQL_STMT *stmt; MYSQL_STMT *stmt;
int rc, i, j; int rc, i, j;
...@@ -8509,7 +8509,7 @@ static void jest_join() ...@@ -8509,7 +8509,7 @@ static void jest_join()
"SELECT * FROM t2 natural right join t1", "SELECT * FROM t2 natural right join t1",
"SELECT * FROM t2 right join t1 using(a)"}; "SELECT * FROM t2 right join t1 using(a)"};
myheader("jest_join"); myheader("test_join");
rc = mysql_query(mysql, "DROP TABLE IF EXISTS t1,t2"); rc = mysql_query(mysql, "DROP TABLE IF EXISTS t1,t2");
myquery(rc); myquery(rc);
...@@ -8526,6 +8526,7 @@ static void jest_join() ...@@ -8526,6 +8526,7 @@ static void jest_join()
rc= mysql_query(mysql, rc= mysql_query(mysql,
"insert into t2 values (1,1), (2, 2), (3,3), (4,4), (5,5);"); "insert into t2 values (1,1), (2, 2), (3,3), (4,4), (5,5);");
myquery(rc);
for (j= 0; j < 9; j++) for (j= 0; j < 9; j++)
{ {
...@@ -8591,6 +8592,83 @@ static void test_selecttmp() ...@@ -8591,6 +8592,83 @@ static void test_selecttmp()
} }
static void test_create_drop()
{
MYSQL_STMT *stmt_create, *stmt_drop;
char *query;
int rc, i;
myheader("test_table_manipulation");
rc = mysql_query(mysql, "DROP TABLE IF EXISTS t1,t2");
myquery(rc);
query= (char*)"create table t1 (a int)";
stmt_create= mysql_prepare(mysql, query, strlen(query));
mystmt_init(stmt_create);
query= (char*)"drop table t1";
stmt_drop= mysql_prepare(mysql, query, strlen(query));
mystmt_init(stmt_drop);
for (i= 0; i < 3; i++)
{
rc= mysql_execute(stmt_create);
mystmt(stmt_create, rc);
fprintf(stdout, "created %i\n", i);
rc= mysql_execute(stmt_drop);
mystmt(stmt_drop, rc);
fprintf(stdout, "droped %i\n", i);
}
mysql_stmt_close(stmt_create);
mysql_stmt_close(stmt_drop);
}
static void test_rename()
{
MYSQL_STMT *stmt;
const char *query= "rename table t1 to t2, t3 to t4";
int rc;
myheader("test_table_manipulation");
rc = mysql_query(mysql, "DROP TABLE IF EXISTS t1,t2,t3,t4");
myquery(rc);
stmt= mysql_prepare(mysql, query, strlen(query));
mystmt_init(stmt);
rc= mysql_query(mysql,"create table t1 (a int)");
myquery(rc);
rc= mysql_execute(stmt);
mystmt_r(stmt, rc);
fprintf(stdout, "rename without t3\n");
rc= mysql_query(mysql,"create table t3 (a int)");
myquery(rc);
rc= mysql_execute(stmt);
mystmt(stmt, rc);
fprintf(stdout, "rename with t3\n");
rc= mysql_execute(stmt);
mystmt_r(stmt, rc);
fprintf(stdout, "rename renamed\n");
rc= mysql_query(mysql,"rename table t2 to t1, t4 to t3");
myquery(rc);
rc= mysql_execute(stmt);
mystmt(stmt, rc);
fprintf(stdout, "rename reverted\n");
mysql_stmt_close(stmt);
rc= mysql_query(mysql, "DROP TABLE t2,t4");
myquery(rc);
}
/* /*
Read and parse arguments and MySQL options from my.cnf Read and parse arguments and MySQL options from my.cnf
*/ */
...@@ -8850,9 +8928,10 @@ int main(int argc, char **argv) ...@@ -8850,9 +8928,10 @@ int main(int argc, char **argv)
Item_field -> Item_ref */ Item_field -> Item_ref */
test_union(); /* test union with prepared statements */ test_union(); /* test union with prepared statements */
test_bug3117(); /* BUG#3117: LAST_INSERT_ID() */ test_bug3117(); /* BUG#3117: LAST_INSERT_ID() */
jest_join(); /* different kinds of join, BUG#2794 */ test_join(); /* different kinds of join, BUG#2794 */
test_selecttmp(); /* temporary table used in select execution */ test_selecttmp(); /* temporary table used in select execution */
test_create_drop(); /* some table manipulation BUG#2811 */
test_rename(); /* rename test */
end_time= time((time_t *)0); end_time= time((time_t *)0);
total_time+= difftime(end_time, start_time); total_time+= difftime(end_time, start_time);
......
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