From 231b0ff8dd13dc39a1ab94ed7c24b4a2d40e9c1c Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 17 Jun 2003 16:20:07 +0300 Subject: [PATCH] Two Sprint tasks and two behaviour changes. sql/sql_acl.cc: Fix for a grant bug. If there is a table privilege, for which no column privileges are defined , and the same privilege is granted for a column, new code prevents that table privilege is reduced to a column privilege. To accomplish that, now a REVOKE command has to be used first. sql/sql_parse.cc: SCRUM TASK No 1. Adding support for INSERT .. SELECT with a table in the join that is to be inserted into. test case pending. sql/sql_union.cc: Changing behaviour for SQL_OPTION_FOUND_ROWS in unins. sql/sql_yacc.yy: SCRUM TASK no 2. Making CREATE and INSERT to work with any UNION> --- sql/sql_acl.cc | 13 ++++++++---- sql/sql_parse.cc | 17 +++++++++------- sql/sql_union.cc | 12 +++++------ sql/sql_yacc.yy | 52 ++++++++++++++++++++++++++++++++++++++---------- 4 files changed, 66 insertions(+), 28 deletions(-) diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 12ea3a94464..e2946022ddf 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -2038,7 +2038,7 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, check->column.c_ptr(), table_list->alias); DBUG_RETURN(-1); } - column_priv |= check->rights | (rights & COL_ACLS); + column_priv |= check->rights & COL_ACLS; } close_thread_tables(thd); } @@ -2173,7 +2173,12 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, } else { - column_priv|= grant_table->cols; + /* + This code makes sure that if there is X privilege on the entire table and + X can be also a column privilege, that granting column privilege does not + revoke a table privilege. + */ + column_priv&= ~(grant_table->privs & ~grant_table->cols); } @@ -2186,13 +2191,13 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, { // Crashend table ?? result= -1; /* purecov: deadcode */ } - else if (tables[2].table) + else if (tables[2].table && (column_priv | revoke_grant)) { if ((replace_column_table(grant_table,tables[2].table, *Str, columns, table_list->db, table_list->real_name, - rights, revoke_grant))) + (revoke_grant) ? rights : column_priv, revoke_grant))) { result= -1; } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 2f9a7db5ef4..392b4ae4235 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1959,11 +1959,6 @@ mysql_execute_command(void) if (thd->select_limit < select_lex->select_limit) thd->select_limit= HA_POS_ERROR; // No limit - if (check_dup(tables->db, tables->real_name, tables->next)) - { - net_printf(&thd->net,ER_INSERT_TABLE_USED,tables->real_name); - DBUG_VOID_RETURN; - } { /* TODO: Delete the following loop when locks is set by sql_yacc */ TABLE_LIST *table; @@ -3361,8 +3356,16 @@ TABLE_LIST *add_table_to_list(Table_ident *table, LEX_STRING *alias, { if (!strcmp(alias_str,tables->alias) && !strcmp(ptr->db, tables->db)) { - net_printf(&thd->net,ER_NONUNIQ_TABLE,alias_str); /* purecov: tested */ - DBUG_RETURN(0); /* purecov: tested */ + if ((thd->lex.sql_command & (SQLCOM_INSERT_SELECT | SQLCOM_REPLACE_SELECT)) + && (tables->lock_type & (TL_WRITE_CONCURRENT_INSERT | + TL_WRITE_LOW_PRIORITY | TL_WRITE_DELAYED | + TL_WRITE))) + thd->lex.select->options |= OPTION_BUFFER_RESULT; + else + { + net_printf(&thd->net,ER_NONUNIQ_TABLE,alias_str); /* purecov: tested */ + DBUG_RETURN(0); /* purecov: tested */ + } } } } diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 55b5d57d07d..407bf64d628 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -63,10 +63,7 @@ int mysql_union(THD *thd, LEX *lex,select_result *result) */ lex_sl= sl; order= (ORDER *) lex_sl->order_list.first; - found_rows_for_union = (lex->select_lex.options & OPTION_FOUND_ROWS && - !describe && sl->select_limit); - if (found_rows_for_union) - lex->select_lex.options ^= OPTION_FOUND_ROWS; + found_rows_for_union = lex->select_lex.options & OPTION_FOUND_ROWS && sl->select_limit; // This is done to eliminate unnecessary slowing down of the first query if (!order || !describe) last_sl->next=0; // Remove this extra element @@ -144,7 +141,7 @@ int mysql_union(THD *thd, LEX *lex,select_result *result) thd->select_limit=sl->select_limit+sl->offset_limit; if (thd->select_limit < sl->select_limit) thd->select_limit= HA_POS_ERROR; // no limit - if (thd->select_limit == HA_POS_ERROR) + if (thd->select_limit == HA_POS_ERROR || sl->braces) sl->options&= ~OPTION_FOUND_ROWS; res=mysql_select(thd, (describe && sl->linkage==NOT_A_SELECT) ? @@ -203,9 +200,12 @@ int mysql_union(THD *thd, LEX *lex,select_result *result) { thd->offset_limit= 0; thd->select_limit= thd->variables.select_limit; + if (found_rows_for_union && !describe) + thd->options|= OPTION_FOUND_ROWS; } if (describe) thd->select_limit= HA_POS_ERROR; // no limit + res=mysql_select(thd,&result_table_list, item_list, NULL, (describe) ? 0 : order, (ORDER*) NULL, NULL, (ORDER*) NULL, @@ -264,7 +264,7 @@ bool select_union::send_data(List &values) if ((write_record(table,&info))) { if (create_myisam_from_heap(thd, table, tmp_table_param, info.last_errno, - 0)) + 1)) return 1; } return 0; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index c79750c8014..c011c058dc8 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -595,7 +595,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); table_to_table_list table_to_table opt_table_list opt_as handler_rkey_function handler_read_or_scan single_multi table_wild_list table_wild_one opt_wild opt_union union_list - precision union_option opt_and + precision union_option END_OF_INPUT %type @@ -787,17 +787,31 @@ create: create2: '(' field_list ')' opt_create_table_options create3 {} - | opt_create_table_options create3 {}; + | opt_create_table_options create3 {} + | select_for_create {} + ; create3: /* empty */ {} - | opt_duplicate opt_as SELECT_SYM + | opt_duplicate opt_as select_for_create {} + ; + +select_for_create: + SELECT_SYM { LEX *lex=Lex; lex->lock_option= (using_update_log) ? TL_READ_NO_INSERT : TL_READ; mysql_init_select(lex); } - select_options select_item_list opt_select_from opt_union {}; + select_options select_item_list opt_select_from { Select->braces= 0;} opt_union + |'(' SELECT_SYM + { + LEX *lex=Lex; + lex->lock_option= (using_update_log) ? TL_READ_NO_INSERT : TL_READ; + mysql_init_select(lex); + } + select_options select_item_list opt_select_from ')' { Select->braces= 1;} union_opt + ; opt_as: /* empty */ {} @@ -2600,7 +2614,9 @@ insert_field_spec: lex->many_values.push_back(lex->insert_list)) YYABORT; } - ident_eq_list; + ident_eq_list + | select_for_insert {} + ; opt_field_spec: /* empty */ { } @@ -2609,20 +2625,34 @@ opt_field_spec: fields: fields ',' insert_ident { Lex->field_list.push_back($3); } - | insert_ident { Lex->field_list.push_back($1); }; + | insert_ident { Lex->field_list.push_back($1); } + ; insert_values: VALUES values_list {} - | SELECT_SYM - { + | select_for_insert {} + ; + +select_for_insert: + SELECT_SYM + { LEX *lex=Lex; lex->sql_command = (lex->sql_command == SQLCOM_INSERT ? SQLCOM_INSERT_SELECT : SQLCOM_REPLACE_SELECT); lex->lock_option= (using_update_log) ? TL_READ_NO_INSERT : TL_READ; mysql_init_select(lex); - } - select_options select_item_list select_from select_lock_type - opt_union {}; + } + select_options select_item_list opt_select_from select_lock_type { Select->braces= 0;} opt_union + |'(' SELECT_SYM + { + LEX *lex=Lex; + lex->sql_command = (lex->sql_command == SQLCOM_INSERT ? + SQLCOM_INSERT_SELECT : SQLCOM_REPLACE_SELECT); + lex->lock_option= (using_update_log) ? TL_READ_NO_INSERT : TL_READ; + mysql_init_select(lex); + } + select_options select_item_list opt_select_from select_lock_type ')' { Select->braces= 1;} union_opt + ; values_list: values_list ',' no_braces