diff options
-rw-r--r-- | sql/sql_parse.cc | 60 | ||||
-rw-r--r-- | sql/sql_rename.cc | 44 | ||||
-rw-r--r-- | tests/client_test.c | 87 |
3 files changed, 162 insertions, 29 deletions
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 55e1f35f730..2b8720abebb 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1864,7 +1864,6 @@ mysql_execute_command(THD *thd) } #endif /* !HAVE_REPLICATION */ if (&lex->select_lex != lex->all_selects_list && - lex->sql_command != SQLCOM_CREATE_TABLE && lex->unit.create_total_list(thd, lex, &tables)) DBUG_VOID_RETURN; @@ -2166,12 +2165,16 @@ mysql_execute_command(THD *thd) { /* Skip first table, which is the table we are creating */ 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; - 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; - 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) ? CREATE_TMP_ACL : CREATE_ACL); @@ -2181,10 +2184,10 @@ mysql_execute_command(THD *thd) check_merge_table_access(thd, create_table->db, (TABLE_LIST *) lex->create_info.merge_list.first)) - goto error; /* purecov: inspected */ + goto create_eror; /* purecov: inspected */ if (grant_option && want_priv != CREATE_TMP_ACL && check_grant(thd, want_priv, create_table,0,0)) - goto error; + goto create_eror; #ifndef HAVE_READLINK lex->create_info.data_file_name=lex->create_info.index_file_name=0; #else @@ -2195,7 +2198,7 @@ mysql_execute_command(THD *thd) create_table->real_name)) { res=-1; - break; + goto unsent_create_error; } #endif /* @@ -2220,10 +2223,10 @@ mysql_execute_command(THD *thd) 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)) - goto error; // Error message is given + goto create_eror; // Error message is given select_lex->options|= SELECT_NO_UNLOCK; unit->offset_limit_cnt= select_lex->offset_limit; unit->select_limit_cnt= select_lex->select_limit+ @@ -2258,6 +2261,35 @@ mysql_execute_command(THD *thd) if (!res) 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; } case SQLCOM_CREATE_INDEX: @@ -2617,13 +2649,8 @@ mysql_execute_command(THD *thd) { ulong privilege= (lex->duplicates == DUP_REPLACE ? INSERT_ACL | DELETE_ACL : INSERT_ACL); - TABLE_LIST *save_next=tables->next; - tables->next=0; if (check_one_table_access(thd, privilege, tables, 0)) goto error; - tables->next=save_next; - if (check_table_access(thd, SELECT_ACL, save_next, 0)) - goto error; } /* Fix lock for first table */ @@ -3479,7 +3506,10 @@ static int check_one_table_access(THD *thd, ulong privilege, TABLE_LIST *subselects_tables= tables->next; tables->next= 0; if (grant_option && check_grant(thd, privilege, tables, 0, 0)) + { + tables->next= subselects_tables; return 1; + } // check rights on tables of subselect (if exists) if (subselects_tables) diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc index 7793e7236c0..d2b575c0838 100644 --- a/sql/sql_rename.cc +++ b/sql/sql_rename.cc @@ -24,6 +24,8 @@ static TABLE_LIST *rename_tables(THD *thd, TABLE_LIST *table_list, 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 second entry is the new name. @@ -56,17 +58,10 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list) if ((ren_table=rename_tables(thd,table_list,0))) { /* Rename didn't succeed; rename back the tables in reverse order */ - TABLE_LIST *prev=0,*table; - /* Reverse the table list */ + TABLE_LIST *table; - while (table_list) - { - TABLE_LIST *next=table_list->next; - table_list->next=prev; - prev=table_list; - table_list=next; - } - table_list=prev; + /* Reverse the table list */ + table_list= reverse_table_list(table_list); /* Find the last renamed table */ for (table=table_list ; @@ -75,6 +70,10 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list) table=table->next->next; // Skip error table /* Revert to old names */ rename_tables(thd, table, 1); + + /* Revert the table list (for prepared statements) */ + table_list= reverse_table_list(table_list); + error= 1; } @@ -101,6 +100,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 wrong. Note that the table_list may be empty! */ diff --git a/tests/client_test.c b/tests/client_test.c index 0d4d84b02c7..eaa9c6d7acd 100644 --- a/tests/client_test.c +++ b/tests/client_test.c @@ -8495,7 +8495,7 @@ static void test_bug3117() } -static void jest_join() +static void test_join() { MYSQL_STMT *stmt; int rc, i, j; @@ -8509,7 +8509,7 @@ static void jest_join() "SELECT * FROM t2 natural right join t1", "SELECT * FROM t2 right join t1 using(a)"}; - myheader("jest_join"); + myheader("test_join"); rc = mysql_query(mysql, "DROP TABLE IF EXISTS t1,t2"); myquery(rc); @@ -8526,6 +8526,7 @@ static void jest_join() rc= mysql_query(mysql, "insert into t2 values (1,1), (2, 2), (3,3), (4,4), (5,5);"); + myquery(rc); for (j= 0; j < 9; j++) { @@ -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 */ @@ -8850,9 +8928,10 @@ int main(int argc, char **argv) Item_field -> Item_ref */ test_union(); /* test union with prepared statements */ 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_create_drop(); /* some table manipulation BUG#2811 */ + test_rename(); /* rename test */ end_time= time((time_t *)0); total_time+= difftime(end_time, start_time); |