From f6834a5de08024c795a0506bbe906d4e6756c131 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 2 Sep 2004 16:20:30 +0500 Subject: [PATCH 1/7] A fix (bug #5056: defaults-extra-file throws no error when file is inaccessible). --- mysys/default.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/mysys/default.c b/mysys/default.c index 81290322223..e8195893ad8 100644 --- a/mysys/default.c +++ b/mysys/default.c @@ -164,8 +164,11 @@ int load_defaults(const char *conf_file, const char **groups, if (forced_default_file) { if ((error= search_default_file(&args, &alloc, "", - forced_default_file, "", &group)) < 0) + forced_default_file, "", &group))) + { + fprintf(stderr, "Error reading '%s' file.\n", forced_default_file); goto err; + } } else if (dirname_length(conf_file)) { @@ -199,8 +202,11 @@ int load_defaults(const char *conf_file, const char **groups, else if (defaults_extra_file) { if (search_default_file(&args, &alloc, NullS, defaults_extra_file, - default_ext, &group) < 0) + default_ext, &group)) + { + fprintf(stderr, "Error reading '%s' file.\n", defaults_extra_file); goto err; /* Fatal error */ + } } } } From 70fe41d2ec0fccdd54f643d832b67274a8f76f16 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 21 Oct 2004 17:02:24 +0500 Subject: [PATCH 2/7] A fix (bug #4802 prompt in mysql client shows wrong database after dropping default db). client/mysql.cc: A fix (bug #4802 prompt in mysql client shows wrong database after dropping default db). Introduced new get_current_db() function which is called from the com_use() and the com_go() if we get SERVER_STATUS_DB_DROPPED. include/mysql_com.h: A fix (bug #4802 prompt in mysql client shows wrong database after dropping default db). SERVER_STATUS_DB_DROPPED flag added. Note: it is set to 256 to don't conflict with 5.0 ver. sql/sql_db.cc: A fix (bug #4802 prompt in mysql client shows wrong database after dropping default db). SERVER_STATUS_DB_DROPPED flag is set/unset. --- client/mysql.cc | 38 ++++++++++++++++++++------------------ include/mysql_com.h | 1 + sql/sql_db.cc | 2 ++ 3 files changed, 23 insertions(+), 18 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index 05d5d1355ad..18dc4dd76cb 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -1574,6 +1574,22 @@ static int reconnect(void) return 0; } +static void get_current_db() +{ + MYSQL_RES *res; + + my_free(current_db, MYF(MY_ALLOW_ZERO_PTR)); + current_db= NULL; + /* In case of error below current_db will be NULL */ + if (!mysql_query(&mysql, "SELECT DATABASE()") && + (res= mysql_use_result(&mysql))) + { + MYSQL_ROW row= mysql_fetch_row(res); + if (row[0]) + current_db= my_strdup(row[0], MYF(MY_WME)); + mysql_free_result(res); + } +} /*************************************************************************** The different commands @@ -1899,6 +1915,9 @@ com_go(String *buffer,char *line __attribute__((unused))) if (err >= 1) error= put_error(&mysql); + if (!status.batch && (mysql.server_status & SERVER_STATUS_DB_DROPPED)) + get_current_db(); + return error; /* New command follows */ } @@ -2614,24 +2633,7 @@ com_use(String *buffer __attribute__((unused)), char *line) under our feet, for example if DROP DATABASE or RENAME DATABASE (latter one not yet available by the time the comment was written) */ - /* Let's reset current_db, assume it's gone */ - my_free(current_db, MYF(MY_ALLOW_ZERO_PTR)); - current_db= 0; - /* - We don't care about in case of an error below because current_db - was just set to 0. - */ - if (!mysql_query(&mysql, "SELECT DATABASE()") && - (res= mysql_use_result(&mysql))) - { - row= mysql_fetch_row(res); - if (row[0]) - { - current_db= my_strdup(row[0], MYF(MY_WME)); - } - (void) mysql_fetch_row(res); // Read eof - mysql_free_result(res); - } + get_current_db(); if (!current_db || cmp_database(charset_info, current_db,tmp)) { diff --git a/include/mysql_com.h b/include/mysql_com.h index 449cd0ba396..6fc1d106197 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -127,6 +127,7 @@ enum enum_server_command #define SERVER_MORE_RESULTS_EXISTS 8 /* Multi query - next query exists */ #define SERVER_QUERY_NO_GOOD_INDEX_USED 16 #define SERVER_QUERY_NO_INDEX_USED 32 +#define SERVER_STATUS_DB_DROPPED 256 /* A database was dropped */ #define MYSQL_ERRMSG_SIZE 512 #define NET_READ_TIMEOUT 30 /* Timeout on read */ diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 426f7d36633..e5b426ef508 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -634,7 +634,9 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) thd->clear_error(); mysql_bin_log.write(&qinfo); } + thd->server_status|= SERVER_STATUS_DB_DROPPED; send_ok(thd, (ulong) deleted); + thd->server_status&= !SERVER_STATUS_DB_DROPPED; } exit: From 935585a3369c7cf6f47edc71399c0c146178ea48 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 2 Feb 2005 15:52:19 +0400 Subject: [PATCH 3/7] After review fixes client/mysql.cc: check for "error" added sql/sql_db.cc: typo fixed --- client/mysql.cc | 3 ++- sql/sql_db.cc | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index a799027542b..d48e937023b 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -1921,7 +1921,8 @@ com_go(String *buffer,char *line __attribute__((unused))) if (err >= 1) error= put_error(&mysql); - if (!status.batch && (mysql.server_status & SERVER_STATUS_DB_DROPPED)) + if (!error && !status.batch && + (mysql.server_status & SERVER_STATUS_DB_DROPPED)) get_current_db(); return error; /* New command follows */ diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 731ca1d781e..c918480812c 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -670,7 +670,7 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) } thd->server_status|= SERVER_STATUS_DB_DROPPED; send_ok(thd, (ulong) deleted); - thd->server_status&= !SERVER_STATUS_DB_DROPPED; + thd->server_status&= ~SERVER_STATUS_DB_DROPPED; } exit: From d9f6581f259d859c3b87cd1b93481b10a2c47011 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 22 Feb 2005 21:05:17 +0200 Subject: [PATCH 4/7] row0sel.c: Fix bug #8677: if one used LOCK TABLES, created an InnoDB temp table, and did a multi-table update where a MyISAM table was the update table and the temp table was a read table, then InnoDB aserted in row0sel.c because n_mysql_tables_in_use was 0. Also, we remove the assertion altogether and just print an error to the .err log if this important consistency check fails. Then it is up to the user to read the .err log and notice the problem if there still are errors in MySQL's table locking. innobase/row/row0sel.c: Fix bug #8677: if one used LOCK TABLES, created an InnoDB temp table, and did a multi-table update where a MyISAM table was the update table and the temp table was a read table, then InnoDB aserted in row0sel.c because n_mysql_tables_in_use was 0. Also, we remove the assertion altogether and just print an error to the .err log if this important consistency check fails. Then it is up to the user to read the .err log and notice the problem if there still are errors in MySQL's table locking. --- innobase/row/row0sel.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c index 52228caccb0..2de02081176 100644 --- a/innobase/row/row0sel.c +++ b/innobase/row/row0sel.c @@ -2912,14 +2912,19 @@ row_search_for_mysql( ut_error; } - if (trx->n_mysql_tables_in_use == 0) { + if (trx->n_mysql_tables_in_use == 0 + && prebuilt->select_lock_type == LOCK_NONE) { + /* Note that if MySQL uses an InnoDB temp table that it + created inside LOCK TABLES, then n_mysql_tables_in_use can + be zero; in that case select_lock_type is set to LOCK_X in + ::start_stmt. */ + fputs( "InnoDB: Error: MySQL is trying to perform a SELECT\n" "InnoDB: but it has not locked any tables in ::external_lock()!\n", stderr); trx_print(stderr, trx); fputc('\n', stderr); - ut_a(0); } /* fprintf(stderr, "Match mode %lu\n search tuple ", (ulong) match_mode); From 3c5b16eebed40cf72d9deaa800229266bdf75f9a Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 25 Feb 2005 18:12:53 +0400 Subject: [PATCH 5/7] mysqldump.c: Bug#7997 Add implicit --skip-set-charset when mysqldump from 4.0 server w/ 4.1 client client/mysqldump.c: Bug#7997 Add implicit --skip-set-charset when mysqldump from 4.0 server w/ 4.1 client --- client/mysqldump.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/client/mysqldump.c b/client/mysqldump.c index c2c44024cf4..2c0bdf9a7a9 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -861,6 +861,11 @@ static int dbConnect(char *host, char *user,char *passwd) DBerror(&mysql_connection, "when trying to connect"); return 1; } + /* + Don't dump SET NAMES with a pre-4.1 server (bug#7997). + */ + if (mysql_get_server_version(&mysql_connection) < 40100) + opt_set_charset= 0; /* As we're going to set SQL_MODE, it would be lost on reconnect, so we cannot reconnect. From 46a8c5221750f4f0b5baf870d4f131d8f3de2821 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 25 Feb 2005 22:16:14 +0200 Subject: [PATCH 6/7] fil0fil.c: Check if node == NULL, which means we are outside tablespace bounds, and print a big fatal error message innobase/fil/fil0fil.c: Check if node == NULL, which means we are outside tablespace bounds, and print a big fatal error message --- innobase/fil/fil0fil.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/innobase/fil/fil0fil.c b/innobase/fil/fil0fil.c index a8da074cab9..16ae8e6e228 100644 --- a/innobase/fil/fil0fil.c +++ b/innobase/fil/fil0fil.c @@ -3800,13 +3800,6 @@ fil_io( node = UT_LIST_GET_FIRST(space->chain); for (;;) { - if (space->id != 0 && node->size == 0) { - /* We do not know the size of a single-table tablespace - before we open the file */ - - break; - } - if (node == NULL) { fprintf(stderr, "InnoDB: Error: trying to access page number %lu in space %lu,\n" @@ -3820,6 +3813,13 @@ fil_io( ut_error; } + if (space->id != 0 && node->size == 0) { + /* We do not know the size of a single-table tablespace + before we open the file */ + + break; + } + if (node->size > block_offset) { /* Found! */ break; From 8b8c9452ddc734c42301f64e625c31779968232a Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 28 Feb 2005 11:59:46 +0200 Subject: [PATCH 7/7] Fixed wrong memory references found by purify (No really critical errors found, but a few possible wrong results) innobase/dict/dict0dict.c: Replace memcmp with comparison of characters to avoid warnings from purify when 'sptr' points to a very short string mysql-test/r/select_found.result: Add missing drop table mysql-test/r/type_set.result: More tests mysql-test/t/select_found.test: Add missing drop table mysql-test/t/type_set.test: More tests mysys/my_init.c: Avoid warning from purify (purify doesn't handle getrusage() properly) sql/field.h: enum & set are sorted as numbers. This fixes an access to uninitialized memory when enum/set are multi-byte characters sql/filesort.cc: enum & set are sorted as numbers. This fixes an access to uninitialized memory when enum/set are multi-byte characters sql/item_cmpfunc.cc: Fixed warning from purify. (Not critical as the arguments are passed to a function but not used) Allocate Arg_comparator() with 'new' instead of sql_alloc() to ensure proper initialization sql/mysqld.cc: Wait for signal handler to stop when running --bootstrap (Fixes warning from purify) sql/sql_insert.cc: Initialize slot used by innodb.cc (not critical) sql/sql_lex.h: Better comments sql/sql_repl.cc: memcmp -> bcmp() to avoid warning from purify sql/sql_select.cc: Fix for out-of-bound memory reference when doing DISTINCT on const expressions strings/ctype-simple.c: Fixes to not access uninitialized memory (Not critical) --- innobase/dict/dict0dict.c | 3 +- mysql-test/r/select_found.result | 1 + mysql-test/r/type_set.result | 18 ++++++++ mysql-test/t/select_found.test | 1 + mysql-test/t/type_set.test | 2 + mysys/my_init.c | 4 ++ sql/field.h | 3 ++ sql/filesort.cc | 2 +- sql/item_cmpfunc.cc | 8 +++- sql/mysqld.cc | 42 +++++++++++------- sql/sql_insert.cc | 3 +- sql/sql_lex.h | 73 ++++++++++++++++++++++---------- sql/sql_repl.cc | 2 +- sql/sql_select.cc | 33 ++++++++++----- strings/ctype-simple.c | 9 ++-- 15 files changed, 148 insertions(+), 56 deletions(-) diff --git a/innobase/dict/dict0dict.c b/innobase/dict/dict0dict.c index 186f3be2f31..a73dd8b9dd9 100644 --- a/innobase/dict/dict0dict.c +++ b/innobase/dict/dict0dict.c @@ -2671,7 +2671,8 @@ scan_more: /* Starting quote: remember the quote character. */ quote = *sptr; } else if (*sptr == '#' - || (0 == memcmp("-- ", sptr, 3))) { + || (sptr[0] == '-' && sptr[1] == '-' && + sptr[2] == ' ')) { for (;;) { /* In Unix a newline is 0x0A while in Windows it is 0x0D followed by 0x0A */ diff --git a/mysql-test/r/select_found.result b/mysql-test/r/select_found.result index 665277f68f2..39a949ef86b 100644 --- a/mysql-test/r/select_found.result +++ b/mysql-test/r/select_found.result @@ -254,3 +254,4 @@ a SELECT FOUND_ROWS(); FOUND_ROWS() 1 +DROP TABLE t1; diff --git a/mysql-test/r/type_set.result b/mysql-test/r/type_set.result index 9c82f59fc69..5aedefda283 100644 --- a/mysql-test/r/type_set.result +++ b/mysql-test/r/type_set.result @@ -29,6 +29,12 @@ a A a,A a,A +select s from t1 order by concat(s); +s +A +a +a,A +a,A drop table t1; CREATE TABLE t1 (c set('ae','oe','ue','ss') collate latin1_german2_ci); INSERT INTO t1 VALUES ('ä'),('ö'),('ü'),('ß'); @@ -47,4 +53,16 @@ ss ss ae,oe,ue,ss ae,oe,ue,ss +SELECT c FROM t1 ORDER BY concat(c); +c +ae +ae +ae,oe,ue,ss +ae,oe,ue,ss +oe +oe +ss +ss +ue +ue DROP TABLE t1; diff --git a/mysql-test/t/select_found.test b/mysql-test/t/select_found.test index d31d7d0b02e..5bd068eb0e6 100644 --- a/mysql-test/t/select_found.test +++ b/mysql-test/t/select_found.test @@ -175,3 +175,4 @@ CREATE TABLE t1 (a int, b int); INSERT INTO t1 VALUES (1,2), (1,3), (1,4), (1,5); SELECT SQL_CALC_FOUND_ROWS DISTINCT 'a' FROM t1 GROUP BY b LIMIT 2; SELECT FOUND_ROWS(); +DROP TABLE t1; diff --git a/mysql-test/t/type_set.test b/mysql-test/t/type_set.test index e4aeecb2c79..b6410a9ea3d 100644 --- a/mysql-test/t/type_set.test +++ b/mysql-test/t/type_set.test @@ -23,6 +23,7 @@ create table t1 (s set ('a','A') character set latin1 collate latin1_bin); show create table t1; insert into t1 values ('a'),('a,A'),('A,a'),('A'); select s from t1 order by s; +select s from t1 order by concat(s); drop table t1; # @@ -34,4 +35,5 @@ INSERT INTO t1 VALUES ('ae'),('oe'),('ue'),('ss'); INSERT INTO t1 VALUES ('ä,ö,ü,ß'); INSERT INTO t1 VALUES ('ae,oe,ue,ss'); SELECT c FROM t1 ORDER BY c; +SELECT c FROM t1 ORDER BY concat(c); DROP TABLE t1; diff --git a/mysys/my_init.c b/mysys/my_init.c index c32fcfe6a09..bee485c3bed 100644 --- a/mysys/my_init.c +++ b/mysys/my_init.c @@ -145,6 +145,10 @@ void my_end(int infoflag) { #ifdef HAVE_GETRUSAGE struct rusage rus; +#ifdef HAVE_purify + /* Purify assumes that rus is uninitialized after getrusage call */ + bzero((char*) &rus, sizeof(rus)); +#endif if (!getrusage(RUSAGE_SELF, &rus)) fprintf(info_file,"\n\ User time %.2f, System time %.2f\n\ diff --git a/sql/field.h b/sql/field.h index fd0f2f9c2f1..b5d88504939 100644 --- a/sql/field.h +++ b/sql/field.h @@ -277,6 +277,7 @@ public: virtual bool get_date(TIME *ltime,uint fuzzydate); virtual bool get_time(TIME *ltime); virtual CHARSET_INFO *charset(void) const { return &my_charset_bin; } + virtual CHARSET_INFO *sort_charset(void) const { return charset(); } virtual bool has_charset(void) const { return FALSE; } virtual void set_charset(CHARSET_INFO *charset) { } bool set_warning(const unsigned int level, const unsigned int code, @@ -1152,6 +1153,8 @@ public: bool optimize_range(uint idx, uint part) { return 0; } bool eq_def(Field *field); bool has_charset(void) const { return TRUE; } + /* enum and set are sorted as integers */ + CHARSET_INFO *sort_charset(void) const { return &my_charset_bin; } field_cast_enum field_cast_type() { return FIELD_CAST_ENUM; } }; diff --git a/sql/filesort.cc b/sql/filesort.cc index 24088210f1a..76ce9ac4ce2 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -1127,7 +1127,7 @@ sortlength(SORT_FIELD *sortorder, uint s_length, bool *multi_byte_charset) else { sortorder->length=sortorder->field->pack_length(); - if (use_strnxfrm((cs=sortorder->field->charset()))) + if (use_strnxfrm((cs=sortorder->field->sort_charset()))) { sortorder->need_strxnfrm= 1; *multi_byte_charset= 1; diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index aff11ac7b25..690da1be18c 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -265,7 +265,7 @@ int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type) comparators= 0; return 1; } - if (!(comparators= (Arg_comparator *) sql_alloc(sizeof(Arg_comparator)*n))) + if (!(comparators= new Arg_comparator[n])) return 1; for (uint i=0; i < n; i++) { @@ -1528,6 +1528,12 @@ in_row::in_row(uint elements, Item * item) size= sizeof(cmp_item_row); compare= (qsort2_cmp) cmp_row; tmp.store_value(item); + /* + We need to reset these as otherwise we will call sort() with + uninitialized (even if not used) elements + */ + used_count= elements; + collation= 0; } in_row::~in_row() diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 1591b205d46..f1b1d8a7d86 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -530,6 +530,7 @@ extern "C" pthread_handler_decl(handle_slave,arg); static ulong find_bit_type(const char *x, TYPELIB *bit_lib); static void clean_up(bool print_message); static void clean_up_mutexes(void); +static void wait_for_signal_thread_to_end(void); static int test_if_case_insensitive(const char *dir_name); static void create_pid_file(); @@ -918,6 +919,7 @@ extern "C" void unireg_abort(int exit_code) sql_print_error("Aborting\n"); clean_up(exit_code || !opt_bootstrap); /* purecov: inspected */ DBUG_PRINT("quit",("done with cleanup in unireg_abort")); + wait_for_signal_thread_to_end(); clean_up_mutexes(); my_end(opt_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0); exit(exit_code); /* purecov: inspected */ @@ -1023,6 +1025,29 @@ void clean_up(bool print_message) } /* clean_up */ +/* + This is mainly needed when running with purify, but it's still nice to + know that all child threads have died when mysqld exits +*/ + +static void wait_for_signal_thread_to_end() +{ +#ifndef __NETWARE__ + uint i; + /* + Wait up to 10 seconds for signal thread to die. We use this mainly to + avoid getting warnings that my_thread_end has not been called + */ + for (i= 0 ; i < 100 && signal_thread_in_use; i++) + { + if (pthread_kill(signal_thread, MYSQL_KILL_SIGNAL)) + break; + my_sleep(100); // Give it time to die + } +#endif +} + + static void clean_up_mutexes() { (void) pthread_mutex_destroy(&LOCK_mysql_create_db); @@ -2117,6 +2142,7 @@ extern "C" void *signal_hand(void *arg __attribute__((unused))) while ((error=my_sigwait(&set,&sig)) == EINTR) ; if (cleanup_done) { + DBUG_PRINT("quit",("signal_handler: calling my_thread_end()")); my_thread_end(); signal_thread_in_use= 0; pthread_exit(0); // Safety @@ -3111,21 +3137,7 @@ we force server id to 2, but this MySQL server will not act as a slave."); CloseHandle(hEventShutdown); } #endif -#ifndef __NETWARE__ - { - uint i; - /* - Wait up to 10 seconds for signal thread to die. We use this mainly to - avoid getting warnings that my_thread_end has not been called - */ - for (i= 0 ; i < 100 && signal_thread_in_use; i++) - { - if (pthread_kill(signal_thread, MYSQL_KILL_SIGNAL)) - break; - my_sleep(100); // Give it time to die - } - } -#endif + wait_for_signal_thread_to_end(); clean_up_mutexes(); my_end(opt_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0); diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 844e5e7dac2..1f190a450de 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -688,7 +688,8 @@ public: thd.current_tablenr=0; thd.version=refresh_version; thd.command=COM_DELAYED_INSERT; - thd.lex->current_select= 0; /* for my_message_sql */ + thd.lex->current_select= 0; // for my_message_sql + thd.lex->sql_command= SQLCOM_INSERT; // For innodb::store_lock() bzero((char*) &thd.net, sizeof(thd.net)); // Safety bzero((char*) &table_list, sizeof(table_list)); // Safety diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 3e2f6a3f2b5..f48ff42bbf8 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -125,27 +125,46 @@ enum tablespace_op_type /* The state of the lex parsing for selects - All select describing structures linked with following pointers: - - list of neighbors (next/prev) (prev of first element point to slave - pointer of upper structure) - - one level units for unit (union) structure - - member of one union(unit) for ordinary select_lex - - pointer to master - - outer select_lex for unit (union) - - unit structure for ordinary select_lex - - pointer to slave - - first list element of select_lex belonged to this unit for unit - - first unit in list of units that belong to this select_lex (as - subselects or derived tables) for ordinary select_lex - - list of all select_lex (for group operation like correcting list of opened - tables) - - if unit contain several selects (union) then it have special - select_lex called fake_select_lex. It used for storing global parameters - and executing union. subqueries of global ORDER BY clause will be - attached to this fake_select_lex, which will allow them correctly - resolve fields of 'upper' union and other more outer selects. + master and slaves are pointers to select_lex. + master is pointer to upper level node. + slave is pointer to lower level node + select_lex is a SELECT without union + unit is container of either + - One SELECT + - UNION of selects + select_lex and unit are both inherited form select_lex_node + neighbors are two select_lex or units on the same level - for example for following query: + All select describing structures linked with following pointers: + - list of neighbors (next/prev) (prev of first element point to slave + pointer of upper structure) + - For select this is a list of UNION's (or one element list) + - For units this is a list of sub queries for the upper level select + + - pointer to master (master), which is + If this is a unit + - pointer to outer select_lex + If this is a select_lex + - pointer to outer unit structure for select + + - pointer to slave (slave), which is either: + If this is a unit: + - first SELECT that belong to this unit + If this is a select_lex + - first unit that belong to this SELECT (subquries or derived tables) + + - list of all select_lex (link_next/link_prev) + This is to be used for things like derived tables creation, where we + go through this list and create the derived tables. + + If unit contain several selects (UNION now, INTERSECT etc later) + then it have special select_lex called fake_select_lex. It used for + storing global parameters (like ORDER BY, LIMIT) and executing union. + Subqueries used in global ORDER BY clause will be attached to this + fake_select_lex, which will allow them correctly resolve fields of + 'upper' UNION and outer selects. + + For example for following query: select * from table1 @@ -163,6 +182,11 @@ enum tablespace_op_type we will have following structure: + select1: (select * from table1 ...) + select2: (select * from table2 ...) + select3: (select * from table3) + select1.1.1: (select * from table1_1_1) + ... main unit fake0 @@ -185,7 +209,12 @@ enum tablespace_op_type relation in main unit will be following: - + (bigger picture for: + main unit + fake0 + select1 select2 select3 + in the above picture) + main unit |^^^^|fake_select_lex |||||+--------------------------------------------+ @@ -382,7 +411,7 @@ private: typedef class st_select_lex_unit SELECT_LEX_UNIT; /* - SELECT_LEX - store information of parsed SELECT_LEX statment + SELECT_LEX - store information of parsed SELECT statment */ class st_select_lex: public st_select_lex_node { diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index fd165ad1fa5..d02bb5ff0a3 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -246,7 +246,7 @@ bool log_in_use(const char* log_name) if ((linfo = tmp->current_linfo)) { pthread_mutex_lock(&linfo->lock); - result = !memcmp(log_name, linfo->log_file_name, log_name_len); + result = !bcmp(log_name, linfo->log_file_name, log_name_len); pthread_mutex_unlock(&linfo->lock); if (result) break; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 05314097ca3..a210fbbbe02 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -7622,8 +7622,8 @@ static int remove_dup_with_hash_index(THD *thd, TABLE *table, { byte *key_buffer, *key_pos, *record=table->record[0]; int error; - handler *file=table->file; - ulong extra_length=ALIGN_SIZE(key_length)-key_length; + handler *file= table->file; + ulong extra_length= ALIGN_SIZE(key_length)-key_length; uint *field_lengths,*field_length; HASH hash; DBUG_ENTER("remove_dup_with_hash_index"); @@ -7637,22 +7637,34 @@ static int remove_dup_with_hash_index(THD *thd, TABLE *table, NullS)) DBUG_RETURN(1); + { + Field **ptr; + ulong total_length= 0; + for (ptr= first_field, field_length=field_lengths ; *ptr ; ptr++) + { + uint length= (*ptr)->pack_length(); + (*field_length++)= length; + total_length+= length; + } + DBUG_PRINT("info",("field_count: %u key_length: %lu total_length: %lu", + field_count, key_length, total_length)); + DBUG_ASSERT(total_length <= key_length); + key_length= total_length; + extra_length= ALIGN_SIZE(key_length)-key_length; + } + if (hash_init(&hash, &my_charset_bin, (uint) file->records, 0, - key_length,(hash_get_key) 0, 0, 0)) + key_length, (hash_get_key) 0, 0, 0)) { my_free((char*) key_buffer,MYF(0)); DBUG_RETURN(1); } - { - Field **ptr; - for (ptr= first_field, field_length=field_lengths ; *ptr ; ptr++) - (*field_length++)= (*ptr)->pack_length(); - } file->ha_rnd_init(1); key_pos=key_buffer; for (;;) { + byte *org_key_pos; if (thd->killed) { my_error(ER_SERVER_SHUTDOWN,MYF(0)); @@ -7675,6 +7687,7 @@ static int remove_dup_with_hash_index(THD *thd, TABLE *table, } /* copy fields to key buffer */ + org_key_pos= key_pos; field_length=field_lengths; for (Field **ptr= first_field ; *ptr ; ptr++) { @@ -7682,14 +7695,14 @@ static int remove_dup_with_hash_index(THD *thd, TABLE *table, key_pos+= *field_length++; } /* Check if it exists before */ - if (hash_search(&hash,key_pos-key_length,key_length)) + if (hash_search(&hash, org_key_pos, key_length)) { /* Duplicated found ; Remove the row */ if ((error=file->delete_row(record))) goto err; } else - (void) my_hash_insert(&hash, key_pos-key_length); + (void) my_hash_insert(&hash, org_key_pos); key_pos+=extra_length; } my_free((char*) key_buffer,MYF(0)); diff --git a/strings/ctype-simple.c b/strings/ctype-simple.c index c2a6aa4e17f..080e0b780b7 100644 --- a/strings/ctype-simple.c +++ b/strings/ctype-simple.c @@ -518,7 +518,6 @@ longlong my_strntoll_8bit(CHARSET_INFO *cs __attribute__((unused)), register unsigned int cutlim; register ulonglong i; register const char *s, *e; - register unsigned char c; const char *save; int overflow; @@ -581,8 +580,9 @@ longlong my_strntoll_8bit(CHARSET_INFO *cs __attribute__((unused)), overflow = 0; i = 0; - for (c = *s; s != e; c = *++s) + for ( ; s != e; s++) { + register unsigned char c= *s; if (c>='0' && c<='9') c -= '0'; else if (c>='A' && c<='Z') @@ -641,7 +641,6 @@ ulonglong my_strntoull_8bit(CHARSET_INFO *cs, register unsigned int cutlim; register ulonglong i; register const char *s, *e; - register unsigned char c; const char *save; int overflow; @@ -704,8 +703,10 @@ ulonglong my_strntoull_8bit(CHARSET_INFO *cs, overflow = 0; i = 0; - for (c = *s; s != e; c = *++s) + for ( ; s != e; s++) { + register unsigned char c= *s; + if (c>='0' && c<='9') c -= '0'; else if (c>='A' && c<='Z')