diff --git a/mysql-test/README b/mysql-test/README index 65e6186613a..10d64784ed4 100644 --- a/mysql-test/README +++ b/mysql-test/README @@ -2,8 +2,17 @@ This directory contains a test suite for mysql daemon. To run the currently existing test cases, simply execute ./mysql-test-run in this directory. It will fire up the newly built mysqld and test it. -If you want to run the test with a running MySQL server use the --external -option to mysql-test-run. +If you want to run a test with a running MySQL server use the --extern +option to mysql-test-run. Please note that in this mode the test suite +expects user to specify test names to run. Otherwise it falls back to the +normal "non-extern" behaviour. The reason is that some tests +could not run with external server. Here is the sample command +to test "alias" and "analyze" tests on external server: + +mysql-test-run --extern alias analyze + +To match your setup you might also need to provide --socket, --user and +other relevant options. Note that you do not have to have to do make install, and you could actually have a co-existing MySQL installation - the tests will not diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 0ecc7bc6c52..4f673fe567d 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -772,7 +772,8 @@ sub executable_setup () { { if ( $glob_win32 ) { - $path_client_bindir= mtr_path_exists("$glob_basedir/client_release"); + $path_client_bindir= mtr_path_exists("$glob_basedir/client_release", + "$glob_basedir/bin"); $exe_mysqld= mtr_exe_exists ("$path_client_bindir/mysqld-nt"); $path_language= mtr_path_exists("$glob_basedir/share/english/"); $path_charsetsdir= mtr_path_exists("$glob_basedir/share/charsets"); @@ -794,7 +795,7 @@ sub executable_setup () { } else { - $exe_mysqltest= mtr_exe_exists("$glob_basedir/client/mysqltest"); + $exe_mysqltest= mtr_exe_exists("$path_client_bindir/mysqltest"); $exe_mysql_client_test= mtr_exe_exists("$glob_basedir/tests/mysql_client_test"); } @@ -2013,6 +2014,14 @@ sub run_mysqltest ($$) { "--port=$master->[0]->{'path_myport'} " . "--socket=$master->[0]->{'path_mysock'}"; + if ( $glob_use_embedded_server ) + { + $cmdline_mysql_client_test.= + " -A --language=$path_language" . + " -A --datadir=$slave->[0]->{'path_myddir'}" . + " -A --character-sets-dir=$path_charsetsdir"; + } + my $cmdline_mysql_fix_system_tables= "$exe_mysql_fix_system_tables --no-defaults --host=localhost --user=root --password= " . "--basedir=$glob_basedir --bindir=$path_client_bindir --verbose " . @@ -2129,8 +2138,7 @@ sub run_mysqltest ($$) { # ############################################################################## -sub usage ($) -{ +sub usage ($) { print STDERR < MAX_RESERVED_NAME_LENGTH) + if (path == end || (uint) (end - path) > MAX_RESERVED_NAME_LENGTH) DBUG_RETURN(0); /* Simplify inner loop */ for (reserved_name= reserved_names; *reserved_name; reserved_name++) { const char *name= path; - while (name != end) + const char *current_reserved_name= *reserved_name; + + while (name != end && *current_reserved_name) { - if (my_toupper(&my_charset_latin1, *path) != - my_toupper(&my_charset_latin1, *name)) + if (*current_reserved_name != my_toupper(&my_charset_latin1, *name)) break; - if (name++ == end) + current_reserved_name++; + if (++name == end) DBUG_RETURN(1); /* Found wrong path */ } } diff --git a/ndb/src/common/util/version.c b/ndb/src/common/util/version.c index ed2e2565eea..7221dc48fa4 100644 --- a/ndb/src/common/util/version.c +++ b/ndb/src/common/util/version.c @@ -90,7 +90,7 @@ void ndbSetOwnVersion() {} #ifndef TEST_VERSION struct NdbUpGradeCompatible ndbCompatibleTable_full[] = { - { MAKE_VERSION(4,1,12), MAKE_VERSION(4,1,10), UG_Range }, + { MAKE_VERSION(4,1,NDB_VERSION_BUILD), MAKE_VERSION(4,1,10), UG_Range }, { MAKE_VERSION(4,1,10), MAKE_VERSION(4,1,9), UG_Exact }, { MAKE_VERSION(4,1,9), MAKE_VERSION(4,1,8), UG_Exact }, { MAKE_VERSION(3,5,2), MAKE_VERSION(3,5,1), UG_Exact }, diff --git a/sql/item.cc b/sql/item.cc index c96794ff482..9c5bf499d11 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -65,6 +65,7 @@ Item::Item(): place == IN_HAVING) thd->lex->current_select->select_n_having_items++; } + item_flags= 0; } /* @@ -83,7 +84,8 @@ Item::Item(THD *thd, Item *item): unsigned_flag(item->unsigned_flag), with_sum_func(item->with_sum_func), fixed(item->fixed), - collation(item->collation) + collation(item->collation), + item_flags(item->item_flags) { next= thd->free_list; // Put in free list thd->free_list= this; diff --git a/sql/item.h b/sql/item.h index 8de2adeb730..82ab5a66cfb 100644 --- a/sql/item.h +++ b/sql/item.h @@ -107,6 +107,11 @@ public: typedef bool (Item::*Item_processor)(byte *arg); +/* + See comments for sql_yacc.yy: insert_update_elem rule + */ +#define MY_ITEM_PREFER_1ST_TABLE 1 + class Item { Item(const Item &); /* Prevent use of these */ void operator=(Item &); @@ -142,6 +147,7 @@ public: my_bool with_sum_func; my_bool fixed; /* If item fixed with fix_fields */ DTCollation collation; + uint8 item_flags; /* Flags on how item should be processed */ // alloc & destruct is done as start of select using sql_alloc Item(); @@ -327,6 +333,11 @@ public: cleanup(); delete this; } + virtual bool set_flags_processor(byte *args) + { + this->item_flags|= *((uint8*)args); + return false; + } }; diff --git a/sql/item_buff.cc b/sql/item_buff.cc index f5e77862e1d..8298ce2cfb7 100644 --- a/sql/item_buff.cc +++ b/sql/item_buff.cc @@ -51,8 +51,8 @@ bool Item_str_buff::cmp(void) String *res; bool tmp; - res=item->val_str(&tmp_value); - res->length(min(res->length(), value.alloced_length())); + if ((res=item->val_str(&tmp_value))) + res->length(min(res->length(), value.alloced_length())); if (null_value != item->null_value) { if ((null_value= item->null_value)) diff --git a/sql/sql_base.cc b/sql/sql_base.cc index b4c212afb3f..e5d5e95cb5a 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2096,7 +2096,8 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, return (Field*) 0; } bool allow_rowid= tables && !tables->next; // Only one table - for (; tables ; tables=tables->next) + uint table_idx= 0; + for (; tables ; tables=tables->next, table_idx++) { if (!tables->table) { @@ -2124,7 +2125,9 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, name,thd->where); return (Field*) 0; } - found=field; + found= field; + if (table_idx == 0 && item->item_flags & MY_ITEM_PREFER_1ST_TABLE) + break; } } if (found) diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index b90de7e93cc..f09d3214c74 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1636,11 +1636,22 @@ bool select_insert::send_data(List &values) store_values(values); error=thd->net.report_error || write_record(table,&info); thd->count_cuted_fields= CHECK_FIELD_IGNORE; - if (!error && table->next_number_field) // Clear for next record + + if (!error) { - table->next_number_field->reset(); - if (! last_insert_id && thd->insert_id_used) - last_insert_id=thd->insert_id(); + /* + Restore fields of the record since it is possible that they were + changed by ON DUPLICATE KEY UPDATE clause. + */ + if (info.handle_duplicates == DUP_UPDATE) + restore_record(table, default_values); + + if (table->next_number_field) // Clear for next record + { + table->next_number_field->reset(); + if (! last_insert_id && thd->insert_id_used) + last_insert_id=thd->insert_id(); + } } DBUG_RETURN(error); } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index c107203b548..233104c9a90 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1943,6 +1943,16 @@ mysql_execute_command(THD *thd) if (tables || &lex->select_lex != lex->all_selects_list) mysql_reset_errors(thd); + /* + When subselects or time_zone info is used in a query + we create a new TABLE_LIST containing all referenced tables + and set local variable 'tables' to point to this list. + */ + if ((&lex->select_lex != lex->all_selects_list || + lex->time_zone_tables_used) && + lex->unit.create_total_list(thd, lex, &tables)) + DBUG_VOID_RETURN; + #ifdef HAVE_REPLICATION if (thd->slave_thread) { @@ -1993,14 +2003,6 @@ mysql_execute_command(THD *thd) } #endif /* !HAVE_REPLICATION */ - /* When subselects or time_zone info is used in a query - * we create a new TABLE_LIST containing all referenced tables - * and set local variable 'tables' to point to this list. */ - if ((&lex->select_lex != lex->all_selects_list || - lex->time_zone_tables_used) && - lex->unit.create_total_list(thd, lex, &tables)) - DBUG_VOID_RETURN; - /* When option readonly is set deny operations which change tables. Except for the replication thread and the 'super' users. @@ -2854,17 +2856,14 @@ unsent_create_error: if ((res= open_and_lock_tables(thd, tables))) break; - TABLE *table= tables->table; /* Skip first table, which is the table we are inserting in */ select_lex->table_list.first= (byte*) first_local_table->next; - tables= (TABLE_LIST *) select_lex->table_list.first; - first_local_table->next= 0; if (!(res= mysql_prepare_insert(thd, tables, first_local_table, - table, lex->field_list, 0, + tables->table, lex->field_list, 0, lex->update_list, lex->value_list, lex->duplicates)) && - (result= new select_insert(table, &lex->field_list, + (result= new select_insert(tables->table, &lex->field_list, &lex->update_list, &lex->value_list, lex->duplicates, lex->ignore))) { @@ -2877,7 +2876,7 @@ unsent_create_error: /* revert changes for SP */ lex->select_lex.resolve_mode= SELECT_LEX::INSERT_MODE; delete result; - table->insert_values= 0; + tables->table->insert_values= 0; if (thd->net.report_error) res= -1; } diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index bc21649fe54..460234de156 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -4239,9 +4239,24 @@ insert_update_elem: simple_ident equal expr_or_default { LEX *lex= Lex; + uint8 tmp= MY_ITEM_PREFER_1ST_TABLE; if (lex->update_list.push_back($1) || lex->value_list.push_back($3)) YYABORT; + /* + INSERT INTO a1(a) SELECT b1.a FROM b1 ON DUPLICATE KEY + UPDATE a= a + b1.b + + Set MY_ITEM_PREFER_1ST_TABLE flag to $1 and $3 items + to prevent find_field_in_tables() doing further item searching + if it finds item occurence in first table in insert_table_list. + This allows to avoid ambiguity in resolving 'a' field in + example above. + */ + $1->walk(&Item::set_flags_processor, + (byte *) &tmp); + $3->walk(&Item::set_flags_processor, + (byte *) &tmp); }; opt_low_priority: