From c7581758ece924c94b1798cb9f97ef73d37b2223 Mon Sep 17 00:00:00 2001 From: "petr@mysql.com" <> Date: Wed, 1 Jun 2005 04:40:22 +0400 Subject: [PATCH 01/16] fix IM to display version string in "show instance status" (Bug #10229) --- server-tools/instance-manager/buffer.h | 2 +- server-tools/instance-manager/commands.cc | 9 +- .../instance-manager/instance_options.cc | 117 ++++++++++++++---- .../instance-manager/instance_options.h | 9 +- server-tools/instance-manager/options.cc | 2 +- server-tools/instance-manager/parse_output.cc | 24 +++- server-tools/instance-manager/parse_output.h | 3 +- 7 files changed, 130 insertions(+), 36 deletions(-) diff --git a/server-tools/instance-manager/buffer.h b/server-tools/instance-manager/buffer.h index a94047b11a5..e63d725f508 100644 --- a/server-tools/instance-manager/buffer.h +++ b/server-tools/instance-manager/buffer.h @@ -52,7 +52,7 @@ public: ~Buffer() { - free(buffer); + my_free(buffer, MYF(0)); } public: diff --git a/server-tools/instance-manager/commands.cc b/server-tools/instance-manager/commands.cc index 77c26fd28de..737eb47bdf6 100644 --- a/server-tools/instance-manager/commands.cc +++ b/server-tools/instance-manager/commands.cc @@ -203,15 +203,14 @@ int Show_instance_status::execute(struct st_net *net, if (!(instance= instance_map->find(instance_name, strlen(instance_name)))) goto err; if (instance->is_running()) - { store_to_string(&send_buff, (char*) "online", &position); - store_to_string(&send_buff, "unknown", &position); - } else - { store_to_string(&send_buff, (char*) "offline", &position); + + if (instance->options.mysqld_version) + store_to_string(&send_buff, instance->options.mysqld_version, &position); + else store_to_string(&send_buff, (char*) "unknown", &position); - } if (send_buff.is_error() || diff --git a/server-tools/instance-manager/instance_options.cc b/server-tools/instance-manager/instance_options.cc index c8288c35a6f..c6b9141ece4 100644 --- a/server-tools/instance-manager/instance_options.cc +++ b/server-tools/instance-manager/instance_options.cc @@ -27,6 +27,39 @@ #include #include +#ifdef __WIN__ +#define NEWLINE_LEN 2 +#else +#define NEWLINE_LEN 1 +#endif + + +/* Create "mysqld ..." command in the buffer */ + +static inline int create_mysqld_command(Buffer *buf, + const char *mysqld_path_str, + uint mysqld_path_len, + const char *option, + uint option_len) +{ + int position= 0; + + if (buf->get_size()) /* malloc succeeded */ + { + buf->append(position, mysqld_path_str, mysqld_path_len); + position+= mysqld_path_len; + /* here the '\0' character is copied from the option string */ + buf->append(position, option, option_len); + + if (buf->is_error()) + return 1; + } + else + return 1; + + return 0; +} + /* Get compiled-in value of default_option @@ -50,25 +83,19 @@ int Instance_options::get_default_option(char *result, size_t result_len, const char *option_name) { - int position= 0; int rc= 1; char verbose_option[]= " --no-defaults --verbose --help"; - Buffer cmd(strlen(mysqld_path) + sizeof(verbose_option) + 1); - if (cmd.get_size()) /* malloc succeeded */ - { - cmd.append(position, mysqld_path, strlen(mysqld_path)); - position+= strlen(mysqld_path); - cmd.append(position, verbose_option, sizeof(verbose_option) - 1); - position+= sizeof(verbose_option) - 1; - cmd.append(position, "\0", 1); + /* reserve space fot the path + option + final '\0' */ + Buffer cmd(mysqld_path_len + sizeof(verbose_option)); - if (cmd.is_error()) - goto err; - /* get the value from "mysqld --help --verbose" */ - rc= parse_output_and_get_value(cmd.buffer, option_name + 2, + if (create_mysqld_command(&cmd, mysqld_path, mysqld_path_len, + verbose_option, sizeof(verbose_option))) + goto err; + + /* +2 eats first "--" from the option string (E.g. "--datadir") */ + rc= parse_output_and_get_value(cmd.buffer, option_name + 2, result, result_len); - } return rc; err: @@ -77,17 +104,62 @@ err: /* - Get compiled-in value of default_option + Fill mysqld_version option (used at initialization stage) SYNOPSYS - get_default_option() - result buffer to put found value - result_len buffer size - option_name the name of the option, prefixed with "--" + fill_instance_version() DESCRIPTION - Get compile-in value of requested option from server + Get mysqld version string from "mysqld --version" output. + + RETURN + 0 - ok + 1 - error occured +*/ + +int Instance_options::fill_instance_version() +{ + enum { MAX_VERSION_STRING_LENGTH= 160 }; + enum { RETURN_LINE= 1 }; + char result[MAX_VERSION_STRING_LENGTH]; + char version_option[]= " --version"; + int rc= 1; + Buffer cmd(mysqld_path_len + sizeof(version_option)); + + if (create_mysqld_command(&cmd, mysqld_path, mysqld_path_len, + version_option, sizeof(version_option))) + goto err; + + rc= parse_output_and_get_value(cmd.buffer, mysqld_path, + result, MAX_VERSION_STRING_LENGTH, + RETURN_LINE); + + if (*result != '\0') + { + /* chop the newline from the end of the version string */ + result[strlen(result) - NEWLINE_LEN]= '\0'; + mysqld_version= strdup_root(&alloc, result); + } + + return rc; + +err: + return 1; +} + + +/* + Fill various log options + + SYNOPSYS + fill_log_options() + + DESCRIPTION + + Compute paths to enabled log files. If the path is not specified in the + instance explicitly (I.e. log=/home/user/mysql.log), we try to guess the + file name and placement. RETURN 0 - ok @@ -276,6 +348,8 @@ int Instance_options::complete_initialization(const char *default_path, goto err; } + mysqld_path_len= strlen(mysqld_path); + if (mysqld_port) mysqld_port_val= atoi(strchr(mysqld_port, '=') + 1); @@ -330,7 +404,8 @@ int Instance_options::complete_initialization(const char *default_path, options_array.elements*sizeof(char*)); argv[filled_default_options + options_array.elements]= 0; - fill_log_options(); + if (fill_log_options() || fill_instance_version()) + goto err; return 0; diff --git a/server-tools/instance-manager/instance_options.h b/server-tools/instance-manager/instance_options.h index ebeeaa1978e..0d2c32fae66 100644 --- a/server-tools/instance-manager/instance_options.h +++ b/server-tools/instance-manager/instance_options.h @@ -38,7 +38,7 @@ class Instance_options { public: Instance_options() : - mysqld_socket(0), mysqld_datadir(0), + mysqld_version(0), mysqld_socket(0), mysqld_datadir(0), mysqld_bind_address(0), mysqld_pid_file(0), mysqld_port(0), mysqld_port_val(0), mysqld_path(0), nonguarded(0), shutdown_delay(0), shutdown_delay_val(0), filled_default_options(0) @@ -64,6 +64,11 @@ public: enum { MEM_ROOT_BLOCK_SIZE= 512 }; char pid_file_with_path[MAX_PATH_LEN]; char **argv; + /* + Here we cache the version string, obtained from mysqld --version. + In the case when mysqld binary is not found we get "unknown" here. + */ + const char *mysqld_version; /* We need the some options, so we store them as a separate pointers */ const char *mysqld_socket; const char *mysqld_datadir; @@ -74,6 +79,7 @@ public: const char *instance_name; uint instance_name_len; const char *mysqld_path; + uint mysqld_path_len; const char *nonguarded; const char *shutdown_delay; uint shutdown_delay_val; @@ -84,6 +90,7 @@ public: DYNAMIC_ARRAY options_array; private: int fill_log_options(); + int fill_instance_version(); int add_to_argv(const char *option); int get_default_option(char *result, size_t result_len, const char *option_name); diff --git a/server-tools/instance-manager/options.cc b/server-tools/instance-manager/options.cc index 28899940e47..e44e4c6ff34 100644 --- a/server-tools/instance-manager/options.cc +++ b/server-tools/instance-manager/options.cc @@ -224,10 +224,10 @@ int Options::load(int argc, char **argv) /* config-file options are prepended to command-line ones */ load_defaults("my", default_groups, &argc, &argv); + Options::saved_argv= argv; if ((rc= handle_options(&argc, &argv, my_long_options, get_one_option)) != 0) return rc; - Options::saved_argv= argv; return 0; } diff --git a/server-tools/instance-manager/parse_output.cc b/server-tools/instance-manager/parse_output.cc index d6adb8079ce..8e083b0cd0d 100644 --- a/server-tools/instance-manager/parse_output.cc +++ b/server-tools/instance-manager/parse_output.cc @@ -32,10 +32,13 @@ word the word to look for (usually an option name) result the buffer to store the next word (option value) result_len self-explanatory + get_all_line flag, which is set if we want to get all the line after + the matched word. DESCRIPTION Parse output of the "command". Find the "word" and return the next one + if get_all_line is 0. Return the rest of the parsed string otherwise. RETURN 0 - ok @@ -43,7 +46,8 @@ */ int parse_output_and_get_value(const char *command, const char *word, - char *result, size_t result_len) + char *result, size_t result_len, + int get_all_line) { FILE *output; uint wordlen; @@ -81,11 +85,19 @@ int parse_output_and_get_value(const char *command, const char *word, an option value. */ linep+= lineword_len; /* swallow the previous one */ - get_word((const char **) &linep, &lineword_len, NONSPACE); - if (result_len <= lineword_len) - goto err; - strncpy(result, linep, lineword_len); - result[lineword_len]= '\0'; + if (!get_all_line) + { + get_word((const char **) &linep, &lineword_len, NONSPACE); + if (result_len <= lineword_len) + goto err; + strncpy(result, linep, lineword_len); + result[lineword_len]= '\0'; + } + else + { + strncpy(result, linep, result_len); + result[result_len]= '\0'; /* safety */ + } goto pclose; } } diff --git a/server-tools/instance-manager/parse_output.h b/server-tools/instance-manager/parse_output.h index 48fd2ae4068..e0161cf29e3 100644 --- a/server-tools/instance-manager/parse_output.h +++ b/server-tools/instance-manager/parse_output.h @@ -17,6 +17,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ int parse_output_and_get_value(const char *command, const char *word, - char *result, size_t result_len); + char *result, size_t result_len, + int get_all_line= 0); #endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_PARSE_OUTPUT_H */ From b906f31388b5c7c5a7cbd38b9a2f7b2f38b4b0c2 Mon Sep 17 00:00:00 2001 From: "elliot@mysql.com" <> Date: Mon, 6 Jun 2005 22:17:16 -0400 Subject: [PATCH 02/16] BUG#7967 Fix mysqlhotcopy --record-log-position --- .bzrignore | 1 + scripts/mysqlhotcopy.sh | 20 +++++++++++++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/.bzrignore b/.bzrignore index c9f9f140366..174fc6020f2 100644 --- a/.bzrignore +++ b/.bzrignore @@ -1052,3 +1052,4 @@ vio/test-ssl vio/test-sslclient vio/test-sslserver vio/viotest-ssl +scripts/mysqlhotcopy.sh.rej diff --git a/scripts/mysqlhotcopy.sh b/scripts/mysqlhotcopy.sh index 632174dc41a..1c5cd6a4faf 100644 --- a/scripts/mysqlhotcopy.sh +++ b/scripts/mysqlhotcopy.sh @@ -746,9 +746,15 @@ sub record_log_pos { my ($file,$position) = get_row( $dbh, "show master status" ); die "master status is undefined" if !defined $file || !defined $position; - my ($master_host, undef, undef, undef, $log_file, $log_pos ) - = get_row( $dbh, "show slave status" ); - + my $row_hash = get_row_hash( $dbh, "show slave status" ); + my ($master_host, $log_file, $log_pos ); + if ( $dbh->{mysql_serverinfo} =~ /^3\.23/ ) { + ($master_host, $log_file, $log_pos ) + = @{$row_hash}{ qw / Master_Host Log_File Pos / }; + } else { + ($master_host, $log_file, $log_pos ) + = @{$row_hash}{ qw / Master_Host Master_Log_File Read_Master_Log_Pos / }; + } my $hostname = hostname(); $dbh->do( qq{ replace into $table_name @@ -773,6 +779,14 @@ sub get_row { return $sth->fetchrow_array(); } +sub get_row_hash { + my ( $dbh, $sql ) = @_; + + my $sth = $dbh->prepare($sql); + $sth->execute; + return $sth->fetchrow_hashref(); +} + sub scan_raid_dir { my ( $r_db_files, $data_dir, @raid_dir ) = @_; From 093573b6b722b17bf550bebb2058fa8cac33c110 Mon Sep 17 00:00:00 2001 From: "bar@mysql.com" <> Date: Tue, 7 Jun 2005 13:56:42 +0500 Subject: [PATCH 03/16] Bug#10253: compound index length and utf8 char set produces invalid query results mi_key.c: well_formed_length should be executed before space trimming, not after. ctype_utf8.test: ctype_utf8.result: adding test. --- myisam/mi_key.c | 6 +++--- mysql-test/r/ctype_utf8.result | 11 +++++++++++ mysql-test/t/ctype_utf8.test | 14 ++++++++++++++ 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/myisam/mi_key.c b/myisam/mi_key.c index b7240f34538..6a8d88f1117 100644 --- a/myisam/mi_key.c +++ b/myisam/mi_key.c @@ -84,7 +84,8 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key, pos= (byte*) record+keyseg->start; if (keyseg->flag & HA_SPACE_PACK) { - end=pos+length; + FIX_LENGTH(cs, pos, length, char_length); + end= pos + char_length; if (type != HA_KEYTYPE_NUM) { while (end > pos && end[-1] == ' ') @@ -95,8 +96,7 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key, while (pos < end && pos[0] == ' ') pos++; } - length=(uint) (end-pos); - FIX_LENGTH(cs, pos, length, char_length); + char_length= (uint) (end - pos); store_key_length_inc(key,char_length); memcpy((byte*) key,(byte*) pos,(size_t) char_length); key+=char_length; diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index b7aa7c68b67..ac421ea1717 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -891,3 +891,14 @@ string create table t1 (a varchar(255)) default character set utf8; insert into t1 values (1.0); drop table t1; +create table t1 ( +id int not null, +city varchar(20) not null, +key (city(7),id) +) character set=utf8; +insert into t1 values (1,'Durban North'); +insert into t1 values (2,'Durban'); +select * from t1 where city = 'Durban'; +id city +2 Durban +drop table t1; diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test index bac6e60c302..a281558e5a1 100644 --- a/mysql-test/t/ctype_utf8.test +++ b/mysql-test/t/ctype_utf8.test @@ -731,3 +731,17 @@ select ifnull(NULL, _utf8'string'); create table t1 (a varchar(255)) default character set utf8; insert into t1 values (1.0); drop table t1; + +# +# Bug#10253 compound index length and utf8 char set +# produces invalid query results +# +create table t1 ( + id int not null, + city varchar(20) not null, + key (city(7),id) +) character set=utf8; +insert into t1 values (1,'Durban North'); +insert into t1 values (2,'Durban'); +select * from t1 where city = 'Durban'; +drop table t1; From 2a1f5c074842ee44d7c7289917311468ea18d464 Mon Sep 17 00:00:00 2001 From: "elliot@mysql.com" <> Date: Tue, 7 Jun 2005 05:10:18 -0400 Subject: [PATCH 04/16] Accepted openlogging --- BitKeeper/etc/logging_ok | 1 + 1 file changed, 1 insertion(+) diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index ce1e179789e..343fb26c83a 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -47,6 +47,7 @@ dlenev@build.mysql.com dlenev@jabberwock.localdomain dlenev@mysql.com ejonore@mc03.ndb.mysql.com +elliot@mysql.com evgen@moonbone.(none) evgen@moonbone.local gbichot@bk-internal.mysql.com From 90dd86907ef5f0714b18cc66851b9407a3794ee5 Mon Sep 17 00:00:00 2001 From: "igor@rurik.mysql.com" <> Date: Tue, 7 Jun 2005 03:05:57 -0700 Subject: [PATCH 05/16] sql_select.cc, item_buff.cc, item.h: Fixed bug #11088: a crash for queries with GROUP BY a BLOB column + COUNT(DISTINCT...) due to an attempt to allocate a too large buffer for the BLOB field. Now the size of the buffer is limited by max_sort_length. group_by.test, group_by.result: Added a test case for bug #11088. --- mysql-test/r/group_by.result | 11 +++++++++++ mysql-test/t/group_by.test | 17 +++++++++++++++++ sql/item.h | 4 ++-- sql/item_buff.cc | 9 +++++++-- sql/sql_select.cc | 2 +- 5 files changed, 38 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result index b0c00a51722..3e082fa04e3 100644 --- a/mysql-test/r/group_by.result +++ b/mysql-test/r/group_by.result @@ -711,3 +711,14 @@ select min(b) from t1; min(b) 3000000000 drop table t1; +CREATE TABLE t1 (id int PRIMARY KEY, user_id int, hostname longtext); +INSERT INTO t1 VALUES +(1, 7, 'cache-dtc-af05.proxy.aol.com'), +(2, 3, 'what.ever.com'), +(3, 7, 'cache-dtc-af05.proxy.aol.com'), +(4, 7, 'cache-dtc-af05.proxy.aol.com'); +SELECT hostname, COUNT(DISTINCT user_id) as no FROM t1 +WHERE hostname LIKE '%aol%' + GROUP BY hostname; +hostname no +cache-dtc-af05.proxy.aol.com 1 diff --git a/mysql-test/t/group_by.test b/mysql-test/t/group_by.test index fbd39019e6d..21d5abcc287 100644 --- a/mysql-test/t/group_by.test +++ b/mysql-test/t/group_by.test @@ -522,3 +522,20 @@ insert into t1 values(3000000000); select * from t1; select min(b) from t1; drop table t1; + +# +# Test for bug #11088: GROUP BY a BLOB colimn with COUNT(DISTINCT column1) +# + +CREATE TABLE t1 (id int PRIMARY KEY, user_id int, hostname longtext); + +INSERT INTO t1 VALUES + (1, 7, 'cache-dtc-af05.proxy.aol.com'), + (2, 3, 'what.ever.com'), + (3, 7, 'cache-dtc-af05.proxy.aol.com'), + (4, 7, 'cache-dtc-af05.proxy.aol.com'); + +SELECT hostname, COUNT(DISTINCT user_id) as no FROM t1 + WHERE hostname LIKE '%aol%' + GROUP BY hostname; + diff --git a/sql/item.h b/sql/item.h index 2edbeef400c..8de2adeb730 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1118,7 +1118,7 @@ class Item_str_buff :public Item_buff Item *item; String value,tmp_value; public: - Item_str_buff(Item *arg) :item(arg),value(arg->max_length) {} + Item_str_buff(THD *thd, Item *arg); bool cmp(void); ~Item_str_buff(); // Deallocate String:s }; @@ -1385,7 +1385,7 @@ public: }; -extern Item_buff *new_Item_buff(Item *item); +extern Item_buff *new_Item_buff(THD *thd, Item *item); extern Item_result item_cmp_type(Item_result a,Item_result b); extern void resolve_const_item(THD *thd, Item **ref, Item *cmp_item); extern bool field_is_equal_to_item(Field *field,Item *item); diff --git a/sql/item_buff.cc b/sql/item_buff.cc index 1559cfe958e..2324205eb65 100644 --- a/sql/item_buff.cc +++ b/sql/item_buff.cc @@ -23,13 +23,13 @@ ** Create right type of item_buffer for an item */ -Item_buff *new_Item_buff(Item *item) +Item_buff *new_Item_buff(THD *thd, Item *item) { if (item->type() == Item::FIELD_ITEM && !(((Item_field *) item)->field->flags & BLOB_FLAG)) return new Item_field_buff((Item_field *) item); if (item->result_type() == STRING_RESULT) - return new Item_str_buff((Item_field *) item); + return new Item_str_buff(thd, (Item_field *) item); if (item->result_type() == INT_RESULT) return new Item_int_buff((Item_field *) item); return new Item_real_buff(item); @@ -42,12 +42,17 @@ Item_buff::~Item_buff() {} ** Return true if values have changed */ +Item_str_buff::Item_str_buff(THD *thd, Item *arg) + :item(arg), value(min(arg->max_length, thd->variables. max_sort_length)) +{} + 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 (null_value != item->null_value) { if ((null_value= item->null_value)) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 0424cd8fdbb..5b1603b44e2 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -8656,7 +8656,7 @@ alloc_group_fields(JOIN *join,ORDER *group) { for (; group ; group=group->next) { - Item_buff *tmp=new_Item_buff(*group->item); + Item_buff *tmp=new_Item_buff(join->thd, *group->item); if (!tmp || join->group_fields.push_front(tmp)) return TRUE; } From 9f379d7f05c43b2d09de91c3af5cc35613a745e4 Mon Sep 17 00:00:00 2001 From: "konstantin@mysql.com" <> Date: Tue, 7 Jun 2005 14:11:36 +0400 Subject: [PATCH 06/16] Patch two (the final one) for Bug#7306 "the server side preparedStatement error for LIMIT placeholder". The patch adds grammar support for LIMIT ?, ? and changes the type of ST_SELECT_LEX::select_limit,offset_limit from ha_rows to Item*, so that it can point to Item_param. --- mysql-test/include/ps_modify.inc | 7 ++---- mysql-test/include/ps_query.inc | 6 ++--- mysql-test/r/ps.result | 41 ++++++++++++++++++++++++++++++++ mysql-test/r/ps_2myisam.result | 13 +++++----- mysql-test/r/ps_3innodb.result | 13 +++++----- mysql-test/r/ps_4heap.result | 13 +++++----- mysql-test/r/ps_5merge.result | 26 ++++++++++---------- mysql-test/r/ps_6bdb.result | 13 +++++----- mysql-test/r/ps_7ndb.result | 10 +++----- mysql-test/t/ps.test | 29 ++++++++++++++++++++++ sql/item.h | 12 ++++++---- sql/item_subselect.cc | 4 ++-- sql/sp_head.cc | 4 ++-- sql/sql_class.h | 5 ++-- sql/sql_derived.cc | 8 +++---- sql/sql_error.cc | 16 ++++++------- sql/sql_handler.cc | 11 ++++----- sql/sql_lex.cc | 33 ++++++++++++------------- sql/sql_lex.h | 2 +- sql/sql_parse.cc | 25 +++++++++++-------- sql/sql_repl.cc | 6 +++-- sql/sql_select.cc | 2 +- sql/sql_union.cc | 2 +- sql/sql_view.cc | 5 ++-- sql/sql_yacc.yy | 29 ++++++++++++---------- 25 files changed, 203 insertions(+), 132 deletions(-) diff --git a/mysql-test/include/ps_modify.inc b/mysql-test/include/ps_modify.inc index 04b9734240b..633c317f4b2 100644 --- a/mysql-test/include/ps_modify.inc +++ b/mysql-test/include/ps_modify.inc @@ -174,11 +174,8 @@ where a=2 limit 1'; execute stmt1 ; select a,b from t1 where b = 'bla' ; -# currently (May 2004, Version 4.1) it is impossible --- error 1064 -prepare stmt1 from 'update t1 set b=''bla'' -where a=2 -limit ?'; +prepare stmt1 from 'update t1 set b=''bla'' where a=2 limit ?'; +execute stmt1 using @arg00; --disable_query_log select '------ insert tests ------' as test_sequence ; diff --git a/mysql-test/include/ps_query.inc b/mysql-test/include/ps_query.inc index 9a413bff2f3..63504a0fa2b 100644 --- a/mysql-test/include/ps_query.inc +++ b/mysql-test/include/ps_query.inc @@ -300,10 +300,8 @@ set @arg00=1; prepare stmt1 from ' select a,b from t1 order by a limit 1 '; execute stmt1 ; -# currently (May 2004, Version 4.1) it is impossible --- error 1064 -prepare stmt1 from ' select a,b from t1 -limit ? '; +prepare stmt1 from ' select a,b from t1 limit ? '; +execute stmt1 using @arg00; ##### parameter used in many places set @arg00='b' ; diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index 8371437d664..496d566a5ee 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -634,3 +634,44 @@ id 3 deallocate prepare stmt; drop table t1, t2; +create table t1 (a int); +insert into t1 (a) values (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); +prepare stmt from "select * from t1 limit ?, ?"; +set @offset=0, @limit=1; +execute stmt using @offset, @limit; +a +1 +select * from t1 limit 0, 1; +a +1 +set @offset=3, @limit=2; +execute stmt using @offset, @limit; +a +4 +5 +select * from t1 limit 3, 2; +a +4 +5 +prepare stmt from "select * from t1 limit ?"; +execute stmt using @limit; +a +1 +2 +prepare stmt from "select * from t1 where a in (select a from t1 limit ?)"; +ERROR 42000: This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery' +prepare stmt from "select * from t1 union all select * from t1 limit ?, ?"; +set @offset=9; +set @limit=2; +execute stmt using @offset, @limit; +a +10 +1 +prepare stmt from "(select * from t1 limit ?, ?) union all + (select * from t1 limit ?, ?) order by a limit ?"; +execute stmt using @offset, @limit, @offset, @limit, @limit; +a +10 +10 +drop table t1; +deallocate prepare stmt; diff --git a/mysql-test/r/ps_2myisam.result b/mysql-test/r/ps_2myisam.result index d6c3d0e78d5..53fb3da8bb9 100644 --- a/mysql-test/r/ps_2myisam.result +++ b/mysql-test/r/ps_2myisam.result @@ -444,9 +444,10 @@ limit 1 '; execute stmt1 ; a b 1 one -prepare stmt1 from ' select a,b from t1 -limit ? '; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 2 +prepare stmt1 from ' select a,b from t1 limit ? '; +execute stmt1 using @arg00; +a b +1 one set @arg00='b' ; set @arg01=0 ; set @arg02=2 ; @@ -1381,10 +1382,8 @@ execute stmt1 ; select a,b from t1 where b = 'bla' ; a b 2 bla -prepare stmt1 from 'update t1 set b=''bla'' -where a=2 -limit ?'; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 3 +prepare stmt1 from 'update t1 set b=''bla'' where a=2 limit ?'; +execute stmt1 using @arg00; test_sequence ------ insert tests ------ delete from t1 ; diff --git a/mysql-test/r/ps_3innodb.result b/mysql-test/r/ps_3innodb.result index 1bbc1091393..658fd01dd0d 100644 --- a/mysql-test/r/ps_3innodb.result +++ b/mysql-test/r/ps_3innodb.result @@ -444,9 +444,10 @@ limit 1 '; execute stmt1 ; a b 1 one -prepare stmt1 from ' select a,b from t1 -limit ? '; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 2 +prepare stmt1 from ' select a,b from t1 limit ? '; +execute stmt1 using @arg00; +a b +1 one set @arg00='b' ; set @arg01=0 ; set @arg02=2 ; @@ -1364,10 +1365,8 @@ execute stmt1 ; select a,b from t1 where b = 'bla' ; a b 2 bla -prepare stmt1 from 'update t1 set b=''bla'' -where a=2 -limit ?'; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 3 +prepare stmt1 from 'update t1 set b=''bla'' where a=2 limit ?'; +execute stmt1 using @arg00; test_sequence ------ insert tests ------ delete from t1 ; diff --git a/mysql-test/r/ps_4heap.result b/mysql-test/r/ps_4heap.result index 009b642d7e7..f22317974cb 100644 --- a/mysql-test/r/ps_4heap.result +++ b/mysql-test/r/ps_4heap.result @@ -445,9 +445,10 @@ limit 1 '; execute stmt1 ; a b 1 one -prepare stmt1 from ' select a,b from t1 -limit ? '; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 2 +prepare stmt1 from ' select a,b from t1 limit ? '; +execute stmt1 using @arg00; +a b +1 one set @arg00='b' ; set @arg01=0 ; set @arg02=2 ; @@ -1365,10 +1366,8 @@ execute stmt1 ; select a,b from t1 where b = 'bla' ; a b 2 bla -prepare stmt1 from 'update t1 set b=''bla'' -where a=2 -limit ?'; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 3 +prepare stmt1 from 'update t1 set b=''bla'' where a=2 limit ?'; +execute stmt1 using @arg00; test_sequence ------ insert tests ------ delete from t1 ; diff --git a/mysql-test/r/ps_5merge.result b/mysql-test/r/ps_5merge.result index 5bd18078213..2ce7eb34a10 100644 --- a/mysql-test/r/ps_5merge.result +++ b/mysql-test/r/ps_5merge.result @@ -487,9 +487,10 @@ limit 1 '; execute stmt1 ; a b 1 one -prepare stmt1 from ' select a,b from t1 -limit ? '; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 2 +prepare stmt1 from ' select a,b from t1 limit ? '; +execute stmt1 using @arg00; +a b +1 one set @arg00='b' ; set @arg01=0 ; set @arg02=2 ; @@ -1407,10 +1408,8 @@ execute stmt1 ; select a,b from t1 where b = 'bla' ; a b 2 bla -prepare stmt1 from 'update t1 set b=''bla'' -where a=2 -limit ?'; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 3 +prepare stmt1 from 'update t1 set b=''bla'' where a=2 limit ?'; +execute stmt1 using @arg00; test_sequence ------ insert tests ------ delete from t1 ; @@ -3500,9 +3499,10 @@ limit 1 '; execute stmt1 ; a b 1 one -prepare stmt1 from ' select a,b from t1 -limit ? '; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 2 +prepare stmt1 from ' select a,b from t1 limit ? '; +execute stmt1 using @arg00; +a b +1 one set @arg00='b' ; set @arg01=0 ; set @arg02=2 ; @@ -4420,10 +4420,8 @@ execute stmt1 ; select a,b from t1 where b = 'bla' ; a b 2 bla -prepare stmt1 from 'update t1 set b=''bla'' -where a=2 -limit ?'; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 3 +prepare stmt1 from 'update t1 set b=''bla'' where a=2 limit ?'; +execute stmt1 using @arg00; test_sequence ------ insert tests ------ delete from t1 ; diff --git a/mysql-test/r/ps_6bdb.result b/mysql-test/r/ps_6bdb.result index 753def70dc0..03b155c6fa4 100644 --- a/mysql-test/r/ps_6bdb.result +++ b/mysql-test/r/ps_6bdb.result @@ -444,9 +444,10 @@ limit 1 '; execute stmt1 ; a b 1 one -prepare stmt1 from ' select a,b from t1 -limit ? '; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 2 +prepare stmt1 from ' select a,b from t1 limit ? '; +execute stmt1 using @arg00; +a b +1 one set @arg00='b' ; set @arg01=0 ; set @arg02=2 ; @@ -1364,10 +1365,8 @@ execute stmt1 ; select a,b from t1 where b = 'bla' ; a b 2 bla -prepare stmt1 from 'update t1 set b=''bla'' -where a=2 -limit ?'; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 3 +prepare stmt1 from 'update t1 set b=''bla'' where a=2 limit ?'; +execute stmt1 using @arg00; test_sequence ------ insert tests ------ delete from t1 ; diff --git a/mysql-test/r/ps_7ndb.result b/mysql-test/r/ps_7ndb.result index a6da6e169db..3b071d70b93 100644 --- a/mysql-test/r/ps_7ndb.result +++ b/mysql-test/r/ps_7ndb.result @@ -1,6 +1,4 @@ -use test; -drop table if exists t1, t9 ; -create table t1 +use test; drop table if exists t1, t9 ; create table t1 ( a int, b varchar(30), primary key(a) @@ -1364,10 +1362,8 @@ execute stmt1 ; select a,b from t1 where b = 'bla' ; a b 2 bla -prepare stmt1 from 'update t1 set b=''bla'' -where a=2 -limit ?'; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 3 +prepare stmt1 from 'update t1 set b=''bla'' where a=2 limit ?'; +execute stmt1 using @arg00; test_sequence ------ insert tests ------ delete from t1 ; diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index f4396e41a20..60b77576572 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -664,3 +664,32 @@ select t2.id from t2, t1 where (t1.id=1 and t2.t1_id=t1.id); deallocate prepare stmt; drop table t1, t2; + +# +# Bug#7306 LIMIT ?, ? and also WL#1785 " Prepared statements: implement +# support for placeholders in LIMIT clause." +# Add basic test coverage for the feature. +# +create table t1 (a int); +insert into t1 (a) values (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); +prepare stmt from "select * from t1 limit ?, ?"; +set @offset=0, @limit=1; +execute stmt using @offset, @limit; +select * from t1 limit 0, 1; +set @offset=3, @limit=2; +execute stmt using @offset, @limit; +select * from t1 limit 3, 2; +prepare stmt from "select * from t1 limit ?"; +execute stmt using @limit; +--error 1235 +prepare stmt from "select * from t1 where a in (select a from t1 limit ?)"; +prepare stmt from "select * from t1 union all select * from t1 limit ?, ?"; +set @offset=9; +set @limit=2; +execute stmt using @offset, @limit; +prepare stmt from "(select * from t1 limit ?, ?) union all + (select * from t1 limit ?, ?) order by a limit ?"; +execute stmt using @offset, @limit, @offset, @limit, @limit; + +drop table t1; +deallocate prepare stmt; diff --git a/sql/item.h b/sql/item.h index 4f5ed9934c5..4a7dd5b6390 100644 --- a/sql/item.h +++ b/sql/item.h @@ -334,6 +334,11 @@ public: If value is not null null_value flag will be reset to FALSE. */ virtual longlong val_int()=0; + /* + This is just a shortcut to avoid the cast. You should still use + unsigned_flag to check the sign of the item. + */ + inline ulonglong val_uint() { return (ulonglong) val_int(); } /* Return string representation of this item object. @@ -978,10 +983,10 @@ public: longlong value; Item_int(int32 i,uint length=11) :value((longlong) i) { max_length=length; fixed= 1; } -#ifdef HAVE_LONG_LONG Item_int(longlong i,uint length=21) :value(i) { max_length=length; fixed= 1; } -#endif + Item_int(ulonglong i, uint length= 21) :value((longlong)i) + { max_length=length; fixed= 1; unsigned_flag= 1; } Item_int(const char *str_arg,longlong i,uint length) :value(i) { max_length=length; name=(char*) str_arg; fixed= 1; } Item_int(const char *str_arg, uint length=64); @@ -1019,9 +1024,8 @@ class Item_uint :public Item_int { public: Item_uint(const char *str_arg, uint length); + Item_uint(uint32 i) :Item_int((ulonglong) i, 10) {} Item_uint(const char *str_arg, longlong i, uint length); - Item_uint(uint32 i) :Item_int((longlong) i, 10) - { unsigned_flag= 1; } double val_real() { DBUG_ASSERT(fixed == 1); return ulonglong2double((ulonglong)value); } String *val_str(String*); diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 4f1e5b9a290..7b83cbcd53a 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -602,8 +602,8 @@ void Item_exists_subselect::fix_length_and_dec() decimals= 0; max_length= 1; max_columns= engine->cols(); - /* We need only 1 row to determinate existence */ - unit->global_parameters->select_limit= 1; + /* We need only 1 row to determine existence */ + unit->global_parameters->select_limit= new Item_int(1); } double Item_exists_subselect::val_real() diff --git a/sql/sp_head.cc b/sql/sp_head.cc index c17c8b81cb2..a72128a54da 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -320,7 +320,7 @@ sp_head::sp_head() *sp_lex_sp_key(const byte *ptr, uint *plen, my_bool first); DBUG_ENTER("sp_head::sp_head"); - state= INITIALIZED; + state= INITIALIZED_FOR_SP; m_backpatch.empty(); m_lex.empty(); hash_init(&m_sptabs, system_charset_info, 0, 0, 0, sp_table_key, 0, 0); @@ -1078,7 +1078,7 @@ sp_head::restore_thd_mem_root(THD *thd) DBUG_ENTER("sp_head::restore_thd_mem_root"); Item *flist= free_list; // The old list set_item_arena(thd); // Get new free_list and mem_root - state= INITIALIZED; + state= INITIALIZED_FOR_SP; DBUG_PRINT("info", ("mem_root 0x%lx returned from thd mem root 0x%lx", (ulong) &mem_root, (ulong) &thd->mem_root)); diff --git a/sql/sql_class.h b/sql/sql_class.h index 7c8ead7558e..a976407322f 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -665,8 +665,8 @@ public: #endif enum enum_state { - INITIALIZED= 0, PREPARED= 1, EXECUTED= 3, CONVENTIONAL_EXECUTION= 2, - ERROR= -1 + INITIALIZED= 0, INITIALIZED_FOR_SP= 1, PREPARED= 2, + CONVENTIONAL_EXECUTION= 3, EXECUTED= 4, ERROR= -1 }; enum_state state; @@ -695,6 +695,7 @@ public: virtual Type type() const; virtual ~Item_arena() {}; + inline bool is_stmt_prepare() const { return state == INITIALIZED; } inline bool is_stmt_prepare_or_first_sp_execute() const { return (int)state < (int)PREPARED; } inline bool is_first_stmt_execute() const { return state == PREPARED; } diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 2ae293c1bff..e1d701936cf 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -217,6 +217,8 @@ exit: queries defined. After temporary table is filled, if this is not EXPLAIN, then the entire unit / node is deleted. unit is deleted if UNION is used for derived table and node is deleted is it is a simple SELECT. + If you use this function, make sure it's not called at prepare. + Due to evaluation of LIMIT clause it can not be used at prepared stage. RETURN 0 ok @@ -245,11 +247,7 @@ int mysql_derived_filling(THD *thd, LEX *lex, TABLE_LIST *orig_table_list) } else { - unit->offset_limit_cnt= first_select->offset_limit; - unit->select_limit_cnt= first_select->select_limit+ - first_select->offset_limit; - if (unit->select_limit_cnt < first_select->select_limit) - unit->select_limit_cnt= HA_POS_ERROR; + unit->set_limit(first_select); if (unit->select_limit_cnt == HA_POS_ERROR) first_select->options&= ~OPTION_FOUND_ROWS; diff --git a/sql/sql_error.cc b/sql/sql_error.cc index 3bda16202b9..8a12339ccee 100644 --- a/sql/sql_error.cc +++ b/sql/sql_error.cc @@ -225,20 +225,22 @@ bool mysqld_show_warnings(THD *thd, ulong levels_to_show) MYSQL_ERROR *err; SELECT_LEX *sel= &thd->lex->select_lex; - ha_rows offset= sel->offset_limit, limit= sel->select_limit; + SELECT_LEX_UNIT *unit= &thd->lex->unit; + ha_rows idx= 0; Protocol *protocol=thd->protocol; - + + unit->set_limit(sel); + List_iterator_fast it(thd->warn_list); while ((err= it++)) { /* Skip levels that the user is not interested in */ if (!(levels_to_show & ((ulong) 1 << err->level))) continue; - if (offset) - { - offset--; + if (++idx <= unit->offset_limit_cnt) continue; - } + if (idx > unit->select_limit_cnt) + break; protocol->prepare_for_resend(); protocol->store(warning_level_names[err->level], warning_level_length[err->level], system_charset_info); @@ -246,8 +248,6 @@ bool mysqld_show_warnings(THD *thd, ulong levels_to_show) protocol->store(err->msg, strlen(err->msg), system_charset_info); if (protocol->write()) DBUG_RETURN(TRUE); - if (!--limit) - break; } send_eof(thd); DBUG_RETURN(FALSE); diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index 1aa034ce61c..aca53db0ec8 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -321,8 +321,8 @@ bool mysql_ha_close(THD *thd, TABLE_LIST *tables) key_expr ha_rkey_mode cond - select_limit - offset_limit + select_limit_cnt + offset_limit_cnt RETURN FALSE ok @@ -333,7 +333,7 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables, enum enum_ha_read_modes mode, char *keyname, List *key_expr, enum ha_rkey_function ha_rkey_mode, Item *cond, - ha_rows select_limit,ha_rows offset_limit) + ha_rows select_limit_cnt, ha_rows offset_limit_cnt) { TABLE_LIST *hash_tables; TABLE *table; @@ -429,7 +429,6 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables, if (insert_fields(thd, tables, tables->db, tables->alias, &it, 0, 0)) goto err0; - select_limit+=offset_limit; protocol->send_fields(&list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF); HANDLER_TABLES_HACK(thd); @@ -447,7 +446,7 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables, table->file->init_table_handle_for_HANDLER(); - for (num_rows=0; num_rows < select_limit; ) + for (num_rows=0; num_rows < select_limit_cnt; ) { switch (mode) { case RFIRST: @@ -535,7 +534,7 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables, } if (cond && !cond->val_int()) continue; - if (num_rows >= offset_limit) + if (num_rows >= offset_limit_cnt) { Item *item; protocol->prepare_for_resend(); diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 574c9966c63..6b9330182d6 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1138,8 +1138,9 @@ void st_select_lex::init_select() order_list.elements= 0; order_list.first= 0; order_list.next= (byte**) &order_list.first; - select_limit= HA_POS_ERROR; - offset_limit= 0; + /* Set limit and offset to default values */ + select_limit= 0; /* denotes the default limit = HA_POS_ERROR */ + offset_limit= 0; /* denotes the default offset = 0 */ with_sum_func= 0; } @@ -1363,7 +1364,7 @@ ulong st_select_lex_node::get_table_join_options() */ bool st_select_lex::test_limit() { - if (select_limit != HA_POS_ERROR) + if (select_limit != 0) { my_error(ER_NOT_SUPPORTED_YET, MYF(0), "LIMIT & IN/ALL/ANY/SOME subquery"); @@ -1551,24 +1552,20 @@ void st_select_lex::print_limit(THD *thd, String *str) item->substype() == Item_subselect::IN_SUBS || item->substype() == Item_subselect::ALL_SUBS)) { - DBUG_ASSERT(!item->fixed || select_limit == 1L && offset_limit == 0L); + DBUG_ASSERT(!item->fixed || + select_limit->val_int() == LL(1) && offset_limit == 0); return; } if (explicit_limit) { str->append(" limit ", 7); - char buff[20]; - // latin1 is good enough for numbers - String st(buff, sizeof(buff), &my_charset_latin1); - st.set((ulonglong)select_limit, &my_charset_latin1); - str->append(st); if (offset_limit) { + offset_limit->print(str); str->append(','); - st.set((ulonglong)select_limit, &my_charset_latin1); - str->append(st); } + select_limit->print(str); } } @@ -1619,7 +1616,7 @@ bool st_lex::can_be_merged() select_lex.with_sum_func == 0 && select_lex.table_list.elements >= 1 && !(select_lex.options & SELECT_DISTINCT) && - select_lex.select_limit == HA_POS_ERROR); + select_lex.select_limit == 0); } @@ -1756,11 +1753,15 @@ bool st_lex::need_correct_ident() values - SELECT_LEX with initial values for counters */ -void st_select_lex_unit::set_limit(SELECT_LEX *values) +void st_select_lex_unit::set_limit(SELECT_LEX *sl) { - offset_limit_cnt= values->offset_limit; - select_limit_cnt= values->select_limit+values->offset_limit; - if (select_limit_cnt < values->select_limit) + ulonglong select_limit_val; + + select_limit_val= sl->select_limit ? sl->select_limit->val_uint() : + HA_POS_ERROR; + offset_limit_cnt= sl->offset_limit ? sl->offset_limit->val_uint() : ULL(0); + select_limit_cnt= select_limit_val + offset_limit_cnt; + if (select_limit_cnt < select_limit_val) select_limit_cnt= HA_POS_ERROR; // no limit } diff --git a/sql/sql_lex.h b/sql/sql_lex.h index e297d303f3d..5022392565c 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -488,7 +488,7 @@ public: List expr_list; List when_list; /* WHEN clause (expression) */ SQL_LIST *gorder_list; - ha_rows select_limit, offset_limit; /* LIMIT clause parameters */ + Item *select_limit, *offset_limit; /* LIMIT clause parameters */ // Arrays of pointers to top elements of all_fields list Item **ref_pointer_array; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index a9e68de3705..1a3a03012eb 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2351,7 +2351,8 @@ mysql_execute_command(THD *thd) { SELECT_LEX *param= lex->unit.global_parameters; if (!param->explicit_limit) - param->select_limit= thd->variables.select_limit; + param->select_limit= + new Item_int((ulonglong)thd->variables.select_limit); } select_result *result=lex->result; @@ -3146,13 +3147,15 @@ unsent_create_error: DBUG_ASSERT(first_table == all_tables && first_table != 0); if (update_precheck(thd, all_tables)) break; + DBUG_ASSERT(select_lex->offset_limit == 0); + unit->set_limit(select_lex); res= (result= mysql_update(thd, all_tables, select_lex->item_list, lex->value_list, select_lex->where, select_lex->order_list.elements, (ORDER *) select_lex->order_list.first, - select_lex->select_limit, + unit->select_limit_cnt, lex->duplicates, lex->ignore)); /* mysql_update return 2 if we need to switch to multi-update */ if (result != 2) @@ -3258,9 +3261,11 @@ unsent_create_error: DBUG_ASSERT(first_table == all_tables && first_table != 0); if ((res= delete_precheck(thd, all_tables))) break; + DBUG_ASSERT(select_lex->offset_limit == 0); + unit->set_limit(select_lex); res = mysql_delete(thd, all_tables, select_lex->where, &select_lex->order_list, - select_lex->select_limit, select_lex->options); + unit->select_limit_cnt, select_lex->options); break; } case SQLCOM_DELETE_MULTI: @@ -3847,9 +3852,10 @@ unsent_create_error: */ if (check_db_used(thd, all_tables)) goto error; + unit->set_limit(select_lex); res= mysql_ha_read(thd, first_table, lex->ha_read_mode, lex->ident.str, lex->insert_list, lex->ha_rkey_mode, select_lex->where, - select_lex->select_limit, select_lex->offset_limit); + unit->select_limit_cnt, unit->offset_limit_cnt); break; case SQLCOM_BEGIN: @@ -5130,7 +5136,6 @@ mysql_init_select(LEX *lex) { SELECT_LEX *select_lex= lex->current_select; select_lex->init_select(); - select_lex->select_limit= HA_POS_ERROR; lex->orig_sql_command= SQLCOM_END; lex->wild= 0; if (select_lex == &lex->select_lex) @@ -5145,6 +5150,7 @@ bool mysql_new_select(LEX *lex, bool move_down) { SELECT_LEX *select_lex; + THD *thd; DBUG_ENTER("mysql_new_select"); if (!(select_lex= new(lex->thd->mem_root) SELECT_LEX())) @@ -5194,7 +5200,7 @@ mysql_new_select(LEX *lex, bool move_down) fake->select_number= INT_MAX; fake->make_empty_select(); fake->linkage= GLOBAL_OPTIONS_TYPE; - fake->select_limit= HA_POS_ERROR; + fake->select_limit= 0; } } @@ -5242,8 +5248,8 @@ void mysql_init_multi_delete(LEX *lex) { lex->sql_command= SQLCOM_DELETE_MULTI; mysql_init_select(lex); - lex->select_lex.select_limit= lex->unit.select_limit_cnt= - HA_POS_ERROR; + lex->select_lex.select_limit= 0; + lex->unit.select_limit_cnt= HA_POS_ERROR; lex->select_lex.table_list.save_and_clear(&lex->auxilliary_table_list); lex->lock_option= using_update_log ? TL_READ_NO_INSERT : TL_READ; lex->query_tables= 0; @@ -6757,8 +6763,7 @@ bool multi_update_precheck(THD *thd, TABLE_LIST *tables) if (select_lex->order_list.elements) msg= "ORDER BY"; - else if (select_lex->select_limit && select_lex->select_limit != - HA_POS_ERROR) + else if (select_lex->select_limit) msg= "LIMIT"; if (msg) { diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 71cebb61ae6..0b5ac63dd0b 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -1316,6 +1316,7 @@ bool mysql_show_binlog_events(THD* thd) if (mysql_bin_log.is_open()) { LEX_MASTER_INFO *lex_mi= &thd->lex->mi; + SELECT_LEX_UNIT *unit= &thd->lex->unit; ha_rows event_count, limit_start, limit_end; my_off_t pos = max(BIN_LOG_HEADER_SIZE, lex_mi->pos); // user-friendly char search_file_name[FN_REFLEN], *name; @@ -1324,8 +1325,9 @@ bool mysql_show_binlog_events(THD* thd) LOG_INFO linfo; Log_event* ev; - limit_start= thd->lex->current_select->offset_limit; - limit_end= thd->lex->current_select->select_limit + limit_start; + unit->set_limit(thd->lex->current_select); + limit_start= unit->offset_limit_cnt; + limit_end= unit->select_limit_cnt; name= search_file_name; if (log_file_name) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 27ef3fcea6f..d07dd523f75 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -10051,7 +10051,7 @@ end_send(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), { join->do_send_rows= 0; if (join->unit->fake_select_lex) - join->unit->fake_select_lex->select_limit= HA_POS_ERROR; + join->unit->fake_select_lex->select_limit= 0; DBUG_RETURN(NESTED_LOOP_OK); } } diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 56401ced67c..912636b6cf3 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -448,7 +448,7 @@ bool st_select_lex_unit::exec() table->no_keyread=1; } res= sl->join->error; - offset_limit_cnt= sl->offset_limit; + offset_limit_cnt= sl->offset_limit ? sl->offset_limit->val_uint() : 0; if (!res) { examined_rows+= thd->examined_row_count; diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 289bf9d28a3..9f0c3260d8f 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -1000,8 +1000,9 @@ bool check_key_in_view(THD *thd, TABLE_LIST *view) we do not support updatable UNIONs in VIEW, so we can check just limit of LEX::select_lex */ - if ((!view->view && !view->belong_to_view) || thd->lex->sql_command == SQLCOM_INSERT || - thd->lex->select_lex.select_limit == HA_POS_ERROR) + if ((!view->view && !view->belong_to_view) || + thd->lex->sql_command == SQLCOM_INSERT || + thd->lex->select_lex.select_limit == 0) DBUG_RETURN(FALSE); /* it is normal table or query without LIMIT */ table= view->table; if (view->belong_to_view) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 2f584bc6b4e..47a2b098538 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -721,7 +721,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); signed_literal now_or_signed_literal opt_escape sp_opt_default simple_ident_nospvar simple_ident_q - field_or_var + field_or_var limit_option %type NUM_literal @@ -5542,8 +5542,8 @@ opt_limit_clause_init: { LEX *lex= Lex; SELECT_LEX *sel= lex->current_select; - sel->offset_limit= 0L; - sel->select_limit= HA_POS_ERROR; + sel->offset_limit= 0; + sel->select_limit= 0; } | limit_clause {} ; @@ -5558,21 +5558,21 @@ limit_clause: ; limit_options: - ulong_num + limit_option { SELECT_LEX *sel= Select; sel->select_limit= $1; - sel->offset_limit= 0L; + sel->offset_limit= 0; sel->explicit_limit= 1; } - | ulong_num ',' ulong_num + | limit_option ',' limit_option { SELECT_LEX *sel= Select; sel->select_limit= $3; sel->offset_limit= $1; sel->explicit_limit= 1; } - | ulong_num OFFSET_SYM ulong_num + | limit_option OFFSET_SYM limit_option { SELECT_LEX *sel= Select; sel->select_limit= $1; @@ -5580,18 +5580,23 @@ limit_options: sel->explicit_limit= 1; } ; +limit_option: + param_marker + | ULONGLONG_NUM { $$= new Item_uint($1.str, $1.length); } + | LONG_NUM { $$= new Item_uint($1.str, $1.length); } + | NUM { $$= new Item_uint($1.str, $1.length); } delete_limit_clause: /* empty */ { LEX *lex=Lex; - lex->current_select->select_limit= HA_POS_ERROR; + lex->current_select->select_limit= 0; } - | LIMIT ulonglong_num + | LIMIT limit_option { SELECT_LEX *sel= Select; - sel->select_limit= (ha_rows) $2; + sel->select_limit= $2; sel->explicit_limit= 1; }; @@ -7942,8 +7947,8 @@ handler: LEX *lex=Lex; lex->sql_command = SQLCOM_HA_READ; lex->ha_rkey_mode= HA_READ_KEY_EXACT; /* Avoid purify warnings */ - lex->current_select->select_limit= 1; - lex->current_select->offset_limit= 0L; + lex->current_select->select_limit= new Item_int(1); + lex->current_select->offset_limit= 0; if (!lex->current_select->add_table_to_list(lex->thd, $2, 0, 0)) YYABORT; } From 6cc77486b7862f0ef47a021fe2bc92c5e5754448 Mon Sep 17 00:00:00 2001 From: "igor@rurik.mysql.com" <> Date: Tue, 7 Jun 2005 04:21:19 -0700 Subject: [PATCH 07/16] item_buff.cc: Removed an extra space char. --- sql/item_buff.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/item_buff.cc b/sql/item_buff.cc index 2324205eb65..f5e77862e1d 100644 --- a/sql/item_buff.cc +++ b/sql/item_buff.cc @@ -43,7 +43,7 @@ Item_buff::~Item_buff() {} */ Item_str_buff::Item_str_buff(THD *thd, Item *arg) - :item(arg), value(min(arg->max_length, thd->variables. max_sort_length)) + :item(arg), value(min(arg->max_length, thd->variables.max_sort_length)) {} bool Item_str_buff::cmp(void) From 65d79b9d83f4f7f1ea19bd62714e2815d4d6f7cc Mon Sep 17 00:00:00 2001 From: "petr@mysql.com" <> Date: Tue, 7 Jun 2005 15:47:02 +0400 Subject: [PATCH 08/16] post-review fixes --- server-tools/instance-manager/commands.cc | 4 -- server-tools/instance-manager/instance.cc | 4 +- server-tools/instance-manager/instance.h | 2 +- server-tools/instance-manager/instance_map.cc | 4 +- .../instance-manager/instance_options.cc | 42 +++++++++-------- .../instance-manager/instance_options.h | 6 ++- server-tools/instance-manager/listener.cc | 2 +- server-tools/instance-manager/log.cc | 2 +- server-tools/instance-manager/parse_output.cc | 45 +++++++++---------- server-tools/instance-manager/parse_output.h | 6 ++- 10 files changed, 60 insertions(+), 57 deletions(-) diff --git a/server-tools/instance-manager/commands.cc b/server-tools/instance-manager/commands.cc index 737eb47bdf6..b5d88873054 100644 --- a/server-tools/instance-manager/commands.cc +++ b/server-tools/instance-manager/commands.cc @@ -644,10 +644,6 @@ Set_option::Set_option(Instance_map *instance_map_arg, { strmake(option, option_arg, option_len_arg); strmake(option_value, option_value_arg, option_value_len_arg); -/* strncpy(option, option_arg, option_len_arg); - option[option_len_arg]= 0; - strncpy(option_value, option_value_arg, option_value_len_arg); - option_value[option_value_len_arg]= 0; */ } else { diff --git a/server-tools/instance-manager/instance.cc b/server-tools/instance-manager/instance.cc index 615f16f9e22..2b25c74439e 100644 --- a/server-tools/instance-manager/instance.cc +++ b/server-tools/instance-manager/instance.cc @@ -326,8 +326,8 @@ int Instance::init(const char *name_arg) int Instance::complete_initialization(Instance_map *instance_map_arg, const char *mysqld_path, - int only_instance) + uint instance_type) { instance_map= instance_map_arg; - return options.complete_initialization(mysqld_path, only_instance); + return options.complete_initialization(mysqld_path, instance_type); } diff --git a/server-tools/instance-manager/instance.h b/server-tools/instance-manager/instance.h index 14ef5cfcfb9..39a2b8ee846 100644 --- a/server-tools/instance-manager/instance.h +++ b/server-tools/instance-manager/instance.h @@ -33,7 +33,7 @@ public: ~Instance(); int init(const char *name); int complete_initialization(Instance_map *instance_map_arg, - const char *mysqld_path, int only_instance= 0); + const char *mysqld_path, uint instance_type); bool is_running(); int start(); diff --git a/server-tools/instance-manager/instance_map.cc b/server-tools/instance-manager/instance_map.cc index 792ffff5fb6..fa8a5d58114 100644 --- a/server-tools/instance-manager/instance_map.cc +++ b/server-tools/instance-manager/instance_map.cc @@ -202,14 +202,14 @@ int Instance_map::complete_initialization() hash_free should handle it's deletion => goto err, not err_instance. */ - if (instance->complete_initialization(this, mysqld_path, 1)) + if (instance->complete_initialization(this, mysqld_path, DEFAULT_SINGLE_INSTANCE)) goto err; } else while (i < hash.records) { instance= (Instance *) hash_element(&hash, i); - if (instance->complete_initialization(this, mysqld_path)) + if (instance->complete_initialization(this, mysqld_path, USUAL_INSTANCE)) goto err; i++; } diff --git a/server-tools/instance-manager/instance_options.cc b/server-tools/instance-manager/instance_options.cc index c6b9141ece4..7c68ccc7207 100644 --- a/server-tools/instance-manager/instance_options.cc +++ b/server-tools/instance-manager/instance_options.cc @@ -95,7 +95,7 @@ int Instance_options::get_default_option(char *result, size_t result_len, /* +2 eats first "--" from the option string (E.g. "--datadir") */ rc= parse_output_and_get_value(cmd.buffer, option_name + 2, - result, result_len); + result, result_len, GET_VALUE); return rc; err: @@ -121,9 +121,8 @@ err: int Instance_options::fill_instance_version() { enum { MAX_VERSION_STRING_LENGTH= 160 }; - enum { RETURN_LINE= 1 }; char result[MAX_VERSION_STRING_LENGTH]; - char version_option[]= " --version"; + char version_option[]= " --no-defaults --version"; int rc= 1; Buffer cmd(mysqld_path_len + sizeof(version_option)); @@ -133,7 +132,7 @@ int Instance_options::fill_instance_version() rc= parse_output_and_get_value(cmd.buffer, mysqld_path, result, MAX_VERSION_STRING_LENGTH, - RETURN_LINE); + GET_LINE); if (*result != '\0') { @@ -198,8 +197,8 @@ int Instance_options::fill_log_options() goto err; } else /* below is safe, as --datadir always has a value */ - strncpy(datadir, strchr(mysqld_datadir, '=') + 1, - MAX_LOG_OPTION_LENGTH); + strmake(datadir, strchr(mysqld_datadir, '=') + 1, + MAX_LOG_OPTION_LENGTH - 1); if (gethostname(hostname,sizeof(hostname)-1) < 0) strmov(hostname, "mysql"); @@ -232,7 +231,7 @@ int Instance_options::fill_log_options() if ((MAX_LOG_OPTION_LENGTH - strlen(full_name)) > strlen(log_files->default_suffix)) { - strcpy(full_name + strlen(full_name), + strmov(full_name + strlen(full_name), log_files->default_suffix); } else @@ -338,7 +337,7 @@ pid_t Instance_options::get_pid() int Instance_options::complete_initialization(const char *default_path, - int only_instance) + uint instance_type) { const char *tmp; @@ -369,18 +368,23 @@ int Instance_options::complete_initialization(const char *default_path, found, we would like to model mysqld pid file values. */ if (!gethostname(hostname, sizeof(hostname) - 1)) - (only_instance == 0) ? - strxnmov(pidfilename, MAX_PATH_LEN - 1, "--pid-file=", instance_name, "-", - hostname, ".pid", NullS): - strxnmov(pidfilename, MAX_PATH_LEN - 1, "--pid-file=", hostname, - ".pid", NullS); - + { + if (instance_type & DEFAULT_SINGLE_INSTANCE) + strxnmov(pidfilename, MAX_PATH_LEN - 1, "--pid-file=", instance_name, "-", + hostname, ".pid", NullS); + else + strxnmov(pidfilename, MAX_PATH_LEN - 1, "--pid-file=", hostname, + ".pid", NullS); + } else - (only_instance == 0) ? - strxnmov(pidfilename, MAX_PATH_LEN - 1, "--pid-file=", instance_name, - ".pid", NullS): - strxnmov(pidfilename, MAX_PATH_LEN - 1, "--pid-file=", "mysql", - ".pid", NullS); + { + if (instance_type & DEFAULT_SINGLE_INSTANCE) + strxnmov(pidfilename, MAX_PATH_LEN - 1, "--pid-file=", instance_name, + ".pid", NullS); + else + strxnmov(pidfilename, MAX_PATH_LEN - 1, "--pid-file=", "mysql", + ".pid", NullS); + } add_option(pidfilename); } diff --git a/server-tools/instance-manager/instance_options.h b/server-tools/instance-manager/instance_options.h index 0d2c32fae66..e2048c4c548 100644 --- a/server-tools/instance-manager/instance_options.h +++ b/server-tools/instance-manager/instance_options.h @@ -34,6 +34,8 @@ don't have to synchronize between threads. */ +enum { USUAL_INSTANCE= 0, DEFAULT_SINGLE_INSTANCE }; + class Instance_options { public: @@ -45,7 +47,7 @@ public: {} ~Instance_options(); /* fills in argv */ - int complete_initialization(const char *default_path, int only_instance); + int complete_initialization(const char *default_path, uint instance_type); int add_option(const char* option); int init(const char *instance_name_arg); @@ -66,7 +68,7 @@ public: char **argv; /* Here we cache the version string, obtained from mysqld --version. - In the case when mysqld binary is not found we get "unknown" here. + In the case when mysqld binary is not found we get NULL here. */ const char *mysqld_version; /* We need the some options, so we store them as a separate pointers */ diff --git a/server-tools/instance-manager/listener.cc b/server-tools/instance-manager/listener.cc index 98f5b64ca92..4aed18c753d 100644 --- a/server-tools/instance-manager/listener.cc +++ b/server-tools/instance-manager/listener.cc @@ -163,7 +163,7 @@ void Listener_thread::run() unix_socket_address.sun_family= AF_UNIX; strmake(unix_socket_address.sun_path, options.socket_file_name, sizeof(unix_socket_address.sun_path)); - unlink(unix_socket_address.sun_path); // in case we have stale socket file + unlink(unix_socket_address.sun_path); /* in case we have stale socket file */ { /* diff --git a/server-tools/instance-manager/log.cc b/server-tools/instance-manager/log.cc index 88d777eeeb6..3c18d2816bf 100644 --- a/server-tools/instance-manager/log.cc +++ b/server-tools/instance-manager/log.cc @@ -76,7 +76,7 @@ static inline void log(FILE *file, const char *format, va_list args) if (buff_msg == 0) { strmake(buff_stack, "log(): message is too big, my_malloc() failed", - sizeof(buff_stack)); + sizeof(buff_stack) - 1); buff_msg= buff_stack; break; } diff --git a/server-tools/instance-manager/parse_output.cc b/server-tools/instance-manager/parse_output.cc index 8e083b0cd0d..f551e7b525e 100644 --- a/server-tools/instance-manager/parse_output.cc +++ b/server-tools/instance-manager/parse_output.cc @@ -16,10 +16,11 @@ #include #include "parse.h" +#include "parse_output.h" #include #include -#include +#include /* @@ -28,17 +29,17 @@ SYNOPSYS parse_output_and_get_value() - command the command to execue with popen. - word the word to look for (usually an option name) - result the buffer to store the next word (option value) - result_len self-explanatory - get_all_line flag, which is set if we want to get all the line after - the matched word. + command the command to execue with popen. + word the word to look for (usually an option name) + result the buffer to store the next word (option value) + input_buffer_len self-explanatory + flag this equals to GET_LINE if we want to get all the line after + the matched word and GET_VALUE otherwise. DESCRIPTION Parse output of the "command". Find the "word" and return the next one - if get_all_line is 0. Return the rest of the parsed string otherwise. + if flag is GET_VALUE. Return the rest of the parsed string otherwise. RETURN 0 - ok @@ -46,8 +47,8 @@ */ int parse_output_and_get_value(const char *command, const char *word, - char *result, size_t result_len, - int get_all_line) + char *result, size_t input_buffer_len, + uint flag) { FILE *output; uint wordlen; @@ -68,7 +69,7 @@ int parse_output_and_get_value(const char *command, const char *word, while (fgets(linebuf, sizeof(linebuf) - 1, output)) { - uint lineword_len= 0; + uint found_word_len= 0; char *linep= linebuf; linebuf[sizeof(linebuf) - 1]= '\0'; /* safety */ @@ -77,26 +78,24 @@ int parse_output_and_get_value(const char *command, const char *word, Get the word, which might contain non-alphanumeric characters. (Usually these are '/', '-' and '.' in the path expressions and filenames) */ - get_word((const char **) &linep, &lineword_len, NONSPACE); + get_word((const char **) &linep, &found_word_len, NONSPACE); if (!strncmp(word, linep, wordlen)) { /* - If we have found the word, return the next one. This is usually - an option value. + If we have found the word, return the next one (this is usually + an option value) or the whole line (if flag) */ - linep+= lineword_len; /* swallow the previous one */ - if (!get_all_line) + linep+= found_word_len; /* swallow the previous one */ + if (flag & GET_VALUE) /* not GET_LINE */ { - get_word((const char **) &linep, &lineword_len, NONSPACE); - if (result_len <= lineword_len) + get_word((const char **) &linep, &found_word_len, NONSPACE); + if (input_buffer_len <= found_word_len) goto err; - strncpy(result, linep, lineword_len); - result[lineword_len]= '\0'; + strmake(result, linep, found_word_len); } - else + else /* currently there are only two options */ { - strncpy(result, linep, result_len); - result[result_len]= '\0'; /* safety */ + strmake(result, linep, input_buffer_len - 1); } goto pclose; } diff --git a/server-tools/instance-manager/parse_output.h b/server-tools/instance-manager/parse_output.h index e0161cf29e3..82cc83340c2 100644 --- a/server-tools/instance-manager/parse_output.h +++ b/server-tools/instance-manager/parse_output.h @@ -16,8 +16,10 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +enum { GET_VALUE= 1, GET_LINE }; + int parse_output_and_get_value(const char *command, const char *word, - char *result, size_t result_len, - int get_all_line= 0); + char *result, size_t input_buffer_len, + uint flag); #endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_PARSE_OUTPUT_H */ From 1c725ff797a7453d924aa56bafa4e8f5b163fc7c Mon Sep 17 00:00:00 2001 From: "monty@mysql.com" <> Date: Tue, 7 Jun 2005 15:09:49 +0300 Subject: [PATCH 09/16] Revert Bar's fix as this causes changes in the key tree that could cause incompatibilites Fix instead wrong call to ha_key_cmp This is related to bug #10741 Inserting double value into utf8 column crashes server --- myisam/mi_key.c | 6 +++--- myisam/mi_rnext_same.c | 4 ++-- mysql-test/r/ctype_utf8.result | 3 +++ mysql-test/t/ctype_utf8.test | 1 + 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/myisam/mi_key.c b/myisam/mi_key.c index 6a8d88f1117..9df22889b22 100644 --- a/myisam/mi_key.c +++ b/myisam/mi_key.c @@ -84,8 +84,7 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key, pos= (byte*) record+keyseg->start; if (keyseg->flag & HA_SPACE_PACK) { - FIX_LENGTH(cs, pos, length, char_length); - end= pos + char_length; + end= pos + length; if (type != HA_KEYTYPE_NUM) { while (end > pos && end[-1] == ' ') @@ -96,7 +95,8 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key, while (pos < end && pos[0] == ' ') pos++; } - char_length= (uint) (end - pos); + length=(uint) (end-pos); + FIX_LENGTH(cs, pos, length, char_length); store_key_length_inc(key,char_length); memcpy((byte*) key,(byte*) pos,(size_t) char_length); key+=char_length; diff --git a/myisam/mi_rnext_same.c b/myisam/mi_rnext_same.c index 06408f57a3f..4d770258a72 100644 --- a/myisam/mi_rnext_same.c +++ b/myisam/mi_rnext_same.c @@ -68,8 +68,8 @@ int mi_rnext_same(MI_INFO *info, byte *buf) info->lastkey_length,SEARCH_BIGGER, info->s->state.key_root[inx]))) break; - if (ha_key_cmp(keyinfo->seg,info->lastkey2,info->lastkey, - info->last_rkey_length, SEARCH_FIND, ¬_used)) + if (ha_key_cmp(keyinfo->seg, info->lastkey, info->lastkey2, + info->last_rkey_length, SEARCH_FIND, ¬_used)) { error=1; my_errno=HA_ERR_END_OF_FILE; diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index ac421ea1717..29b18f0431c 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -901,4 +901,7 @@ insert into t1 values (2,'Durban'); select * from t1 where city = 'Durban'; id city 2 Durban +select * from t1 where city = 'Durban '; +id city +2 Durban drop table t1; diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test index a281558e5a1..3c49b2a47f7 100644 --- a/mysql-test/t/ctype_utf8.test +++ b/mysql-test/t/ctype_utf8.test @@ -744,4 +744,5 @@ create table t1 ( insert into t1 values (1,'Durban North'); insert into t1 values (2,'Durban'); select * from t1 where city = 'Durban'; +select * from t1 where city = 'Durban '; drop table t1; From d30f69ab0aa32e1f65f37992943b3942df612c75 Mon Sep 17 00:00:00 2001 From: "lenz@mysql.com" <> Date: Tue, 7 Jun 2005 14:39:00 +0200 Subject: [PATCH 10/16] - added the libndbclient static and shared libraries to the RPM (BUG 10676) --- support-files/mysql.spec.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index 3638550ff60..088fbf53698 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -331,6 +331,7 @@ fi # Save libraries (cd libmysql/.libs; tar cf $RBR/shared-libs.tar *.so*) (cd libmysql_r/.libs; tar rf $RBR/shared-libs.tar *.so*) +(cd ndb/src/.libs; tar rf $RBR/shared-libs.tar *.so*) # Now clean up make clean @@ -631,6 +632,8 @@ fi %{_libdir}/mysql/libmysqlclient_r.la %{_libdir}/mysql/libmystrings.a %{_libdir}/mysql/libmysys.a +%{_libdir}/mysql/libndbclient.a +%{_libdir}/mysql/libndbclient.la %{_libdir}/mysql/libvio.a %files shared @@ -663,6 +666,7 @@ fi * Mon Jun 06 2005 Lenz Grimmer - added mysql_client_test to the "bench" subpackage (BUG 10676) +- added the libndbclient static and shared libraries (BUG 10676) * Wed Jun 01 2005 Lenz Grimmer From d3f3cc617ddee9b6d7fea39f848d33dd5a29307a Mon Sep 17 00:00:00 2001 From: "igor@rurik.mysql.com" <> Date: Tue, 7 Jun 2005 06:34:13 -0700 Subject: [PATCH 11/16] Many files: Fixed bug #9899: erronious NOT_NULL flag for some attributes in the EXPLAIN table. --- mysql-test/r/ps_1general.result | 12 ++++++------ mysql-test/r/ps_2myisam.result | 6 +++--- mysql-test/r/ps_3innodb.result | 6 +++--- mysql-test/r/ps_4heap.result | 6 +++--- mysql-test/r/ps_5merge.result | 12 ++++++------ sql/sql_class.cc | 10 +++++++--- 6 files changed, 28 insertions(+), 24 deletions(-) diff --git a/mysql-test/r/ps_1general.result b/mysql-test/r/ps_1general.result index 68d88a454ff..db8dc2e60af 100644 --- a/mysql-test/r/ps_1general.result +++ b/mysql-test/r/ps_1general.result @@ -468,13 +468,13 @@ execute stmt1; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr def id 8 3 1 N 32929 0 63 def select_type 253 19 6 N 1 31 8 -def table 253 64 2 N 1 31 8 -def type 253 10 3 N 1 31 8 +def table 253 64 2 Y 0 31 8 +def type 253 10 3 Y 0 31 8 def possible_keys 253 4096 0 Y 0 31 8 def key 253 64 0 Y 0 31 8 def key_len 8 3 0 Y 32928 0 63 def ref 253 1024 0 Y 0 31 8 -def rows 8 10 1 N 32929 0 63 +def rows 8 10 1 Y 32928 0 63 def Extra 253 255 14 N 1 31 8 id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using filesort @@ -484,13 +484,13 @@ execute stmt1 using @arg00; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr def id 8 3 1 N 32929 0 63 def select_type 253 19 6 N 1 31 8 -def table 253 64 2 N 1 31 8 -def type 253 10 5 N 1 31 8 +def table 253 64 2 Y 0 31 8 +def type 253 10 5 Y 0 31 8 def possible_keys 253 4096 7 Y 0 31 8 def key 253 64 7 Y 0 31 8 def key_len 8 3 1 Y 32928 0 63 def ref 253 1024 0 Y 0 31 8 -def rows 8 10 1 N 32929 0 63 +def rows 8 10 1 Y 32928 0 63 def Extra 253 255 27 N 1 31 8 id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 3 Using where; Using filesort diff --git a/mysql-test/r/ps_2myisam.result b/mysql-test/r/ps_2myisam.result index fd17dc5b1b5..c569c9842f7 100644 --- a/mysql-test/r/ps_2myisam.result +++ b/mysql-test/r/ps_2myisam.result @@ -1151,13 +1151,13 @@ execute stmt1; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr def id 8 3 1 N 32929 0 63 def select_type 253 19 6 N 1 31 8 -def table 253 64 2 N 1 31 8 -def type 253 10 3 N 1 31 8 +def table 253 64 2 Y 0 31 8 +def type 253 10 3 Y 0 31 8 def possible_keys 253 4096 0 Y 0 31 8 def key 253 64 0 Y 0 31 8 def key_len 8 3 0 Y 32928 0 63 def ref 253 1024 0 Y 0 31 8 -def rows 8 10 1 N 32929 0 63 +def rows 8 10 1 Y 32928 0 63 def Extra 253 255 0 N 1 31 8 id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t9 ALL NULL NULL NULL NULL 2 diff --git a/mysql-test/r/ps_3innodb.result b/mysql-test/r/ps_3innodb.result index 50dc580a930..930aea2e381 100644 --- a/mysql-test/r/ps_3innodb.result +++ b/mysql-test/r/ps_3innodb.result @@ -1151,13 +1151,13 @@ execute stmt1; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr def id 8 3 1 N 32929 0 63 def select_type 253 19 6 N 1 31 8 -def table 253 64 2 N 1 31 8 -def type 253 10 3 N 1 31 8 +def table 253 64 2 Y 0 31 8 +def type 253 10 3 Y 0 31 8 def possible_keys 253 4096 0 Y 0 31 8 def key 253 64 0 Y 0 31 8 def key_len 8 3 0 Y 32928 0 63 def ref 253 1024 0 Y 0 31 8 -def rows 8 10 1 N 32929 0 63 +def rows 8 10 1 Y 32928 0 63 def Extra 253 255 0 N 1 31 8 id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t9 ALL NULL NULL NULL NULL 2 diff --git a/mysql-test/r/ps_4heap.result b/mysql-test/r/ps_4heap.result index 050a63f254c..083a4b221fe 100644 --- a/mysql-test/r/ps_4heap.result +++ b/mysql-test/r/ps_4heap.result @@ -1152,13 +1152,13 @@ execute stmt1; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr def id 8 3 1 N 32929 0 63 def select_type 253 19 6 N 1 31 8 -def table 253 64 2 N 1 31 8 -def type 253 10 3 N 1 31 8 +def table 253 64 2 Y 0 31 8 +def type 253 10 3 Y 0 31 8 def possible_keys 253 4096 0 Y 0 31 8 def key 253 64 0 Y 0 31 8 def key_len 8 3 0 Y 32928 0 63 def ref 253 1024 0 Y 0 31 8 -def rows 8 10 1 N 32929 0 63 +def rows 8 10 1 Y 32928 0 63 def Extra 253 255 0 N 1 31 8 id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t9 ALL NULL NULL NULL NULL 2 diff --git a/mysql-test/r/ps_5merge.result b/mysql-test/r/ps_5merge.result index c228ec4672f..1edd617ffc6 100644 --- a/mysql-test/r/ps_5merge.result +++ b/mysql-test/r/ps_5merge.result @@ -1194,13 +1194,13 @@ execute stmt1; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr def id 8 3 1 N 32929 0 63 def select_type 253 19 6 N 1 31 8 -def table 253 64 2 N 1 31 8 -def type 253 10 3 N 1 31 8 +def table 253 64 2 Y 0 31 8 +def type 253 10 3 Y 0 31 8 def possible_keys 253 4096 0 Y 0 31 8 def key 253 64 0 Y 0 31 8 def key_len 8 3 0 Y 32928 0 63 def ref 253 1024 0 Y 0 31 8 -def rows 8 10 1 N 32929 0 63 +def rows 8 10 1 Y 32928 0 63 def Extra 253 255 0 N 1 31 8 id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t9 ALL NULL NULL NULL NULL 2 @@ -4208,13 +4208,13 @@ execute stmt1; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr def id 8 3 1 N 32929 0 63 def select_type 253 19 6 N 1 31 8 -def table 253 64 2 N 1 31 8 -def type 253 10 3 N 1 31 8 +def table 253 64 2 Y 0 31 8 +def type 253 10 3 Y 0 31 8 def possible_keys 253 4096 0 Y 0 31 8 def key 253 64 0 Y 0 31 8 def key_len 8 3 0 Y 32928 0 63 def ref 253 1024 0 Y 0 31 8 -def rows 8 10 1 N 32929 0 63 +def rows 8 10 1 Y 32928 0 63 def Extra 253 255 0 N 1 31 8 id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t9 ALL NULL NULL NULL NULL 2 diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 805db107370..e845769d7ad 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -667,8 +667,10 @@ int THD::send_explain_fields(select_result *result) CHARSET_INFO *cs= system_charset_info; field_list.push_back(new Item_return_int("id",3, MYSQL_TYPE_LONGLONG)); field_list.push_back(new Item_empty_string("select_type", 19, cs)); - field_list.push_back(new Item_empty_string("table", NAME_LEN, cs)); - field_list.push_back(new Item_empty_string("type", 10, cs)); + field_list.push_back(item= new Item_empty_string("table", NAME_LEN, cs)); + item->maybe_null= 1; + field_list.push_back(item= new Item_empty_string("type", 10, cs)); + item->maybe_null= 1; field_list.push_back(item=new Item_empty_string("possible_keys", NAME_LEN*MAX_KEY, cs)); item->maybe_null=1; @@ -680,7 +682,9 @@ int THD::send_explain_fields(select_result *result) field_list.push_back(item=new Item_empty_string("ref", NAME_LEN*MAX_REF_PARTS, cs)); item->maybe_null=1; - field_list.push_back(new Item_return_int("rows", 10, MYSQL_TYPE_LONGLONG)); + field_list.push_back(item= new Item_return_int("rows", 10, + MYSQL_TYPE_LONGLONG)); + item->maybe_null= 1; field_list.push_back(new Item_empty_string("Extra", 255, cs)); return (result->send_fields(field_list,1)); } From a2331d37b6c997e51801a8381a31c3f17a6efde4 Mon Sep 17 00:00:00 2001 From: "petr@mysql.com" <> Date: Tue, 7 Jun 2005 17:57:20 +0400 Subject: [PATCH 12/16] several fixes to the previous patch --- server-tools/instance-manager/instance_options.cc | 10 +++++----- server-tools/instance-manager/instance_options.h | 3 ++- server-tools/instance-manager/parse_output.cc | 2 +- server-tools/instance-manager/parse_output.h | 3 ++- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/server-tools/instance-manager/instance_options.cc b/server-tools/instance-manager/instance_options.cc index 7c68ccc7207..0ae364e5b2d 100644 --- a/server-tools/instance-manager/instance_options.cc +++ b/server-tools/instance-manager/instance_options.cc @@ -370,19 +370,19 @@ int Instance_options::complete_initialization(const char *default_path, if (!gethostname(hostname, sizeof(hostname) - 1)) { if (instance_type & DEFAULT_SINGLE_INSTANCE) - strxnmov(pidfilename, MAX_PATH_LEN - 1, "--pid-file=", instance_name, "-", - hostname, ".pid", NullS); - else strxnmov(pidfilename, MAX_PATH_LEN - 1, "--pid-file=", hostname, ".pid", NullS); + else + strxnmov(pidfilename, MAX_PATH_LEN - 1, "--pid-file=", instance_name, + "-", hostname, ".pid", NullS); } else { if (instance_type & DEFAULT_SINGLE_INSTANCE) - strxnmov(pidfilename, MAX_PATH_LEN - 1, "--pid-file=", instance_name, + strxnmov(pidfilename, MAX_PATH_LEN - 1, "--pid-file=", "mysql", ".pid", NullS); else - strxnmov(pidfilename, MAX_PATH_LEN - 1, "--pid-file=", "mysql", + strxnmov(pidfilename, MAX_PATH_LEN - 1, "--pid-file=", instance_name, ".pid", NullS); } diff --git a/server-tools/instance-manager/instance_options.h b/server-tools/instance-manager/instance_options.h index e2048c4c548..9dac8b39bdc 100644 --- a/server-tools/instance-manager/instance_options.h +++ b/server-tools/instance-manager/instance_options.h @@ -34,7 +34,8 @@ don't have to synchronize between threads. */ -enum { USUAL_INSTANCE= 0, DEFAULT_SINGLE_INSTANCE }; +#define USUAL_INSTANCE 0 +#define DEFAULT_SINGLE_INSTANCE 1 class Instance_options { diff --git a/server-tools/instance-manager/parse_output.cc b/server-tools/instance-manager/parse_output.cc index f551e7b525e..e83a75c6778 100644 --- a/server-tools/instance-manager/parse_output.cc +++ b/server-tools/instance-manager/parse_output.cc @@ -86,7 +86,7 @@ int parse_output_and_get_value(const char *command, const char *word, an option value) or the whole line (if flag) */ linep+= found_word_len; /* swallow the previous one */ - if (flag & GET_VALUE) /* not GET_LINE */ + if (flag & GET_VALUE) { get_word((const char **) &linep, &found_word_len, NONSPACE); if (input_buffer_len <= found_word_len) diff --git a/server-tools/instance-manager/parse_output.h b/server-tools/instance-manager/parse_output.h index 82cc83340c2..6a84fabbf17 100644 --- a/server-tools/instance-manager/parse_output.h +++ b/server-tools/instance-manager/parse_output.h @@ -16,7 +16,8 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -enum { GET_VALUE= 1, GET_LINE }; +#define GET_VALUE 1 +#define GET_LINE 2 int parse_output_and_get_value(const char *command, const char *word, char *result, size_t input_buffer_len, From 75ffe152d4b3a24c5d6af2ee8460440f98b585a5 Mon Sep 17 00:00:00 2001 From: "igor@rurik.mysql.com" <> Date: Tue, 7 Jun 2005 07:48:56 -0700 Subject: [PATCH 13/16] sql_yacc.yy: Added missing ';'. --- sql/sql_yacc.yy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index f84fc6ba33a..e0529da9302 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -5607,7 +5607,7 @@ limit_option: | ULONGLONG_NUM { $$= new Item_uint($1.str, $1.length); } | LONG_NUM { $$= new Item_uint($1.str, $1.length); } | NUM { $$= new Item_uint($1.str, $1.length); } - + ; delete_limit_clause: /* empty */ From 85648050af2565ad5baa785f5c2c0f58528cb1f6 Mon Sep 17 00:00:00 2001 From: "paul@frost.snake.net" <> Date: Tue, 7 Jun 2005 10:03:09 -0500 Subject: [PATCH 14/16] Typo in help message. --- sql/mysqld.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index a0c35b58a4d..7d7782041ca 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -5372,7 +5372,7 @@ The minimum value for this variable is 4096.", (gptr*) &myisam_data_pointer_size, 0, GET_ULONG, REQUIRED_ARG, 6, 2, 8, 0, 1, 0}, {"myisam_max_extra_sort_file_size", OPT_MYISAM_MAX_EXTRA_SORT_FILE_SIZE, - "Depricated option", + "Deprecated option", (gptr*) &global_system_variables.myisam_max_extra_sort_file_size, (gptr*) &max_system_variables.myisam_max_extra_sort_file_size, 0, GET_ULL, REQUIRED_ARG, (ulonglong) MI_MAX_TEMP_LENGTH, From bccd45ca0371f3634fabc10bb57b6446b9508510 Mon Sep 17 00:00:00 2001 From: "joerg@mysql.com" <> Date: Tue, 7 Jun 2005 19:28:43 +0200 Subject: [PATCH 15/16] Builds of 5.0.7 have begun, so anything added into this tree here will go into 5.0.8. --- configure.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index 3e196cf8507..f761c5535f6 100644 --- a/configure.in +++ b/configure.in @@ -6,7 +6,7 @@ AC_PREREQ(2.50)dnl Minimum Autoconf version required. AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # Don't forget to also update the NDB lines below. -AM_INIT_AUTOMAKE(mysql, 5.0.7-beta) +AM_INIT_AUTOMAKE(mysql, 5.0.8-beta) AM_CONFIG_HEADER(config.h) PROTOCOL_VERSION=10 @@ -17,7 +17,7 @@ SHARED_LIB_VERSION=14:0:0 # ndb version NDB_VERSION_MAJOR=5 NDB_VERSION_MINOR=0 -NDB_VERSION_BUILD=7 +NDB_VERSION_BUILD=8 NDB_VERSION_STATUS="beta" # Set all version vars based on $VERSION. How do we do this more elegant ? From 8fd88c144002936e41563f50ac137ab545eda1d3 Mon Sep 17 00:00:00 2001 From: "tulin@dl145b.mysql.com" <> Date: Tue, 7 Jun 2005 23:53:18 +0200 Subject: [PATCH 16/16] ps_6bdb.result, ps_7ndb.result: fixed result files as someone did not run bdb+ndb --- mysql-test/r/ps_6bdb.result | 6 +++--- mysql-test/r/ps_7ndb.result | 17 ++++++++++------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/mysql-test/r/ps_6bdb.result b/mysql-test/r/ps_6bdb.result index 03b155c6fa4..92399c3b3b9 100644 --- a/mysql-test/r/ps_6bdb.result +++ b/mysql-test/r/ps_6bdb.result @@ -1152,13 +1152,13 @@ execute stmt1; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr def id 8 3 1 N 32929 0 63 def select_type 253 19 6 N 1 31 8 -def table 253 64 2 N 1 31 8 -def type 253 10 3 N 1 31 8 +def table 253 64 2 Y 0 31 8 +def type 253 10 3 Y 0 31 8 def possible_keys 253 4096 0 Y 0 31 8 def key 253 64 0 Y 0 31 8 def key_len 253 4096 0 Y 128 31 63 def ref 253 1024 0 Y 0 31 8 -def rows 8 10 1 N 32929 0 63 +def rows 8 10 1 Y 32928 0 63 def Extra 253 255 0 N 1 31 8 id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t9 ALL NULL NULL NULL NULL 3 diff --git a/mysql-test/r/ps_7ndb.result b/mysql-test/r/ps_7ndb.result index 3b071d70b93..c7dabc2016d 100644 --- a/mysql-test/r/ps_7ndb.result +++ b/mysql-test/r/ps_7ndb.result @@ -1,4 +1,6 @@ -use test; drop table if exists t1, t9 ; create table t1 +use test; +drop table if exists t1, t9 ; +create table t1 ( a int, b varchar(30), primary key(a) @@ -442,9 +444,10 @@ limit 1 '; execute stmt1 ; a b 1 one -prepare stmt1 from ' select a,b from t1 -limit ? '; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 2 +prepare stmt1 from ' select a,b from t1 limit ? '; +execute stmt1 using @arg00; +a b +3 three set @arg00='b' ; set @arg01=0 ; set @arg02=2 ; @@ -1149,13 +1152,13 @@ execute stmt1; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr def id 8 3 1 N 32929 0 63 def select_type 253 19 6 N 1 31 8 -def table 253 64 2 N 1 31 8 -def type 253 10 3 N 1 31 8 +def table 253 64 2 Y 0 31 8 +def type 253 10 3 Y 0 31 8 def possible_keys 253 4096 0 Y 0 31 8 def key 253 64 0 Y 0 31 8 def key_len 253 4096 0 Y 128 31 63 def ref 253 1024 0 Y 0 31 8 -def rows 8 10 1 N 32929 0 63 +def rows 8 10 1 Y 32928 0 63 def Extra 253 255 0 N 1 31 8 id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t9 ALL NULL NULL NULL NULL 2