diff --git a/.bzrignore b/.bzrignore index c0bac9d05f1..7a8066fdba1 100644 --- a/.bzrignore +++ b/.bzrignore @@ -900,6 +900,7 @@ libmysql_r/.libs/libmysqlclient_r.lai libmysql_r/.libs/libmysqlclient_r.so.15 libmysql_r/.libs/libmysqlclient_r.so.15.0.0 libmysql_r/acconfig.h +libmysql_r/client_settings.h libmysql_r/conf_to_src libmysql_r/my_static.h libmysql_r/mysys_priv.h @@ -3004,4 +3005,3 @@ win/vs71cache.txt win/vs8cache.txt zlib/*.ds? zlib/*.vcproj -libmysql_r/client_settings.h diff --git a/CMakeLists.txt b/CMakeLists.txt index a06495021b3..341f8d08df2 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,6 +13,8 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +CMAKE_MINIMUM_REQUIRED(VERSION 2.4.7 FATAL_ERROR) + PROJECT(MySql) # This reads user configuration, generated by configure.js. diff --git a/Docs/INSTALL-BINARY b/Docs/INSTALL-BINARY new file mode 100644 index 00000000000..ba7e72af94d --- /dev/null +++ b/Docs/INSTALL-BINARY @@ -0,0 +1,8 @@ + +You can find information about how to install binary distributions at + + http://dev.mysql.com/doc/refman/5.0/en/quick-standard-installation.html + +The MySQL Reference Manual is also available in various formats on +http://dev.mysql.com/doc; if you're interested in the DocBook XML +sources go to http://svn.mysql.com. diff --git a/Docs/Makefile.am b/Docs/Makefile.am index e57a1abcb0c..dac256f8fd6 100644 --- a/Docs/Makefile.am +++ b/Docs/Makefile.am @@ -13,14 +13,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -noinst_SCRIPTS = generate-text-files.pl - -EXTRA_DIST = $(noinst_SCRIPTS) manual.chm mysql.info INSTALL-BINARY - -TXT_FILES= ../INSTALL-SOURCE ../INSTALL-WIN-SOURCE \ - INSTALL-BINARY ../support-files/MacOSX/ReadMe.txt - -all-local: $(TXT_FILES) +EXTRA_DIST = mysql.info INSTALL-BINARY # make sure that "make install" installs the info page, too # automake only seems to take care of this automatically, @@ -32,38 +25,5 @@ install-data-hook: $(srcdir)/mysql.info uninstall-local: @RM@ -f $(DESTDIR)$(infodir)/mysql.info -# Problems with "make distclean", works differently for make files -# generated by different versions of the automake. Some require the -# generated files explicitly in DISTCLEANFILES. -DISTCLEANFILES = $(TXT_FILES) - -# This target is not used in builds, just for convinience -CLEAN_FILES: $(TXT_FILES) - touch $(TXT_FILES) - -GT = $(srcdir)/generate-text-files.pl - -../INSTALL-SOURCE: $(srcdir)/mysql.info $(GT) - perl -w $(GT) $(srcdir)/mysql.info "installing-source" "windows-source-build" > $@ - -../INSTALL-WIN-SOURCE: $(srcdir)/mysql.info $(GT) - perl -w $(GT) $(srcdir)/mysql.info "windows-source-build" "post-installation" > $@ - -# We put the description for the binary installation here so that -# people who download source wont have to see it. It is moved up to -# the toplevel by the script that makes the binary tar files. -INSTALL-BINARY: $(srcdir)/mysql.info $(GT) - perl -w $(GT) $(srcdir)/mysql.info "installing-binary" "installing-source" > $@ - -../support-files/MacOSX/ReadMe.txt: $(srcdir)/mysql.info $(GT) - perl -w $(GT) $(srcdir)/mysql.info "mac-os-x-installation" "netware-installation" > $@ - -# Include the Windows manual.chm in source .tar.gz only if available. -# It is not in BitKeeper, but is downloaded from intranet by Bootstrap. -dist-hook: - if [ -e $(srcdir)/manual.chm ] ; then \ - cp -f $(srcdir)/manual.chm $(distdir); \ - fi - # Don't update the files from bitkeeper %::SCCS/s.% diff --git a/Docs/generate-text-files.pl b/Docs/generate-text-files.pl deleted file mode 100755 index 69e0478eb8a..00000000000 --- a/Docs/generate-text-files.pl +++ /dev/null @@ -1,58 +0,0 @@ -#!/usr/bin/perl -w -*- perl -*- -# Copyright (C) 2000, 2003, 2005 MySQL AB -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; version 2 of the License. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -# Generate text files from top directory from the manual. - -$from = shift(@ARGV); -$fnode = shift(@ARGV); -$tnode = shift(@ARGV); - -open(IN, "$from") || die "Cannot open $from: $!"; - -$in = 0; - -while () -{ - if ($in) - { - if (/Node: $tnode,/ || /\[index/) - { - $in = 0; - } - elsif (/^File: mysql.info/ || (/^/)) - { - # Just Skip node beginnings - } - else - { - print; - } - } - else - { - if (/Node: $fnode,/) - { - $in = 1; - # Skip first empty line - ; - } - } -} - -close(IN); - -die "Could not find node \"$tnode\"" if ($in == 1); -exit 0; diff --git a/Docs/manual.chm b/Docs/manual.chm deleted file mode 100644 index 28c3e1b5a86..00000000000 --- a/Docs/manual.chm +++ /dev/null @@ -1,14 +0,0 @@ - -********************************************************* - -This is a dummy placeholder file for "manual.chm" in the -MySQL source trees. - -Note, that the documentation has been moved into a separate -BitKeeper source tree named "mysqldoc" - do not attempt to edit this -file! All changes to it should be done in the mysqldoc tree. - -This dummy file is being replaced with the actual file from the -mysqldoc tree when building the official source distribution. - -********************************************************* diff --git a/Docs/mysql.info b/Docs/mysql.info index 5846d7aadf6..b2c411e51ab 100644 --- a/Docs/mysql.info +++ b/Docs/mysql.info @@ -1,27 +1,4 @@ -This is mysql.info, produced by makeinfo version 4.8 from manual.texi. -START-INFO-DIR-ENTRY -* mysql: (mysql). MySQL documentation. -END-INFO-DIR-ENTRY - - -File: mysql.info, Node: Top, Next: (dir), Prev: (dir), Up: (dir) - -This is an empty placeholder file for the MySQL manual. - -The MySQL manual is now maintained in a separate BitKeeper source tree! -Please see `http://www.mysql.com/doc/en/Installing_source_tree.html' -for more info on how to work with BitKeeper. - -This file will be replaced with the current `mysql.info' when building -the official source distribution. - -You can find a specific manual for any older version of MySQL in the -binary or source distribution for that version. - - - -Tag Table: -Node: Top166 - -End Tag Table +The MySQL Reference Manual is available in various formats on +http://dev.mysql.com/doc; if you're interested in the DocBook XML +sources go to http://svn.mysql.com. diff --git a/INSTALL-SOURCE b/INSTALL-SOURCE new file mode 100644 index 00000000000..3d9d7d41114 --- /dev/null +++ b/INSTALL-SOURCE @@ -0,0 +1,8 @@ + +You can find information about how to install from a source distributions at + + http://dev.mysql.com/doc/refman/5.0/en/installing-source.html + +The MySQL Reference Manual is also available in various formats on +http://dev.mysql.com/doc; if you're interested in the DocBook XML +sources go to http://svn.mysql.com. diff --git a/INSTALL-WIN-SOURCE b/INSTALL-WIN-SOURCE new file mode 100644 index 00000000000..2478e2cf609 --- /dev/null +++ b/INSTALL-WIN-SOURCE @@ -0,0 +1,9 @@ + +You can find information about how to install from a Windows source +distributions at + + http://dev.mysql.com/doc/refman/5.0/en/windows-source-build.html + +The MySQL Reference Manual is also available in various formats on +http://dev.mysql.com/doc; if you're interested in the DocBook XML +sources go to http://svn.mysql.com. diff --git a/client/mysql.cc b/client/mysql.cc index 1dd33593b83..b102c80655a 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -144,6 +144,7 @@ static my_bool ignore_errors=0,wait_flag=0,quick=0, show_warnings= 0, executing_query= 0, interrupted_query= 0; static my_bool debug_info_flag, debug_check_flag; static my_bool column_types_flag; +static my_bool preserve_comments= 0; static ulong opt_max_allowed_packet, opt_net_buffer_length; static uint verbose=0,opt_silent=0,opt_mysql_port=0, opt_local_infile=0; static uint my_end_arg; @@ -778,6 +779,10 @@ static struct my_option my_long_options[] = {"show-warnings", OPT_SHOW_WARNINGS, "Show warnings after every statement.", (uchar**) &show_warnings, (uchar**) &show_warnings, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"comments", 'c', "Preserve comments. Send comments to the server." + " Comments are discarded by default, enable with --enable-comments", + (uchar**) &preserve_comments, (uchar**) &preserve_comments, + 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; @@ -1087,6 +1092,17 @@ static int read_and_execute(bool interactive) if (!interactive) { line=batch_readline(status.line_buff); + /* + Skip UTF8 Byte Order Marker (BOM) 0xEFBBBF. + Editors like "notepad" put this marker in + the very beginning of a text file when + you save the file using "Unicode UTF-8" format. + */ + if (!line_number && + (uchar) line[0] == 0xEF && + (uchar) line[1] == 0xBB && + (uchar) line[2] == 0xBF) + line+= 3; line_number++; if (!glob_buffer.length()) status.query_start_line=line_number; @@ -1154,10 +1170,6 @@ static int read_and_execute(bool interactive) status.exit_status=0; break; } - if (!in_string && (line[0] == '#' || - (line[0] == '-' && line[1] == '-') || - line[0] == 0)) - continue; // Skip comment lines /* Check if line is a mysql command line @@ -1283,15 +1295,21 @@ static bool add_line(String &buffer,char *line,char *in_string, for (pos=out=line ; (inchar= (uchar) *pos) ; pos++) { - if (my_isspace(charset_info,inchar) && out == line && - buffer.is_empty()) - continue; + if (!preserve_comments) + { + // Skip spaces at the beggining of a statement + if (my_isspace(charset_info,inchar) && (out == line) && + buffer.is_empty()) + continue; + } + #ifdef USE_MB + // Accept multi-byte characters as-is int length; if (use_mb(charset_info) && (length= my_ismbchar(charset_info, pos, end_of_line))) { - if (!*ml_comment) + if (!*ml_comment || preserve_comments) { while (length--) *out++ = *pos++; @@ -1317,8 +1335,13 @@ static bool add_line(String &buffer,char *line,char *in_string, } if ((com=find_command(NullS,(char) inchar))) { - const String tmp(line,(uint) (out-line), charset_info); - buffer.append(tmp); + // Flush previously accepted characters + if (out != line) + { + buffer.append(line, (uint) (out-line)); + out= line; + } + if ((*com->func)(&buffer,pos-1) > 0) DBUG_RETURN(1); // Quit if (com->takes_params) @@ -1346,7 +1369,6 @@ static bool add_line(String &buffer,char *line,char *in_string, pos+= delimiter_length - 1; // Point at last delim char } } - out=line; } else { @@ -1359,46 +1381,105 @@ static bool add_line(String &buffer,char *line,char *in_string, } } else if (!*ml_comment && !*in_string && - (*pos == *delimiter && is_prefix(pos + 1, delimiter + 1) || - buffer.length() == 0 && (out - line) >= 9 && - !my_strcasecmp(charset_info, line, "delimiter"))) - { - uint old_delimiter_length= delimiter_length; + strlen(pos) >= 10 && + !my_strnncoll(charset_info, (uchar*) pos, 10, + (const uchar*) "delimiter ", 10)) + { + // Flush previously accepted characters if (out != line) - buffer.append(line, (uint) (out - line)); // Add this line + { + buffer.append(line, (uint32) (out - line)); + out= line; + } + + // Flush possible comments in the buffer + if (!buffer.is_empty()) + { + if (com_go(&buffer, 0) > 0) // < 0 is not fatal + DBUG_RETURN(1); + buffer.length(0); + } + + /* + Delimiter wants the get rest of the given line as argument to + allow one to change ';' to ';;' and back + */ + buffer.append(pos); + if (com_delimiter(&buffer, pos) > 0) + DBUG_RETURN(1); + + buffer.length(0); + break; + } + else if (!*ml_comment && !*in_string && is_prefix(pos, delimiter)) + { + // Found a statement. Continue parsing after the delimiter + pos+= delimiter_length; + + if (preserve_comments) + { + while (my_isspace(charset_info, *pos)) + *out++= *pos++; + } + // Flush previously accepted characters + if (out != line) + { + buffer.append(line, (uint32) (out-line)); + out= line; + } + + if (preserve_comments && ((*pos == '#') || + ((*pos == '-') && + (pos[1] == '-') && + my_isspace(charset_info, pos[2])))) + { + // Add trailing single line comments to this statement + buffer.append(pos); + pos+= strlen(pos); + } + + pos--; + if ((com= find_command(buffer.c_ptr(), 0))) { - if (com->func == com_delimiter) - { - /* - Delimiter wants the get rest of the given line as argument to - allow one to change ';' to ';;' and back - */ - char *end= strend(pos); - buffer.append(pos, (uint) (end - pos)); - /* Ensure pos will point at \0 after the pos+= below */ - pos= end - old_delimiter_length + 1; - } - if ((*com->func)(&buffer, buffer.c_ptr()) > 0) - DBUG_RETURN(1); // Quit + + if ((*com->func)(&buffer, buffer.c_ptr()) > 0) + DBUG_RETURN(1); // Quit } else { - if (com_go(&buffer, 0) > 0) // < 0 is not fatal - DBUG_RETURN(1); + if (com_go(&buffer, 0) > 0) // < 0 is not fatal + DBUG_RETURN(1); } buffer.length(0); - out= line; - pos+= old_delimiter_length - 1; } else if (!*ml_comment && (!*in_string && (inchar == '#' || inchar == '-' && pos[1] == '-' && my_isspace(charset_info,pos[2])))) - break; // comment to end of line + { + // Flush previously accepted characters + if (out != line) + { + buffer.append(line, (uint32) (out - line)); + out= line; + } + + // comment to end of line + if (preserve_comments) + buffer.append(pos); + + break; + } else if (!*in_string && inchar == '/' && *(pos+1) == '*' && *(pos+2) != '!') { - pos++; + if (preserve_comments) + { + *out++= *pos++; // copy '/' + *out++= *pos; // copy '*' + } + else + pos++; *ml_comment= 1; if (out != line) { @@ -1408,8 +1489,21 @@ static bool add_line(String &buffer,char *line,char *in_string, } else if (*ml_comment && !ss_comment && inchar == '*' && *(pos + 1) == '/') { - pos++; + if (preserve_comments) + { + *out++= *pos++; // copy '*' + *out++= *pos; // copy '/' + } + else + pos++; *ml_comment= 0; + if (out != line) + { + buffer.append(line, (uint32) (out - line)); + out= line; + } + // Consumed a 2 chars or more, and will add 1 at most, + // so using the 'line' buffer to edit data in place is ok. need_space= 1; } else @@ -1424,14 +1518,12 @@ static bool add_line(String &buffer,char *line,char *in_string, else if (!*ml_comment && !*in_string && (inchar == '\'' || inchar == '"' || inchar == '`')) *in_string= (char) inchar; - if (!*ml_comment) + if (!*ml_comment || preserve_comments) { if (need_space && !my_isspace(charset_info, (char)inchar)) - { *out++= ' '; - need_space= 0; - } - *out++= (char) inchar; + need_space= 0; + *out++= (char) inchar; } } } @@ -1441,7 +1533,7 @@ static bool add_line(String &buffer,char *line,char *in_string, uint length=(uint) (out-line); if (buffer.length() + length >= buffer.alloced_length()) buffer.realloc(buffer.length()+length+IO_SIZE); - if (!(*ml_comment) && buffer.append(line,length)) + if ((!*ml_comment || preserve_comments) && buffer.append(line, length)) DBUG_RETURN(1); } DBUG_RETURN(0); @@ -2074,7 +2166,7 @@ com_go(String *buffer,char *line __attribute__((unused))) { char buff[200], time_buff[32], *pos; MYSQL_RES *result; - ulong timer, warnings; + ulong timer, warnings= 0; uint error= 0; int err= 0; @@ -2126,33 +2218,26 @@ com_go(String *buffer,char *line __attribute__((unused))) } #endif - if (error) - { - executing_query= 0; - buffer->length(0); // Remove query on error - return error; - } - error=0; buffer->length(0); + if (error) + goto end; + do { if (quick) { if (!(result=mysql_use_result(&mysql)) && mysql_field_count(&mysql)) { - executing_query= 0; - return put_error(&mysql); + error= put_error(&mysql); + goto end; } } else { error= mysql_store_result_for_lazy(&result); if (error) - { - executing_query= 0; - return error; - } + goto end; } if (verbose >= 3 || !opt_silent) @@ -2229,12 +2314,11 @@ com_go(String *buffer,char *line __attribute__((unused))) if (err >= 1) error= put_error(&mysql); - if (show_warnings == 1 && warnings >= 1) /* Show warnings if any */ - { - init_pager(); +end: + + /* Show warnings if any or error occured */ + if (show_warnings == 1 && (warnings >= 1 || error)) print_warnings(); - end_pager(); - } if (!error && !status.batch && (mysql.server_status & SERVER_STATUS_DB_DROPPED)) @@ -2366,6 +2450,7 @@ static char *fieldflags2str(uint f) { ff2s_check_flag(GROUP); ff2s_check_flag(UNIQUE); ff2s_check_flag(BINCMP); + ff2s_check_flag(ON_UPDATE_NOW); #undef ff2s_check_flag if (f) sprintf(s, " unknows=0x%04x", f); @@ -2658,6 +2743,9 @@ static void print_warnings() MYSQL_RES *result; MYSQL_ROW cur; my_ulonglong num_rows; + + /* Save current error before calling "show warnings" */ + uint error= mysql_errno(&mysql); /* Get the warnings */ query= "show warnings"; @@ -2666,16 +2754,28 @@ static void print_warnings() /* Bail out when no warnings */ if (!(num_rows= mysql_num_rows(result))) - { - mysql_free_result(result); - return; - } + goto end; + + cur= mysql_fetch_row(result); + + /* + Don't print a duplicate of the current error. It is possible for SHOW + WARNINGS to return multiple errors with the same code, but different + messages. To be safe, skip printing the duplicate only if it is the only + warning. + */ + if (!cur || num_rows == 1 && error == (uint) strtoul(cur[1], NULL, 10)) + goto end; /* Print the warnings */ - while ((cur= mysql_fetch_row(result))) + init_pager(); + do { tee_fprintf(PAGER, "%s (Code %s): %s\n", cur[0], cur[1], cur[2]); - } + } while ((cur= mysql_fetch_row(result))); + end_pager(); + +end: mysql_free_result(result); } diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c index b2018e79364..ce0eceeb907 100644 --- a/client/mysqlcheck.c +++ b/client/mysqlcheck.c @@ -206,6 +206,7 @@ static void dbDisconnect(char *host); static void DBerror(MYSQL *mysql, const char *when); static void safe_exit(int error); static void print_result(); +static uint fixed_name_length(const char *name); static char *fix_table_name(char *dest, char *src); int what_to_do = 0; @@ -438,14 +439,14 @@ static int process_selected_tables(char *db, char **table_names, int tables) { /* We need table list in form `a`, `b`, `c` - that's why we need 4 more chars added to to each table name + that's why we need 2 more chars added to to each table name space is for more readable output in logs and in case of error */ char *table_names_comma_sep, *end; int i, tot_length = 0; for (i = 0; i < tables; i++) - tot_length += strlen(*(table_names + i)) + 4; + tot_length+= fixed_name_length(*(table_names + i)) + 2; if (!(table_names_comma_sep = (char *) my_malloc((sizeof(char) * tot_length) + 4, MYF(MY_WME)))) @@ -463,23 +464,46 @@ static int process_selected_tables(char *db, char **table_names, int tables) } else for (; tables > 0; tables--, table_names++) - handle_request_for_tables(*table_names, strlen(*table_names)); + handle_request_for_tables(*table_names, fixed_name_length(*table_names)); return 0; } /* process_selected_tables */ +static uint fixed_name_length(const char *name) +{ + const char *p; + uint extra_length= 2; /* count the first/last backticks */ + + for (p= name; *p; p++) + { + if (*p == '`') + extra_length++; + else if (*p == '.') + extra_length+= 2; + } + return (p - name) + extra_length; +} + + static char *fix_table_name(char *dest, char *src) { - char *db_sep; - *dest++= '`'; - if ((db_sep= strchr(src, '.'))) + for (; *src; src++) { - dest= strmake(dest, src, (uint) (db_sep - src)); - dest= strmov(dest, "`.`"); - src= db_sep + 1; + switch (*src) { + case '.': /* add backticks around '.' */ + *dest++= '`'; + *dest++= '.'; + *dest++= '`'; + break; + case '`': /* escape backtick character */ + *dest++= '`'; + /* fall through */ + default: + *dest++= *src; + } } - dest= strxmov(dest, src, "`", NullS); + *dest++= '`'; return dest; } @@ -503,7 +527,7 @@ static int process_all_tables_in_db(char *database) { /* We need table list in form `a`, `b`, `c` - that's why we need 4 more chars added to to each table name + that's why we need 2 more chars added to to each table name space is for more readable output in logs and in case of error */ @@ -511,7 +535,7 @@ static int process_all_tables_in_db(char *database) uint tot_length = 0; while ((row = mysql_fetch_row(res))) - tot_length += strlen(row[0]) + 4; + tot_length+= fixed_name_length(row[0]) + 2; mysql_data_seek(res, 0); if (!(tables=(char *) my_malloc(sizeof(char)*tot_length+4, MYF(MY_WME)))) @@ -536,10 +560,11 @@ static int process_all_tables_in_db(char *database) { while ((row = mysql_fetch_row(res))) { - if ((num_columns == 2) && (strcmp(row[1], "VIEW") == 0)) + /* Skip views if we don't perform renaming. */ + if ((what_to_do != DO_UPGRADE) && (num_columns == 2) && (strcmp(row[1], "VIEW") == 0)) continue; - handle_request_for_tables(row[0], strlen(row[0])); + handle_request_for_tables(row[0], fixed_name_length(row[0])); } } mysql_free_result(res); @@ -829,7 +854,7 @@ int main(int argc, char **argv) for (i = 0; i < tables4repair.elements ; i++) { char *name= (char*) dynamic_array_ptr(&tables4repair, i); - handle_request_for_tables(name, strlen(name)); + handle_request_for_tables(name, fixed_name_length(name)); } } end: diff --git a/client/mysqldump.c b/client/mysqldump.c index d504d177490..01b484e924e 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -420,8 +420,12 @@ static struct my_option my_long_options[] = "Creates a consistent snapshot by dumping all tables in a single " "transaction. Works ONLY for tables stored in storage engines which " "support multiversioning (currently only InnoDB does); the dump is NOT " - "guaranteed to be consistent for other storage engines. Option " - "automatically turns off --lock-tables.", + "guaranteed to be consistent for other storage engines. " + "While a --single-transaction dump is in process, to ensure a valid " + "dump file (correct table contents and binary log position), no other " + "connection should use the following statements: ALTER TABLE, DROP " + "TABLE, RENAME TABLE, TRUNCATE TABLE, as consistent snapshot is not " + "isolated from them. Option automatically turns off --lock-tables.", (uchar**) &opt_single_transaction, (uchar**) &opt_single_transaction, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"dump-date", OPT_DUMP_DATE, "Put a dump date to the end of the output.", @@ -1040,8 +1044,10 @@ static int fetch_db_collation(const char *db_name, char query[QUERY_LENGTH]; MYSQL_RES *db_cl_res; MYSQL_ROW db_cl_row; + char quoted_database_buf[NAME_LEN*2+3]; + char *qdatabase= quote_name(db_name, quoted_database_buf, 1); - my_snprintf(query, sizeof (query), "use %s", db_name); + my_snprintf(query, sizeof (query), "use %s", qdatabase); if (mysql_query_with_error_report(mysql, NULL, query)) return 1; diff --git a/client/mysqltest.c b/client/mysqltest.c index 04226719888..cca2420d498 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -2670,7 +2670,7 @@ void do_copy_file(struct st_command *command) command command handle DESCRIPTION - chmod_file + chmod Change file permission of */ diff --git a/cmd-line-utils/readline/INSTALL b/cmd-line-utils/readline/INSTALL index cb4a06fb701..f360b9e7907 100644 --- a/cmd-line-utils/readline/INSTALL +++ b/cmd-line-utils/readline/INSTALL @@ -1,7 +1,7 @@ Basic Installation ================== -These are installation instructions for Readline-5.0. +These are installation instructions for Readline-5.2. The simplest way to compile readline is: @@ -238,6 +238,9 @@ SHLIB_XLDFLAGS Additional flags to pass to SHOBJ_LD for shared library SHLIB_LIBS Any additional libraries that shared libraries should be linked against when they are created. +SHLIB_LIBPREF The prefix to use when generating the filename of the shared + library. The default is `lib'; Cygwin uses `cyg'. + SHLIB_LIBSUFF The suffix to add to `libreadline' and `libhistory' when generating the filename of the shared library. Many systems use `so'; HP-UX uses `sl'. @@ -254,6 +257,17 @@ SHLIB_LIBVERSION The string to append to the filename to indicate the version numbers; use `$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)' on those systems. Other Unix versions use different schemes. +SHLIB_DLLVERSION The version number for shared libraries that determines API + compatibility between readline versions and the underlying + system. Used only on Cygwin. Defaults to $SHLIB_MAJOR, but + can be overridden at configuration time by defining DLLVERSION + in the environment. + +SHLIB_DOT The character used to separate the name of the shared library + from the suffix and version information. The default is `.'; + systems like Cygwin which don't separate version information + from the library name should set this to the empty string. + SHLIB_STATUS Set this to `supported' when you have defined the other necessary variables. Make uses this to determine whether or not shared library creation should be attempted. If diff --git a/cmd-line-utils/readline/README b/cmd-line-utils/readline/README index ac4e3a767f9..8da99626aa1 100644 --- a/cmd-line-utils/readline/README +++ b/cmd-line-utils/readline/README @@ -1,7 +1,7 @@ Introduction ============ -This is the Gnu Readline library, version 5.0. +This is the Gnu Readline library, version 5.2. The Readline library provides a set of functions for use by applications that allow users to edit command lines as they are typed in. Both @@ -102,6 +102,9 @@ SHLIB_XLDFLAGS Additional flags to pass to SHOBJ_LD for shared library SHLIB_LIBS Any additional libraries that shared libraries should be linked against when they are created. +SHLIB_LIBPREF The prefix to use when generating the filename of the shared + library. The default is `lib'; Cygwin uses `cyg'. + SHLIB_LIBSUFF The suffix to add to `libreadline' and `libhistory' when generating the filename of the shared library. Many systems use `so'; HP-UX uses `sl'. @@ -118,6 +121,17 @@ SHLIB_LIBVERSION The string to append to the filename to indicate the version numbers; use `$(SHLIB_LIBSUFF).$(SHLIB_MAJOR)' on those systems. Other Unix versions use different schemes. +SHLIB_DLLVERSION The version number for shared libraries that determines API + compatibility between readline versions and the underlying + system. Used only on Cygwin. Defaults to $SHLIB_MAJOR, but + can be overridden at configuration time by defining DLLVERSION + in the environment. + +SHLIB_DOT The character used to separate the name of the shared library + from the suffix and version information. The default is `.'; + systems like Cygwin which don't separate version information + from the library name should set this to the empty string. + SHLIB_STATUS Set this to `supported' when you have defined the other necessary variables. Make uses this to determine whether or not shared library creation should be attempted. @@ -169,4 +183,4 @@ list (mirrored to the Usenet newsgroup gnu.bash.bug) often contains Readline bug reports and fixes. Chet Ramey -chet@po.cwru.edu +chet.ramey@case.edu diff --git a/cmd-line-utils/readline/bind.c b/cmd-line-utils/readline/bind.c index 568c3e8776a..08c906bfcc3 100644 --- a/cmd-line-utils/readline/bind.c +++ b/cmd-line-utils/readline/bind.c @@ -1,6 +1,6 @@ /* bind.c -- key binding and startup file support for the readline library. */ -/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc. +/* Copyright (C) 1987-2006 Free Software Foundation, Inc. This file is part of the GNU Readline Library, a library for reading lines of text with interactive input and history editing. @@ -26,7 +26,9 @@ # include #endif -#include "config_readline.h" +#if defined (HAVE_CONFIG_H) +# include +#endif #include #include @@ -75,6 +77,9 @@ static char *_rl_read_file PARAMS((char *, size_t *)); static void _rl_init_file_error PARAMS((const char *)); static int _rl_read_init_file PARAMS((const char *, int)); static int glean_key_from_name PARAMS((char *)); +static int find_boolean_var PARAMS((const char *)); + +static char *_rl_get_string_variable_value PARAMS((const char *)); static int substring_member_of_array PARAMS((char *, const char **)); static int currently_reading_init_file; @@ -337,10 +342,9 @@ rl_generic_bind (type, keyseq, data, map) KEYMAP_ENTRY k; k.function = 0; - k.type= 0; /* If no keys to bind to, exit right away. */ - if (!keyseq || !*keyseq) + if (keyseq == 0 || *keyseq == 0) { if (type == ISMACR) free (data); @@ -366,9 +370,12 @@ rl_generic_bind (type, keyseq, data, map) ic = uc; if (ic < 0 || ic >= KEYMAP_SIZE) - return -1; + { + free (keys); + return -1; + } - if (_rl_convert_meta_chars_to_ascii && META_CHAR (ic)) + if (META_CHAR (ic) && _rl_convert_meta_chars_to_ascii) { ic = UNMETA (ic); if (map[ESC].type == ISKMAP) @@ -435,7 +442,7 @@ rl_translate_keyseq (seq, array, len) { register int i, c, l, temp; - for (i = l = 0; (c = seq[i]); i++) + for (i = l = 0; c = seq[i]; i++) { if (c == '\\') { @@ -458,8 +465,24 @@ rl_translate_keyseq (seq, array, len) } else if (c == 'M') { - i++; - array[l++] = ESC; /* ESC is meta-prefix */ + i++; /* seq[i] == '-' */ + /* XXX - obey convert-meta setting */ + if (_rl_convert_meta_chars_to_ascii && _rl_keymap[ESC].type == ISKMAP) + array[l++] = ESC; /* ESC is meta-prefix */ + else if (seq[i+1] == '\\' && seq[i+2] == 'C' && seq[i+3] == '-') + { + i += 4; + temp = (seq[i] == '?') ? RUBOUT : CTRL (_rl_to_upper (seq[i])); + array[l++] = META (temp); + } + else + { + /* This doesn't yet handle things like \M-\a, which may + or may not have any reasonable meaning. You're + probably better off using straight octal or hex. */ + i++; + array[l++] = META (seq[i]); + } } else if (c == 'C') { @@ -554,6 +577,11 @@ rl_untranslate_keyseq (seq) kseq[i++] = '-'; c = UNMETA (c); } + else if (c == ESC) + { + kseq[i++] = '\\'; + c = 'e'; + } else if (CTRL_CHAR (c)) { kseq[i++] = '\\'; @@ -602,7 +630,12 @@ _rl_untranslate_macro_value (seq) *r++ = '-'; c = UNMETA (c); } - else if (CTRL_CHAR (c) && c != ESC) + else if (c == ESC) + { + *r++ = '\\'; + c = 'e'; + } + else if (CTRL_CHAR (c)) { *r++ = '\\'; *r++ = 'C'; @@ -661,7 +694,7 @@ rl_function_of_keyseq (keyseq, map, type) { register int i; - if (!map) + if (map == 0) map = _rl_keymap; for (i = 0; keyseq && keyseq[i]; i++) @@ -670,25 +703,27 @@ rl_function_of_keyseq (keyseq, map, type) if (META_CHAR (ic) && _rl_convert_meta_chars_to_ascii) { - if (map[ESC].type != ISKMAP) + if (map[ESC].type == ISKMAP) + { + map = FUNCTION_TO_KEYMAP (map, ESC); + ic = UNMETA (ic); + } + /* XXX - should we just return NULL here, since this obviously + doesn't match? */ + else { if (type) *type = map[ESC].type; return (map[ESC].function); } - else - { - map = FUNCTION_TO_KEYMAP (map, ESC); - ic = UNMETA (ic); - } } if (map[ic].type == ISKMAP) { /* If this is the last key in the key sequence, return the map. */ - if (!keyseq[i + 1]) + if (keyseq[i + 1] == '\0') { if (type) *type = ISKMAP; @@ -698,7 +733,12 @@ rl_function_of_keyseq (keyseq, map, type) else map = FUNCTION_TO_KEYMAP (map, ic); } - else + /* If we're not at the end of the key sequence, and the current key + is bound to something other than a keymap, then the entire key + sequence is not bound. */ + else if (map[ic].type != ISKMAP && keyseq[i+1]) + return ((rl_command_func_t *)NULL); + else /* map[ic].type != ISKMAP && keyseq[i+1] == 0 */ { if (type) *type = map[ic].type; @@ -736,8 +776,7 @@ _rl_read_file (filename, sizep) file_size = (size_t)finfo.st_size; /* check for overflow on very large files */ - if ((long long) file_size != (long long) finfo.st_size || - file_size + 1 < file_size) + if (file_size != finfo.st_size || file_size + 1 < file_size) { if (file >= 0) close (file); @@ -767,8 +806,8 @@ _rl_read_file (filename, sizep) /* Re-read the current keybindings file. */ int -rl_re_read_init_file (int count __attribute__((unused)), - int ignore __attribute__((unused))) +rl_re_read_init_file (count, ignore) + int count, ignore; { int r; r = rl_read_init_file ((const char *)NULL); @@ -781,6 +820,7 @@ rl_re_read_init_file (int count __attribute__((unused)), 1. the filename used for the previous call 2. the value of the shell variable `INPUTRC' 3. ~/.inputrc + 4. /etc/inputrc If the file existed and could be opened and read, 0 is returned, otherwise errno is returned. */ int @@ -789,17 +829,18 @@ rl_read_init_file (filename) { /* Default the filename. */ if (filename == 0) + filename = last_readline_init_file; + if (filename == 0) + filename = sh_get_env_value ("INPUTRC"); + if (filename == 0 || *filename == 0) { - filename = last_readline_init_file; - if (filename == 0) - filename = sh_get_env_value ("INPUTRC"); - if (filename == 0) - filename = DEFAULT_INPUTRC; + filename = DEFAULT_INPUTRC; + /* Try to read DEFAULT_INPUTRC; fall back to SYS_INPUTRC on failure */ + if (_rl_read_init_file (filename, 0) == 0) + return 0; + filename = SYS_INPUTRC; } - if (*filename == 0) - filename = DEFAULT_INPUTRC; - #if defined (__MSDOS__) if (_rl_read_init_file (filename, 0) == 0) return 0; @@ -989,7 +1030,8 @@ parser_if (args) /* Invert the current parser state if there is anything on the stack. */ static int -parser_else (char *args __attribute__((unused))) +parser_else (args) + char *args; { register int i; @@ -1019,7 +1061,8 @@ parser_else (char *args __attribute__((unused))) /* Terminate a conditional, popping the value of _rl_parsing_conditionalized_out from the stack. */ static int -parser_endif (char *args __attribute__((unused))) +parser_endif (args) + char *args; { if (if_stack_depth) _rl_parsing_conditionalized_out = if_stack[--if_stack_depth]; @@ -1142,7 +1185,7 @@ rl_parse_and_bind (string) { int passc = 0; - for (i = 1; (c = string[i]); i++) + for (i = 1; c = string[i]; i++) { if (passc) { @@ -1183,9 +1226,9 @@ rl_parse_and_bind (string) /* If this is a command to set a variable, then do that. */ if (_rl_stricmp (string, "set") == 0) { - char *var = string + i; - char *value; + char *var, *value, *e; + var = string + i; /* Make VAR point to start of variable name. */ while (*var && whitespace (*var)) var++; @@ -1196,6 +1239,20 @@ rl_parse_and_bind (string) *value++ = '\0'; while (*value && whitespace (*value)) value++; + /* Strip trailing whitespace from values to boolean variables. Temp + fix until I get a real quoted-string parser here. */ + i = find_boolean_var (var); + if (i >= 0) + { + /* remove trailing whitespace */ + e = value + strlen (value) - 1; + while (e >= value && whitespace (*e)) + e--; + e++; /* skip back to whitespace or EOS */ + if (*e && e >= value) + *e = '\0'; + } + rl_variable_bind (var, value); return 0; } @@ -1216,9 +1273,10 @@ rl_parse_and_bind (string) the quoted string delimiter, like the shell. */ if (*funname == '\'' || *funname == '"') { - int delimiter = string[i++], passc; + int delimiter, passc; - for (passc = 0; (c = string[i]); i++) + delimiter = string[i++]; + for (passc = 0; c = string[i]; i++) { if (passc) { @@ -1353,6 +1411,7 @@ static struct { int *value; int flags; } boolean_varlist [] = { + { "bind-tty-special-chars", &_rl_bind_stty_chars, 0 }, { "blink-matching-paren", &rl_blink_matching_paren, V_SPECIAL }, { "byte-oriented", &rl_byte_oriented, 0 }, { "completion-ignore-case", &_rl_completion_case_fold, 0 }, @@ -1377,7 +1436,7 @@ static struct { #if defined (VISIBLE_STATS) { "visible-stats", &rl_visible_stats, 0 }, #endif /* VISIBLE_STATS */ - { (char *)NULL, (int *)NULL, 0 } + { (char *)NULL, (int *)NULL } }; static int @@ -1446,7 +1505,7 @@ static struct { { "editing-mode", V_STRING, sv_editmode }, { "isearch-terminators", V_STRING, sv_isrchterm }, { "keymap", V_STRING, sv_keymap }, - { (char *)NULL, 0, 0 } + { (char *)NULL, 0 } }; static int @@ -1466,13 +1525,32 @@ find_string_var (name) values result in 0 (false). */ static int bool_to_int (value) -const char *value; + const char *value; { return (value == 0 || *value == '\0' || (_rl_stricmp (value, "on") == 0) || (value[0] == '1' && value[1] == '\0')); } +char * +rl_variable_value (name) + const char *name; +{ + register int i; + + /* Check for simple variables first. */ + i = find_boolean_var (name); + if (i >= 0) + return (*boolean_varlist[i].value ? "on" : "off"); + + i = find_string_var (name); + if (i >= 0) + return (_rl_get_string_variable_value (string_varlist[i].name)); + + /* Unknown variable names return NULL. */ + return 0; +} + int rl_variable_bind (name, value) const char *name, *value; @@ -1725,13 +1803,13 @@ char * rl_get_keymap_name_from_edit_mode () { if (rl_editing_mode == emacs_mode) - return (char*) "emacs"; + return "emacs"; #if defined (VI_MODE) else if (rl_editing_mode == vi_mode) - return (char*) "vi"; + return "vi"; #endif /* VI_MODE */ else - return (char*) "none"; + return "none"; } /* **************************************************************** */ @@ -1899,12 +1977,16 @@ rl_invoking_keyseqs_in_map (function, map) char *keyname = (char *)xmalloc (6 + strlen (seqs[i])); if (key == ESC) -#if 0 - sprintf (keyname, "\\e"); -#else - /* XXX - experimental */ - sprintf (keyname, "\\M-"); -#endif + { + /* If ESC is the meta prefix and we're converting chars + with the eighth bit set to ESC-prefixed sequences, then + we can use \M-. Otherwise we need to use the sequence + for ESC. */ + if (_rl_convert_meta_chars_to_ascii && map[ESC].type == ISKMAP) + sprintf (keyname, "\\M-"); + else + sprintf (keyname, "\\e"); + } else if (CTRL_CHAR (key)) sprintf (keyname, "\\C-%c", _rl_to_lower (UNCTRL (key))); else if (key == RUBOUT) @@ -1966,7 +2048,7 @@ rl_function_dumper (print_readably) fprintf (rl_outstream, "\n"); - for (i = 0; (name = names[i]); i++) + for (i = 0; name = names[i]; i++) { rl_command_func_t *function; char **invokers; @@ -2025,8 +2107,8 @@ rl_function_dumper (print_readably) rl_outstream. If an explicit argument is given, then print the output in such a way that it can be read back in. */ int -rl_dump_functions (int count __attribute__((unused)), - int key __attribute__((unused))) +rl_dump_functions (count, key) + int count, key; { if (rl_dispatching) fprintf (rl_outstream, "\r\n"); @@ -2105,7 +2187,8 @@ rl_macro_dumper (print_readably) } int -rl_dump_macros(int count __attribute__((unused)), int key __attribute__((unused))) +rl_dump_macros (count, key) + int count, key; { if (rl_dispatching) fprintf (rl_outstream, "\r\n"); @@ -2114,12 +2197,67 @@ rl_dump_macros(int count __attribute__((unused)), int key __attribute__((unused) return (0); } +static char * +_rl_get_string_variable_value (name) + const char *name; +{ + static char numbuf[32]; + char *ret; + + if (_rl_stricmp (name, "bell-style") == 0) + { + switch (_rl_bell_preference) + { + case NO_BELL: + return "none"; + case VISIBLE_BELL: + return "visible"; + case AUDIBLE_BELL: + default: + return "audible"; + } + } + else if (_rl_stricmp (name, "comment-begin") == 0) + return (_rl_comment_begin ? _rl_comment_begin : RL_COMMENT_BEGIN_DEFAULT); + else if (_rl_stricmp (name, "completion-query-items") == 0) + { + sprintf (numbuf, "%d", rl_completion_query_items); + return (numbuf); + } + else if (_rl_stricmp (name, "editing-mode") == 0) + return (rl_get_keymap_name_from_edit_mode ()); + else if (_rl_stricmp (name, "isearch-terminators") == 0) + { + if (_rl_isearch_terminators == 0) + return 0; + ret = _rl_untranslate_macro_value (_rl_isearch_terminators); + if (ret) + { + strncpy (numbuf, ret, sizeof (numbuf) - 1); + free (ret); + numbuf[sizeof(numbuf) - 1] = '\0'; + } + else + numbuf[0] = '\0'; + return numbuf; + } + else if (_rl_stricmp (name, "keymap") == 0) + { + ret = rl_get_keymap_name (_rl_keymap); + if (ret == 0) + ret = rl_get_keymap_name_from_edit_mode (); + return (ret ? ret : "none"); + } + else + return (0); +} + void rl_variable_dumper (print_readably) int print_readably; { int i; - const char *kname; + char *v; for (i = 0; boolean_varlist[i].name; i++) { @@ -2131,70 +2269,24 @@ rl_variable_dumper (print_readably) *boolean_varlist[i].value ? "on" : "off"); } - /* bell-style */ - switch (_rl_bell_preference) + for (i = 0; string_varlist[i].name; i++) { - case NO_BELL: - kname = "none"; break; - case VISIBLE_BELL: - kname = "visible"; break; - case AUDIBLE_BELL: - default: - kname = "audible"; break; - } - if (print_readably) - fprintf (rl_outstream, "set bell-style %s\n", kname); - else - fprintf (rl_outstream, "bell-style is set to `%s'\n", kname); - - /* comment-begin */ - if (print_readably) - fprintf (rl_outstream, "set comment-begin %s\n", _rl_comment_begin ? _rl_comment_begin : RL_COMMENT_BEGIN_DEFAULT); - else - fprintf (rl_outstream, "comment-begin is set to `%s'\n", _rl_comment_begin ? _rl_comment_begin : RL_COMMENT_BEGIN_DEFAULT); - - /* completion-query-items */ - if (print_readably) - fprintf (rl_outstream, "set completion-query-items %d\n", rl_completion_query_items); - else - fprintf (rl_outstream, "completion-query-items is set to `%d'\n", rl_completion_query_items); - - /* editing-mode */ - if (print_readably) - fprintf (rl_outstream, "set editing-mode %s\n", (rl_editing_mode == emacs_mode) ? "emacs" : "vi"); - else - fprintf (rl_outstream, "editing-mode is set to `%s'\n", (rl_editing_mode == emacs_mode) ? "emacs" : "vi"); - - /* isearch-terminators */ - if (_rl_isearch_terminators) - { - char *disp; - - disp = _rl_untranslate_macro_value (_rl_isearch_terminators); - + v = _rl_get_string_variable_value (string_varlist[i].name); + if (v == 0) /* _rl_isearch_terminators can be NULL */ + continue; if (print_readably) - fprintf (rl_outstream, "set isearch-terminators \"%s\"\n", disp); + fprintf (rl_outstream, "set %s %s\n", string_varlist[i].name, v); else - fprintf (rl_outstream, "isearch-terminators is set to \"%s\"\n", disp); - - free (disp); + fprintf (rl_outstream, "%s is set to `%s'\n", string_varlist[i].name, v); } - - /* keymap */ - kname = rl_get_keymap_name (_rl_keymap); - if (kname == 0) - kname = rl_get_keymap_name_from_edit_mode (); - if (print_readably) - fprintf (rl_outstream, "set keymap %s\n", kname ? kname : "none"); - else - fprintf (rl_outstream, "keymap is set to `%s'\n", kname ? kname : "none"); } /* Print all of the current variables and their values to rl_outstream. If an explicit argument is given, then print the output in such a way that it can be read back in. */ int -rl_dump_variables(int count __attribute__((unused)), int key __attribute__((unused))) +rl_dump_variables (count, key) + int count, key; { if (rl_dispatching) fprintf (rl_outstream, "\r\n"); diff --git a/cmd-line-utils/readline/callback.c b/cmd-line-utils/readline/callback.c index 0807f137b92..ada04d8593b 100644 --- a/cmd-line-utils/readline/callback.c +++ b/cmd-line-utils/readline/callback.c @@ -1,6 +1,6 @@ /* callback.c -- functions to use readline as an X `callback' mechanism. */ -/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc. +/* Copyright (C) 1987-2005 Free Software Foundation, Inc. This file is part of the GNU Readline Library, a library for reading lines of text with interactive input and history editing. @@ -21,7 +21,9 @@ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #define READLINE_LIBRARY -#include "config_readline.h" +#if defined (HAVE_CONFIG_H) +# include +#endif #include "rlconf.h" @@ -41,10 +43,16 @@ #include "rldefs.h" #include "readline.h" #include "rlprivate.h" +#include "xmalloc.h" + +/* Private data for callback registration functions. See comments in + rl_callback_read_char for more details. */ +_rl_callback_func_t *_rl_callback_func = 0; +_rl_callback_generic_arg *_rl_callback_data = 0; /* **************************************************************** */ /* */ -/* Callback Readline Functions */ +/* Callback Readline Functions */ /* */ /* **************************************************************** */ @@ -70,7 +78,8 @@ _rl_callback_newline () { in_handler = 1; - (*rl_prep_term_function) (_rl_meta_flag); + if (rl_prep_term_function) + (*rl_prep_term_function) (_rl_meta_flag); #if defined (HANDLE_SIGNALS) rl_set_signals (); @@ -87,6 +96,7 @@ rl_callback_handler_install (prompt, linefunc) rl_vcpfunc_t *linefunc; { rl_set_prompt (prompt); + RL_SETSTATE (RL_STATE_CALLBACK); rl_linefunc = linefunc; _rl_callback_newline (); } @@ -96,7 +106,8 @@ void rl_callback_read_char () { char *line; - int eof; + int eof, jcode; + static procenv_t olevel; if (rl_linefunc == NULL) { @@ -104,16 +115,89 @@ rl_callback_read_char () abort (); } - eof = readline_internal_char (); - - /* We loop in case some function has pushed input back with rl_execute_next. */ - for (;;) + memcpy ((void *)olevel, (void *)readline_top_level, sizeof (procenv_t)); + jcode = setjmp (readline_top_level); + if (jcode) { + (*rl_redisplay_function) (); + _rl_want_redisplay = 0; + memcpy ((void *)readline_top_level, (void *)olevel, sizeof (procenv_t)); + return; + } + + do + { + if (RL_ISSTATE (RL_STATE_ISEARCH)) + { + eof = _rl_isearch_callback (_rl_iscxt); + if (eof == 0 && (RL_ISSTATE (RL_STATE_ISEARCH) == 0) && RL_ISSTATE (RL_STATE_INPUTPENDING)) + rl_callback_read_char (); + + return; + } + else if (RL_ISSTATE (RL_STATE_NSEARCH)) + { + eof = _rl_nsearch_callback (_rl_nscxt); + return; + } + else if (RL_ISSTATE (RL_STATE_NUMERICARG)) + { + eof = _rl_arg_callback (_rl_argcxt); + if (eof == 0 && (RL_ISSTATE (RL_STATE_NUMERICARG) == 0) && RL_ISSTATE (RL_STATE_INPUTPENDING)) + rl_callback_read_char (); + /* XXX - this should handle _rl_last_command_was_kill better */ + else if (RL_ISSTATE (RL_STATE_NUMERICARG) == 0) + _rl_internal_char_cleanup (); + + return; + } + else if (RL_ISSTATE (RL_STATE_MULTIKEY)) + { + eof = _rl_dispatch_callback (_rl_kscxt); /* For now */ + while ((eof == -1 || eof == -2) && RL_ISSTATE (RL_STATE_MULTIKEY) && _rl_kscxt && (_rl_kscxt->flags & KSEQ_DISPATCHED)) + eof = _rl_dispatch_callback (_rl_kscxt); + if (RL_ISSTATE (RL_STATE_MULTIKEY) == 0) + { + _rl_internal_char_cleanup (); + _rl_want_redisplay = 1; + } + } + else if (_rl_callback_func) + { + /* This allows functions that simply need to read an additional + character (like quoted-insert) to register a function to be + called when input is available. _rl_callback_data is simply a + pointer to a struct that has the argument count originally + passed to the registering function and space for any additional + parameters. */ + eof = (*_rl_callback_func) (_rl_callback_data); + /* If the function `deregisters' itself, make sure the data is + cleaned up. */ + if (_rl_callback_func == 0) + { + if (_rl_callback_data) + { + _rl_callback_data_dispose (_rl_callback_data); + _rl_callback_data = 0; + } + _rl_internal_char_cleanup (); + } + } + else + eof = readline_internal_char (); + + if (rl_done == 0 && _rl_want_redisplay) + { + (*rl_redisplay_function) (); + _rl_want_redisplay = 0; + } + if (rl_done) { line = readline_internal_teardown (eof); - (*rl_deprep_term_function) (); + if (rl_deprep_term_function) + (*rl_deprep_term_function) (); #if defined (HANDLE_SIGNALS) rl_clear_signals (); #endif @@ -129,11 +213,8 @@ rl_callback_read_char () if (in_handler == 0 && rl_linefunc) _rl_callback_newline (); } - if (rl_pending_input || _rl_pushed_input_available ()) - eof = readline_internal_char (); - else - break; } + while (rl_pending_input || _rl_pushed_input_available () || RL_ISSTATE (RL_STATE_MACROINPUT)); } /* Remove the handler, and make sure the terminal is in its normal state. */ @@ -141,14 +222,37 @@ void rl_callback_handler_remove () { rl_linefunc = NULL; + RL_UNSETSTATE (RL_STATE_CALLBACK); if (in_handler) { in_handler = 0; - (*rl_deprep_term_function) (); + if (rl_deprep_term_function) + (*rl_deprep_term_function) (); #if defined (HANDLE_SIGNALS) rl_clear_signals (); #endif } } +_rl_callback_generic_arg * +_rl_callback_data_alloc (count) + int count; +{ + _rl_callback_generic_arg *arg; + + arg = (_rl_callback_generic_arg *)xmalloc (sizeof (_rl_callback_generic_arg)); + arg->count = count; + + arg->i1 = arg->i2 = 0; + + return arg; +} + +void _rl_callback_data_dispose (arg) + _rl_callback_generic_arg *arg; +{ + if (arg) + free (arg); +} + #endif diff --git a/cmd-line-utils/readline/chardefs.h b/cmd-line-utils/readline/chardefs.h index 04a3b7a8e9c..def3a111bd3 100644 --- a/cmd-line-utils/readline/chardefs.h +++ b/cmd-line-utils/readline/chardefs.h @@ -59,11 +59,7 @@ #define largest_char 255 /* Largest character value. */ #define CTRL_CHAR(c) ((c) < control_character_threshold && (((c) & 0x80) == 0)) -#if largest_char >= 255 -#define META_CHAR(c) ((c) > meta_character_threshold) -#else #define META_CHAR(c) ((c) > meta_character_threshold && (c) <= largest_char) -#endif #define CTRL(c) ((c) & control_character_mask) #define META(c) ((c) | meta_character_bit) @@ -90,6 +86,8 @@ /* Some systems define these; we want our definitions. */ #undef ISPRINT +/* Beware: these only work with single-byte ASCII characters. */ + #define ISALNUM(c) (IN_CTYPE_DOMAIN (c) && isalnum (c)) #define ISALPHA(c) (IN_CTYPE_DOMAIN (c) && isalpha (c)) #define ISDIGIT(c) (IN_CTYPE_DOMAIN (c) && isdigit (c)) diff --git a/cmd-line-utils/readline/compat.c b/cmd-line-utils/readline/compat.c index e4fbc322cee..a66d210fd2e 100644 --- a/cmd-line-utils/readline/compat.c +++ b/cmd-line-utils/readline/compat.c @@ -21,7 +21,9 @@ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #define READLINE_LIBRARY -#include "config_readline.h" +#if defined (HAVE_CONFIG_H) +# include +#endif #include diff --git a/cmd-line-utils/readline/complete.c b/cmd-line-utils/readline/complete.c index 526c1edb33d..a0232b2afdf 100644 --- a/cmd-line-utils/readline/complete.c +++ b/cmd-line-utils/readline/complete.c @@ -1,6 +1,6 @@ /* complete.c -- filename completion for readline. */ -/* Copyright (C) 1987-2004 Free Software Foundation, Inc. +/* Copyright (C) 1987-2005 Free Software Foundation, Inc. This file is part of the GNU Readline Library, a library for reading lines of text with interactive input and history editing. @@ -21,18 +21,12 @@ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #define READLINE_LIBRARY -#if !defined(_XOPEN_SOURCE) && !defined(__FreeBSD__) -#define _XOPEN_SOURCE 500 +#if defined (HAVE_CONFIG_H) +# include #endif -#include "config_readline.h" - #include - -/* To get SuSE 9.3 to define wcwidth() (in wchar.h) */ - #include - /* FreeBSD 5.3 will not declare u_int in sys/types.h, file.h needs it */ #if defined (HAVE_SYS_FILE_H) && !defined(__FreeBSD__) # include @@ -55,7 +49,9 @@ extern int errno; #endif /* !errno */ +#if defined (HAVE_PWD_H) #include +#endif #include "posixdir.h" #include "posixstat.h" @@ -86,9 +82,9 @@ typedef int QSFUNC (); /* Most systems don't declare getpwent in if _POSIX_SOURCE is defined. */ -#if !defined (HAVE_GETPW_DECLS) || defined (_POSIX_SOURCE) +#if defined (HAVE_GETPWENT) && (!defined (HAVE_GETPW_DECLS) || defined (_POSIX_SOURCE)) extern struct passwd *getpwent PARAMS((void)); -#endif /* !HAVE_GETPW_DECLS || _POSIX_SOURCE */ +#endif /* HAVE_GETPWENT && (!HAVE_GETPW_DECLS || _POSIX_SOURCE) */ /* If non-zero, then this is the address of a function to call when completing a word would normally display the list of possible matches. @@ -213,7 +209,8 @@ int rl_completion_type = 0; /* Up to this many items will be displayed in response to a possible-completions call. After that, we ask the user if - she is sure she wants to see them all. */ + she is sure she wants to see them all. A negative value means + don't ask. */ int rl_completion_query_items = 100; int _rl_page_completions = 1; @@ -361,15 +358,15 @@ rl_complete (ignore, invoking_key) /* List the possible completions. See description of rl_complete (). */ int -rl_possible_completions (int ignore __attribute__((unused)), - int invoking_key __attribute__((unused))) +rl_possible_completions (ignore, invoking_key) + int ignore, invoking_key; { return (rl_complete_internal ('?')); } int -rl_insert_completions (int ignore __attribute__((unused)), - int invoking_key __attribute__((unused))) +rl_insert_completions (ignore, invoking_key) + int ignore, invoking_key; { return (rl_complete_internal ('*')); } @@ -628,6 +625,8 @@ fnprint (to_print) mbstate_t ps; const char *end; size_t tlen; + int width, w; + wchar_t wc; end = to_print + strlen (to_print) + 1; memset (&ps, 0, sizeof (mbstate_t)); @@ -660,21 +659,28 @@ fnprint (to_print) else { #if defined (HANDLE_MULTIBYTE) - tlen = mbrlen (s, end - s, &ps); + tlen = mbrtowc (&wc, s, end - s, &ps); if (MB_INVALIDCH (tlen)) { tlen = 1; + width = 1; memset (&ps, 0, sizeof (mbstate_t)); } else if (MB_NULLWCH (tlen)) break; + else + { + w = wcwidth (wc); + width = (w >= 0) ? w : 1; + } fwrite (s, 1, tlen, rl_outstream); s += tlen; + printed_len += width; #else putc (*s, rl_outstream); s++; -#endif printed_len++; +#endif } } @@ -690,7 +696,7 @@ print_filename (to_print, full_pathname) char *to_print, *full_pathname; { int printed_len, extension_char, slen, tlen; - char *s, c, *new_full_pathname; + char *s, c, *new_full_pathname, *dn; extension_char = 0; printed_len = fnprint (to_print); @@ -715,7 +721,17 @@ print_filename (to_print, full_pathname) files in the root directory. If we pass a null string to the bash directory completion hook, for example, it will expand it to the current directory. We just want the `/'. */ - s = tilde_expand (full_pathname && *full_pathname ? full_pathname : "/"); + if (full_pathname == 0 || *full_pathname == 0) + dn = "/"; + else if (full_pathname[0] != '/') + dn = full_pathname; + else if (full_pathname[1] == 0) + dn = "//"; /* restore trailing slash to `//' */ + else if (full_pathname[1] == '/' && full_pathname[2] == 0) + dn = "/"; /* don't turn /// into // */ + else + dn = full_pathname; + s = tilde_expand (dn); if (rl_directory_completion_hook) (*rl_directory_completion_hook) (&s); @@ -723,6 +739,10 @@ print_filename (to_print, full_pathname) tlen = strlen (to_print); new_full_pathname = (char *)xmalloc (slen + tlen + 2); strcpy (new_full_pathname, s); + if (s[slen - 1] == '/') + slen--; + else + new_full_pathname[slen] = '/'; new_full_pathname[slen] = '/'; strcpy (new_full_pathname + slen + 1, to_print); @@ -761,7 +781,10 @@ print_filename (to_print, full_pathname) } static char * -rl_quote_filename (char *s, int rtype __attribute__((unused)), char *qcp) +rl_quote_filename (s, rtype, qcp) + char *s; + int rtype; + char *qcp; { char *r; @@ -811,14 +834,7 @@ _rl_find_completion_word (fp, dp) quote substrings for the completer. Try to find the start of an unclosed quoted substring. */ /* FOUND_QUOTE is set so we know what kind of quotes we found. */ -#if defined (HANDLE_MULTIBYTE) - for (scan = pass_next = 0; scan < end; - scan = ((MB_CUR_MAX == 1 || rl_byte_oriented) - ? (scan + 1) - : _rl_find_next_mbchar (rl_line_buffer, scan, 1, MB_FIND_ANY))) -#else - for (scan = pass_next = 0; scan < end; scan++) -#endif + for (scan = pass_next = 0; scan < end; scan = MB_NEXTCHAR (rl_line_buffer, scan, 1, MB_FIND_ANY)) { if (pass_next) { @@ -868,11 +884,7 @@ _rl_find_completion_word (fp, dp) /* We didn't find an unclosed quoted substring upon which to do completion, so use the word break characters to find the substring on which to complete. */ -#if defined (HANDLE_MULTIBYTE) - while ((rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_ANY))) -#else - while (--rl_point) -#endif + while (rl_point = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_ANY)) { scan = rl_line_buffer[rl_point]; @@ -939,7 +951,7 @@ gen_completion_matches (text, start, end, our_func, found_quote, quote_char) rl_compentry_func_t *our_func; int found_quote, quote_char; { - char **matches, *temp; + char **matches; rl_completion_found_quote = found_quote; rl_completion_quote_character = quote_char; @@ -958,21 +970,9 @@ gen_completion_matches (text, start, end, our_func, found_quote, quote_char) } } - /* Beware -- we're stripping the quotes here. Do this only if we know - we are doing filename completion and the application has defined a - filename dequoting function. */ - temp = (char *)NULL; - - if (found_quote && our_func == rl_filename_completion_function && - rl_filename_dequoting_function) - { - /* delete single and double quotes */ - temp = (*rl_filename_dequoting_function) (text, quote_char); - text = temp; /* not freeing text is not a memory leak */ - } + /* XXX -- filename dequoting moved into rl_filename_completion_function */ matches = rl_completion_matches (text, our_func); - FREE (temp); return matches; } @@ -1105,7 +1105,8 @@ compute_lcd_of_matches (match_list, matches, text) #if defined (HANDLE_MULTIBYTE) if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) { - mbstate_t ps_back = ps1; + mbstate_t ps_back; + ps_back = ps1; if (!_rl_compare_chars (match_list[i], si, &ps1, match_list[i+1], si, &ps2)) break; else if ((v = _rl_get_char_len (&match_list[i][si], &ps_back)) > 1) @@ -1155,8 +1156,7 @@ compute_lcd_of_matches (match_list, matches, text) rl_completion_found_quote && rl_filename_quoting_desired) { - dtext = (*rl_filename_dequoting_function) - ((char*) text, rl_completion_quote_character); + dtext = (*rl_filename_dequoting_function) ((char *)text, rl_completion_quote_character); text = dtext; } @@ -1402,7 +1402,7 @@ display_matches (matches) /* If there are many items, then ask the user if she really wants to see them all. */ - if (len >= rl_completion_query_items) + if (rl_completion_query_items > 0 && len >= rl_completion_query_items) { rl_crlf (); fprintf (rl_outstream, "Display all %d possibilities? (y or n)", len); @@ -1539,7 +1539,7 @@ append_to_match (text, delimiter, quote_char, nontrivial_match) : stat (filename, &finfo); if (s == 0 && S_ISDIR (finfo.st_mode)) { - if (_rl_complete_mark_directories) + if (_rl_complete_mark_directories /* && rl_completion_suppress_append == 0 */) { /* This is clumsy. Avoid putting in a double slash if point is at the end of the line and the previous character is a @@ -1803,7 +1803,7 @@ rl_completion_matches (text, entry_function) match_list = (char **)xmalloc ((match_list_size + 1) * sizeof (char *)); match_list[1] = (char *)NULL; - while ((string = (*entry_function) (text, matches))) + while (string = (*entry_function) (text, matches)) { if (matches + 1 == match_list_size) match_list = (char **)xrealloc @@ -1853,16 +1853,20 @@ rl_username_completion_function (text, state) setpwent (); } - while ((entry = getpwent ())) +#if defined (HAVE_GETPWENT) + while (entry = getpwent ()) { /* Null usernames should result in all users as possible completions. */ if (namelen == 0 || (STREQN (username, entry->pw_name, namelen))) break; } +#endif if (entry == 0) { +#if defined (HAVE_GETPWENT) endpwent (); +#endif return ((char *)NULL); } else @@ -1960,13 +1964,30 @@ rl_filename_completion_function (text, state) if (rl_directory_rewrite_hook) (*rl_directory_rewrite_hook) (&dirname); + /* The directory completion hook should perform any necessary + dequoting. */ if (rl_directory_completion_hook && (*rl_directory_completion_hook) (&dirname)) { free (users_dirname); users_dirname = savestring (dirname); } - + else if (rl_completion_found_quote && rl_filename_dequoting_function) + { + /* delete single and double quotes */ + temp = (*rl_filename_dequoting_function) (users_dirname, rl_completion_quote_character); + free (users_dirname); + users_dirname = temp; + } directory = opendir (dirname); + + /* Now dequote a non-null filename. */ + if (filename && *filename && rl_completion_found_quote && rl_filename_dequoting_function) + { + /* delete single and double quotes */ + temp = (*rl_filename_dequoting_function) (filename, rl_completion_quote_character); + free (filename); + filename = temp; + } filename_len = strlen (filename); rl_filename_completion_desired = 1; @@ -2089,7 +2110,8 @@ rl_filename_completion_function (text, state) hit the end of the match list, we restore the original unmatched text, ring the bell, and reset the counter to zero. */ int -rl_menu_complete (int count, int ignore __attribute__((unused))) +rl_menu_complete (count, ignore) + int count, ignore; { rl_compentry_func_t *our_func; int matching_filenames, found_quote; @@ -2173,9 +2195,11 @@ rl_menu_complete (int count, int ignore __attribute__((unused))) return (0); } - match_list_index = (match_list_index + count) % match_list_size; + match_list_index += count; if (match_list_index < 0) match_list_index += match_list_size; + else + match_list_index %= match_list_size; if (match_list_index == 0 && match_list_size > 1) { diff --git a/cmd-line-utils/readline/configure.in b/cmd-line-utils/readline/configure.in index 31e17606024..868773be696 100644 --- a/cmd-line-utils/readline/configure.in +++ b/cmd-line-utils/readline/configure.in @@ -4,9 +4,27 @@ dnl dnl report bugs to chet@po.cwru.edu dnl dnl Process this file with autoconf to produce a configure script. -AC_REVISION([for Readline 5.0, version 2.52, from autoconf version] AC_ACVERSION) -AC_INIT(readline, 5.0-rc1, bug-readline@gnu.org) +# Copyright (C) 1987-2005 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +AC_REVISION([for Readline 5.2, version 2.61]) + +AC_INIT(readline, 5.2, bug-readline@gnu.org) dnl make sure we are using a recent autoconf version AC_PREREQ(2.50) @@ -16,20 +34,28 @@ AC_CONFIG_AUX_DIR(./support) AC_CONFIG_HEADERS(config.h) dnl update the value of RL_READLINE_VERSION in readline.h when this changes -LIBVERSION=5.0 +LIBVERSION=5.2 AC_CANONICAL_HOST dnl configure defaults opt_curses=no +opt_purify=no dnl arguments to configure AC_ARG_WITH(curses, AC_HELP_STRING([--with-curses], [use the curses library instead of the termcap library]), opt_curses=$withval) +AC_ARG_WITH(purify, AC_HELP_STRING([--with-purify], [configure to postprocess with purify]), opt_purify=$withval) if test "$opt_curses" = "yes"; then prefer_curses=yes fi +if test "$opt_purify" = yes; then + PURIFY="purify" +else + PURIFY= +fi + dnl option parsing for optional features opt_multibyte=yes opt_static_libs=yes @@ -43,6 +69,36 @@ if test $opt_multibyte = no; then AC_DEFINE(NO_MULTIBYTE_SUPPORT) fi +dnl load up the cross-building cache file -- add more cases and cache +dnl files as necessary + +dnl Note that host and target machine are the same, and different than the +dnl build machine. + +CROSS_COMPILE= +if test "x$cross_compiling" = "xyes"; then + case "${host}" in + *-cygwin*) + cross_cache=${srcdir}/cross-build/cygwin.cache + ;; + *-mingw*) + cross_cache=${srcdir}/cross-build/mingw.cache + ;; + i[[3456]]86-*-beos*) + cross_cache=${srcdir}/cross-build/x86-beos.cache + ;; + *) echo "configure: cross-compiling for $host is not supported" >&2 + ;; + esac + if test -n "${cross_cache}" && test -r "${cross_cache}"; then + echo "loading cross-build cache file ${cross_cache}" + . ${cross_cache} + fi + unset cross_cache + CROSS_COMPILE='-DCROSS_COMPILING' + AC_SUBST(CROSS_COMPILE) +fi + echo "" echo "Beginning configuration for readline-$LIBVERSION for ${host_cpu}-${host_vendor}-${host_os}" echo "" @@ -83,14 +139,24 @@ AC_HEADER_STDC AC_HEADER_STAT AC_HEADER_DIRENT -AC_CHECK_FUNCS(lstat memmove putenv select setenv setlocale \ - strcasecmp strpbrk tcgetattr vsnprintf isascii isxdigit) +AC_CHECK_FUNCS(fcntl kill lstat) +AC_CHECK_FUNCS(memmove putenv select setenv setlocale \ + strcasecmp strpbrk tcgetattr vsnprintf) +AC_CHECK_FUNCS(isascii isxdigit) +AC_CHECK_FUNCS(getpwent getpwnam getpwuid) AC_FUNC_STRCOLL -AC_CHECK_HEADERS(unistd.h stdlib.h varargs.h stdarg.h string.h strings.h \ - limits.h sys/ptem.h sys/pte.h sys/stream.h sys/select.h \ - termcap.h termios.h termio.h sys/file.h locale.h memory.h ) +AC_CHECK_HEADERS(fcntl.h unistd.h stdlib.h varargs.h stdarg.h string.h strings.h \ + limits.h locale.h pwd.h memory.h termcap.h termios.h termio.h) +AC_CHECK_HEADERS(sys/pte.h sys/stream.h sys/select.h sys/file.h) + +AC_CHECK_HEADERS(sys/ptem.h,,, +[[ +#if HAVE_SYS_STREAM_H +# include +#endif +]]) BASH_SYS_SIGNAL_VINTAGE BASH_SYS_REINSTALL_SIGHANDLERS @@ -143,7 +209,13 @@ esac # if test -f ${srcdir}/support/shobj-conf; then AC_MSG_CHECKING(configuration for building shared libraries) - eval `${CONFIG_SHELL-/bin/sh} ${srcdir}/support/shobj-conf -C "${CC}" -c ${host_cpu} -o ${host_os} -v ${host_vendor}` + eval `TERMCAP_LIB=$TERMCAP_LIB ${CONFIG_SHELL-/bin/sh} ${srcdir}/support/shobj-conf -C "${CC}" -c ${host_cpu} -o ${host_os} -v ${host_vendor}` + +# case "$SHLIB_LIBS" in +# *curses*|*termcap*|*termlib*) ;; +# *) SHLIB_LIBS="$SHLIB_LIBS $TERMCAP_LIB" ;; +# esac + AC_SUBST(SHOBJ_CC) AC_SUBST(SHOBJ_CFLAGS) AC_SUBST(SHOBJ_LD) @@ -153,8 +225,11 @@ if test -f ${srcdir}/support/shobj-conf; then AC_SUBST(SHOBJ_STATUS) AC_SUBST(SHLIB_STATUS) AC_SUBST(SHLIB_XLDFLAGS) + AC_SUBST(SHLIB_DOT) + AC_SUBST(SHLIB_LIBPREF) AC_SUBST(SHLIB_LIBSUFF) AC_SUBST(SHLIB_LIBVERSION) + AC_SUBST(SHLIB_DLLVERSION) AC_SUBST(SHLIB_LIBS) AC_MSG_RESULT($SHLIB_STATUS) @@ -191,6 +266,12 @@ msdosdjgpp*) BUILD_DIR=`pwd.exe` ;; # to prevent //d/path/file *) BUILD_DIR=`pwd` ;; esac +case "$BUILD_DIR" in +*\ *) BUILD_DIR=`echo "$BUILD_DIR" | sed 's: :\\\\ :g'` ;; +*) ;; +esac + +AC_SUBST(PURIFY) AC_SUBST(BUILD_DIR) AC_SUBST(CFLAGS) diff --git a/cmd-line-utils/readline/display.c b/cmd-line-utils/readline/display.c index 06cac3bfd32..47ff0615974 100644 --- a/cmd-line-utils/readline/display.c +++ b/cmd-line-utils/readline/display.c @@ -1,6 +1,6 @@ /* display.c -- readline redisplay facility. */ -/* Copyright (C) 1987-2004 Free Software Foundation, Inc. +/* Copyright (C) 1987-2006 Free Software Foundation, Inc. This file is part of the GNU Readline Library, a library for reading lines of text with interactive input and history editing. @@ -21,16 +21,12 @@ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #define READLINE_LIBRARY -#ifndef _XOPEN_SOURCE -#define _XOPEN_SOURCE 500 +#if defined (HAVE_CONFIG_H) +# include #endif -#include "config_readline.h" - #include -/* To get SuSE 9.3 to define wcwidth() (in wchar.h) */ - #if defined (HAVE_UNISTD_H) # include #endif /* HAVE_UNISTD_H */ @@ -63,10 +59,6 @@ extern char *strchr (), *strrchr (); #endif /* !strchr && !__STDC__ */ -#if defined (HACK_TERMCAP_MOTION) -extern char *_rl_term_forward_char; -#endif - static void update_line PARAMS((char *, char *, int, int, int, int)); static void space_to_eol PARAMS((int)); static void delete_chars PARAMS((int)); @@ -84,9 +76,18 @@ static int *inv_lbreaks, *vis_lbreaks; static int inv_lbsize, vis_lbsize; /* Heuristic used to decide whether it is faster to move from CUR to NEW - by backing up or outputting a carriage return and moving forward. */ + by backing up or outputting a carriage return and moving forward. CUR + and NEW are either both buffer positions or absolute screen positions. */ #define CR_FASTER(new, cur) (((new) + 1) < ((cur) - (new))) +/* _rl_last_c_pos is an absolute cursor position in multibyte locales and a + buffer index in others. This macro is used when deciding whether the + current cursor position is in the middle of a prompt string containing + invisible characters. */ +#define PROMPT_ENDING_INDEX \ + ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) ? prompt_physical_chars : prompt_last_invisible+1) + + /* **************************************************************** */ /* */ /* Display stuff */ @@ -122,16 +123,25 @@ rl_voidfunc_t *rl_redisplay_function = rl_redisplay; int rl_display_fixed = 0; int _rl_suppress_redisplay = 0; +int _rl_want_redisplay = 0; /* The stuff that gets printed out before the actual text of the line. This is usually pointing to rl_prompt. */ char *rl_display_prompt = (char *)NULL; /* Pseudo-global variables declared here. */ + /* The visible cursor position. If you print some text, adjust this. */ +/* NOTE: _rl_last_c_pos is used as a buffer index when not in a locale + supporting multibyte characters, and an absolute cursor position when + in such a locale. This is an artifact of the donated multibyte support. + Care must be taken when modifying its value. */ int _rl_last_c_pos = 0; int _rl_last_v_pos = 0; +static int cpos_adjusted; +static int cpos_buffer_position; + /* Number of lines currently on screen minus 1. */ int _rl_vis_botlin = 0; @@ -158,6 +168,7 @@ static int line_size = 1024; include invisible characters. */ static char *local_prompt, *local_prompt_prefix; +static int local_prompt_len; static int prompt_visible_length, prompt_prefix_length; /* The number of invisible characters in the line currently being @@ -184,6 +195,19 @@ static int prompt_last_screen_line; static int prompt_physical_chars; +/* Variables to save and restore prompt and display information. */ + +/* These are getting numerous enough that it's time to create a struct. */ + +static char *saved_local_prompt; +static char *saved_local_prefix; +static int saved_last_invisible; +static int saved_visible_length; +static int saved_prefix_length; +static int saved_local_length; +static int saved_invis_chars_first_line; +static int saved_physical_chars; + /* Expand the prompt string S and return the number of visible characters in *LP, if LP is not null. This is currently more-or-less a placeholder for expansion. LIP, if non-null is a place to store the @@ -204,8 +228,8 @@ expand_prompt (pmt, lp, lip, niflp, vlp) char *pmt; int *lp, *lip, *niflp, *vlp; { - char *r, *ret, *p; - int l, rl, last, ignoring, ninvis, invfl, ind, pind, physchars; + char *r, *ret, *p, *igstart; + int l, rl, last, ignoring, ninvis, invfl, invflset, ind, pind, physchars; /* Short-circuit if we can. */ if ((MB_CUR_MAX <= 1 || rl_byte_oriented) && strchr (pmt, RL_PROMPT_START_IGNORE) == 0) @@ -218,7 +242,7 @@ expand_prompt (pmt, lp, lip, niflp, vlp) if (niflp) *niflp = 0; if (vlp) - *vlp = lp ? *lp : (int) strlen (r); + *vlp = lp ? *lp : strlen (r); return r; } @@ -226,20 +250,24 @@ expand_prompt (pmt, lp, lip, niflp, vlp) r = ret = (char *)xmalloc (l + 1); invfl = 0; /* invisible chars in first line of prompt */ + invflset = 0; /* we only want to set invfl once */ + igstart = 0; for (rl = ignoring = last = ninvis = physchars = 0, p = pmt; p && *p; p++) { /* This code strips the invisible character string markers RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE */ - if (*p == RL_PROMPT_START_IGNORE) + if (ignoring == 0 && *p == RL_PROMPT_START_IGNORE) /* XXX - check ignoring? */ { - ignoring++; + ignoring = 1; + igstart = p; continue; } else if (ignoring && *p == RL_PROMPT_END_IGNORE) { ignoring = 0; - last = r - ret - 1; + if (p != (igstart + 1)) + last = r - ret - 1; continue; } else @@ -253,7 +281,10 @@ expand_prompt (pmt, lp, lip, niflp, vlp) while (l--) *r++ = *p++; if (!ignoring) - rl += ind - pind; + { + rl += ind - pind; + physchars += _rl_col_width (pmt, pind, ind); + } else ninvis += ind - pind; p--; /* compensate for later increment */ @@ -263,16 +294,19 @@ expand_prompt (pmt, lp, lip, niflp, vlp) { *r++ = *p; if (!ignoring) - rl++; /* visible length byte counter */ + { + rl++; /* visible length byte counter */ + physchars++; + } else ninvis++; /* invisible chars byte counter */ } - if (rl >= _rl_screenwidth) - invfl = ninvis; - - if (ignoring == 0) - physchars++; + if (invflset == 0 && rl >= _rl_screenwidth) + { + invfl = ninvis; + invflset = 1; + } } } @@ -332,7 +366,9 @@ rl_expand_prompt (prompt) FREE (local_prompt_prefix); local_prompt = local_prompt_prefix = (char *)0; - prompt_last_invisible = prompt_visible_length = 0; + local_prompt_len = 0; + prompt_last_invisible = prompt_invis_chars_first_line = 0; + prompt_visible_length = prompt_physical_chars = 0; if (prompt == 0 || *prompt == 0) return (0); @@ -346,6 +382,7 @@ rl_expand_prompt (prompt) &prompt_invis_chars_first_line, &prompt_physical_chars); local_prompt_prefix = (char *)0; + local_prompt_len = local_prompt ? strlen (local_prompt) : 0; return (prompt_visible_length); } else @@ -355,15 +392,16 @@ rl_expand_prompt (prompt) local_prompt = expand_prompt (p, &prompt_visible_length, &prompt_last_invisible, (int *)NULL, - (int *)NULL); + &prompt_physical_chars); c = *t; *t = '\0'; /* The portion of the prompt string up to and including the final newline is now null-terminated. */ local_prompt_prefix = expand_prompt (prompt, &prompt_prefix_length, (int *)NULL, &prompt_invis_chars_first_line, - &prompt_physical_chars); + (int *)NULL); *t = c; + local_prompt_len = local_prompt ? strlen (local_prompt) : 0; return (prompt_prefix_length); } } @@ -420,13 +458,13 @@ rl_redisplay () { register int in, out, c, linenum, cursor_linenum; register char *line; - int c_pos, inv_botlin, lb_botlin, lb_linenum; - int newlines, lpos, temp, modmark; + int inv_botlin, lb_botlin, lb_linenum, o_cpos; + int newlines, lpos, temp, modmark, n0, num; char *prompt_this_line; #if defined (HANDLE_MULTIBYTE) wchar_t wc; size_t wc_bytes; - int wc_width= 0; + int wc_width; mbstate_t ps; int _rl_wrapped_multicolumn = 0; #endif @@ -435,16 +473,16 @@ rl_redisplay () return; if (!rl_display_prompt) - rl_display_prompt = (char*) ""; + rl_display_prompt = ""; - if (invisible_line == 0) + if (invisible_line == 0 || vis_lbreaks == 0) { init_line_structures (0); rl_on_new_line (); } /* Draw the line into the buffer. */ - c_pos = -1; + cpos_buffer_position = -1; line = invisible_line; out = inv_botlin = 0; @@ -471,24 +509,23 @@ rl_redisplay () number of non-visible characters in the prompt string. */ if (rl_display_prompt == rl_prompt || local_prompt) { - int local_len = local_prompt ? strlen (local_prompt) : 0; if (local_prompt_prefix && forced_display) _rl_output_some_chars (local_prompt_prefix, strlen (local_prompt_prefix)); - if (local_len > 0) + if (local_prompt_len > 0) { - temp = local_len + out + 2; + temp = local_prompt_len + out + 2; if (temp >= line_size) { line_size = (temp + 1024) - (temp % 1024); visible_line = (char *)xrealloc (visible_line, line_size); line = invisible_line = (char *)xrealloc (invisible_line, line_size); } - strncpy (line + out, local_prompt, local_len); - out += local_len; + strncpy (line + out, local_prompt, local_prompt_len); + out += local_prompt_len; } line[out] = '\0'; - wrap_offset = local_len - prompt_visible_length; + wrap_offset = local_prompt_len - prompt_visible_length; } else { @@ -524,17 +561,6 @@ rl_redisplay () wrap_offset = prompt_invis_chars_first_line = 0; } -#if defined (HANDLE_MULTIBYTE) -#define CHECK_INV_LBREAKS() \ - do { \ - if (newlines >= (inv_lbsize - 2)) \ - { \ - inv_lbsize *= 2; \ - inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \ - _rl_wrapped_line = (int *)xrealloc (_rl_wrapped_line, inv_lbsize * sizeof (int)); \ - } \ - } while (0) -#else #define CHECK_INV_LBREAKS() \ do { \ if (newlines >= (inv_lbsize - 2)) \ @@ -543,7 +569,6 @@ rl_redisplay () inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \ } \ } while (0) -#endif #if defined (HANDLE_MULTIBYTE) #define CHECK_LPOS() \ @@ -589,6 +614,7 @@ rl_redisplay () #if defined (HANDLE_MULTIBYTE) memset (_rl_wrapped_line, 0, vis_lbsize); + num = 0; #endif /* prompt_invis_chars_first_line is the number of invisible characters in @@ -600,6 +626,7 @@ rl_redisplay () contents of the command line? */ while (lpos >= _rl_screenwidth) { + int z; /* fix from Darin Johnson for prompt string with invisible characters that is longer than the screen width. The prompt_invis_chars_first_line variable could be made into an array @@ -607,19 +634,47 @@ rl_redisplay () probably too much work for the benefit gained. How many people have prompts that exceed two physical lines? Additional logic fix from Edward Catmur */ - temp = ((newlines + 1) * _rl_screenwidth) + - ((local_prompt_prefix == 0) ? ((newlines == 0) ? prompt_invis_chars_first_line - : ((newlines == 1) ? wrap_offset : 0)) - : ((newlines == 0) ? wrap_offset :0)); +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + { + n0 = num; + temp = local_prompt_len; + while (num < temp) + { + z = _rl_col_width (local_prompt, n0, num); + if (z > _rl_screenwidth) + { + num = _rl_find_prev_mbchar (local_prompt, num, MB_FIND_ANY); + break; + } + else if (z == _rl_screenwidth) + break; + num++; + } + temp = num; + } + else +#endif /* !HANDLE_MULTIBYTE */ + temp = ((newlines + 1) * _rl_screenwidth); + + /* Now account for invisible characters in the current line. */ + temp += ((local_prompt_prefix == 0) ? ((newlines == 0) ? prompt_invis_chars_first_line + : ((newlines == 1) ? wrap_offset : 0)) + : ((newlines == 0) ? wrap_offset :0)); inv_lbreaks[++newlines] = temp; - lpos -= _rl_screenwidth; +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + lpos -= _rl_col_width (local_prompt, n0, num); + else +#endif + lpos -= _rl_screenwidth; } prompt_last_screen_line = newlines; /* Draw the rest of the line (after the prompt) into invisible_line, keeping - track of where the cursor is (c_pos), the number of the line containing + track of where the cursor is (cpos_buffer_position), the number of the line containing the cursor (lb_linenum), the last line number (lb_botlin and inv_botlin). It maintains an array of line breaks for display (inv_lbreaks). This handles expanding tabs for display and displaying meta characters. */ @@ -672,7 +727,7 @@ rl_redisplay () if (in == rl_point) { - c_pos = out; + cpos_buffer_position = out; lb_linenum = newlines; } @@ -766,10 +821,10 @@ rl_redisplay () } if (in == rl_point) { - c_pos = out; + cpos_buffer_position = out; lb_linenum = newlines; } - for (i = in; i < (int) (in+wc_bytes); i++) + for (i = in; i < in+wc_bytes; i++) line[out++] = rl_line_buffer[i]; for (i = 0; i < wc_width; i++) CHECK_LPOS(); @@ -797,9 +852,9 @@ rl_redisplay () } line[out] = '\0'; - if (c_pos < 0) + if (cpos_buffer_position < 0) { - c_pos = out; + cpos_buffer_position = out; lb_linenum = newlines; } @@ -808,7 +863,7 @@ rl_redisplay () inv_lbreaks[newlines+1] = out; cursor_linenum = lb_linenum; - /* C_POS == position in buffer where cursor should be placed. + /* CPOS_BUFFER_POSITION == position in buffer where cursor should be placed. CURSOR_LINENUM == line number where the cursor should be placed. */ /* PWP: now is when things get a bit hairy. The visible and invisible @@ -822,7 +877,7 @@ rl_redisplay () if (_rl_horizontal_scroll_mode == 0 && _rl_term_up && *_rl_term_up) { - int nleft, pos, changed_screen_line; + int nleft, pos, changed_screen_line, tx; if (!rl_display_fixed || forced_display) { @@ -847,15 +902,38 @@ rl_redisplay () #define VIS_LLEN(l) ((l) > _rl_vis_botlin ? 0 : (vis_lbreaks[l+1] - vis_lbreaks[l])) #define INV_LLEN(l) (inv_lbreaks[l+1] - inv_lbreaks[l]) #define VIS_CHARS(line) (visible_line + vis_lbreaks[line]) -#define VIS_LINE(line) ((line) > _rl_vis_botlin) ? (char*) "" : VIS_CHARS(line) +#define VIS_LINE(line) ((line) > _rl_vis_botlin) ? "" : VIS_CHARS(line) #define INV_LINE(line) (invisible_line + inv_lbreaks[line]) /* For each line in the buffer, do the updating display. */ for (linenum = 0; linenum <= inv_botlin; linenum++) { + /* This can lead us astray if we execute a program that changes + the locale from a non-multibyte to a multibyte one. */ + o_cpos = _rl_last_c_pos; + cpos_adjusted = 0; update_line (VIS_LINE(linenum), INV_LINE(linenum), linenum, VIS_LLEN(linenum), INV_LLEN(linenum), inv_botlin); + /* update_line potentially changes _rl_last_c_pos, but doesn't + take invisible characters into account, since _rl_last_c_pos + is an absolute cursor position in a multibyte locale. See + if compensating here is the right thing, or if we have to + change update_line itself. There is one case in which + update_line adjusts _rl_last_c_pos itself (so it can pass + _rl_move_cursor_relative accurate values); it communicates + this back by setting cpos_adjusted. If we assume that + _rl_last_c_pos is correct (an absolute cursor position) each + time update_line is called, then we can assume in our + calculations that o_cpos does not need to be adjusted by + wrap_offset. */ + if (linenum == 0 && (MB_CUR_MAX > 1 && rl_byte_oriented == 0) && + cpos_adjusted == 0 && + _rl_last_c_pos != o_cpos && + _rl_last_c_pos > wrap_offset && + o_cpos < prompt_last_invisible) + _rl_last_c_pos -= wrap_offset; + /* If this is the line with the prompt, we might need to compensate for invisible characters in the new line. Do this only if there is not more than one new line (which @@ -867,7 +945,10 @@ rl_redisplay () (wrap_offset > visible_wrap_offset) && (_rl_last_c_pos < visible_first_line_len)) { - nleft = _rl_screenwidth + wrap_offset - _rl_last_c_pos; + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + nleft = _rl_screenwidth - _rl_last_c_pos; + else + nleft = _rl_screenwidth + wrap_offset - _rl_last_c_pos; if (nleft) _rl_clear_to_eol (nleft); } @@ -888,7 +969,7 @@ rl_redisplay () _rl_move_vert (linenum); _rl_move_cursor_relative (0, tt); _rl_clear_to_eol - ((linenum == _rl_vis_botlin) ? (int) strlen (tt) : _rl_screenwidth); + ((linenum == _rl_vis_botlin) ? strlen (tt) : _rl_screenwidth); } } _rl_vis_botlin = inv_botlin; @@ -903,7 +984,7 @@ rl_redisplay () the physical cursor position on the screen stays the same, but the buffer position needs to be adjusted to account for invisible characters. */ - if (cursor_linenum == 0 && wrap_offset) + if ((MB_CUR_MAX == 1 || rl_byte_oriented) && cursor_linenum == 0 && wrap_offset) _rl_last_c_pos += wrap_offset; } @@ -914,7 +995,11 @@ rl_redisplay () invisible character in the prompt string. */ nleft = prompt_visible_length + wrap_offset; if (cursor_linenum == 0 && wrap_offset > 0 && _rl_last_c_pos > 0 && - _rl_last_c_pos <= prompt_last_invisible && local_prompt) +#if 0 + _rl_last_c_pos <= PROMPT_ENDING_INDEX && local_prompt) +#else + _rl_last_c_pos < PROMPT_ENDING_INDEX && local_prompt) +#endif { #if defined (__MSDOS__) putc ('\r', rl_outstream); @@ -924,7 +1009,7 @@ rl_redisplay () #endif _rl_output_some_chars (local_prompt, nleft); if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - _rl_last_c_pos = _rl_col_width (local_prompt, 0, nleft); + _rl_last_c_pos = _rl_col_width (local_prompt, 0, nleft) - wrap_offset; else _rl_last_c_pos = nleft; } @@ -933,21 +1018,35 @@ rl_redisplay () in the buffer? */ pos = inv_lbreaks[cursor_linenum]; /* nleft == number of characters in the line buffer between the - start of the line and the cursor position. */ - nleft = c_pos - pos; + start of the line and the desired cursor position. */ + nleft = cpos_buffer_position - pos; + + /* NLEFT is now a number of characters in a buffer. When in a + multibyte locale, however, _rl_last_c_pos is an absolute cursor + position that doesn't take invisible characters in the prompt + into account. We use a fudge factor to compensate. */ /* Since _rl_backspace() doesn't know about invisible characters in the prompt, and there's no good way to tell it, we compensate for those characters here and call _rl_backspace() directly. */ if (wrap_offset && cursor_linenum == 0 && nleft < _rl_last_c_pos) { - _rl_backspace (_rl_last_c_pos - nleft); + /* TX == new physical cursor position in multibyte locale. */ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - _rl_last_c_pos = _rl_col_width (&visible_line[pos], 0, nleft); + tx = _rl_col_width (&visible_line[pos], 0, nleft) - visible_wrap_offset; else - _rl_last_c_pos = nleft; + tx = nleft; + if (_rl_last_c_pos > tx) + { + _rl_backspace (_rl_last_c_pos - tx); /* XXX */ + _rl_last_c_pos = tx; + } } + /* We need to note that in a multibyte locale we are dealing with + _rl_last_c_pos as an absolute cursor position, but moving to a + point specified by a buffer position (NLEFT) that doesn't take + invisible characters into account. */ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) _rl_move_cursor_relative (nleft, &invisible_line[pos]); else if (nleft != _rl_last_c_pos) @@ -966,11 +1065,11 @@ rl_redisplay () will be LMARGIN. */ /* The number of characters that will be displayed before the cursor. */ - ndisp = c_pos - wrap_offset; + ndisp = cpos_buffer_position - wrap_offset; nleft = prompt_visible_length + wrap_offset; /* Where the new cursor position will be on the screen. This can be longer than SCREENWIDTH; if it is, lmargin will be adjusted. */ - phys_c_pos = c_pos - (last_lmargin ? last_lmargin : wrap_offset); + phys_c_pos = cpos_buffer_position - (last_lmargin ? last_lmargin : wrap_offset); t = _rl_screenwidth / 3; /* If the number of characters had already exceeded the screenwidth, @@ -981,7 +1080,7 @@ rl_redisplay () two-thirds of the way across the screen. */ if (phys_c_pos > _rl_screenwidth - 2) { - lmargin = c_pos - (2 * t); + lmargin = cpos_buffer_position - (2 * t); if (lmargin < 0) lmargin = 0; /* If the left margin would be in the middle of a prompt with @@ -995,7 +1094,7 @@ rl_redisplay () { /* If we are moving back towards the beginning of the line and the last margin is no longer correct, compute a new one. */ - lmargin = ((c_pos - 1) / t) * t; /* XXX */ + lmargin = ((cpos_buffer_position - 1) / t) * t; /* XXX */ if (wrap_offset && lmargin > 0 && lmargin < nleft) lmargin = nleft; } @@ -1040,7 +1139,7 @@ rl_redisplay () if (visible_first_line_len > _rl_screenwidth) visible_first_line_len = _rl_screenwidth; - _rl_move_cursor_relative (c_pos - lmargin, &invisible_line[lmargin]); + _rl_move_cursor_relative (cpos_buffer_position - lmargin, &invisible_line[lmargin]); last_lmargin = lmargin; } } @@ -1106,7 +1205,10 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) the exact cursor position and cut-and-paste with certain terminal emulators. In this calculation, TEMP is the physical screen position of the cursor. */ - temp = _rl_last_c_pos - W_OFFSET(_rl_last_v_pos, visible_wrap_offset); + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + temp = _rl_last_c_pos; + else + temp = _rl_last_c_pos - W_OFFSET(_rl_last_v_pos, visible_wrap_offset); if (temp == _rl_screenwidth && _rl_term_autowrap && !_rl_horizontal_scroll_mode && _rl_last_v_pos == current_line - 1) { @@ -1171,7 +1273,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) putc (new[0], rl_outstream); else putc (' ', rl_outstream); - _rl_last_c_pos = 1; /* XXX */ + _rl_last_c_pos = 1; _rl_last_v_pos++; if (old[0] && new[0]) old[0] = new[0]; @@ -1312,7 +1414,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) if (_rl_last_v_pos != current_line) { _rl_move_vert (current_line); - if (current_line == 0 && visible_wrap_offset) + if ((MB_CUR_MAX == 1 || rl_byte_oriented) && current_line == 0 && visible_wrap_offset) _rl_last_c_pos += visible_wrap_offset; } @@ -1328,11 +1430,11 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) sequences (like drawing the `unbold' sequence without a corresponding `bold') that manifests itself on certain terminals. */ - lendiff = local_prompt ? strlen (local_prompt) : 0; + lendiff = local_prompt_len; od = ofd - old; /* index of first difference in visible line */ if (current_line == 0 && !_rl_horizontal_scroll_mode && _rl_term_cr && lendiff > prompt_visible_length && _rl_last_c_pos > 0 && - od >= lendiff && _rl_last_c_pos <= prompt_last_invisible) + od >= lendiff && _rl_last_c_pos < PROMPT_ENDING_INDEX) { #if defined (__MSDOS__) putc ('\r', rl_outstream); @@ -1341,12 +1443,29 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) #endif _rl_output_some_chars (local_prompt, lendiff); if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - _rl_last_c_pos = _rl_col_width (local_prompt, 0, lendiff); + { + /* We take wrap_offset into account here so we can pass correct + information to _rl_move_cursor_relative. */ + _rl_last_c_pos = _rl_col_width (local_prompt, 0, lendiff) - wrap_offset; + cpos_adjusted = 1; + } else _rl_last_c_pos = lendiff; } + /* When this function returns, _rl_last_c_pos is correct, and an absolute + cursor postion in multibyte mode, but a buffer index when not in a + multibyte locale. */ _rl_move_cursor_relative (od, old); +#if 1 +#if defined (HANDLE_MULTIBYTE) + /* We need to indicate that the cursor position is correct in the presence of + invisible characters in the prompt string. Let's see if setting this when + we make sure we're at the end of the drawn prompt string works. */ + if (current_line == 0 && MB_CUR_MAX > 1 && rl_byte_oriented == 0 && _rl_last_c_pos == prompt_physical_chars) + cpos_adjusted = 1; +#endif +#endif /* if (len (new) > len (old)) lendiff == difference in buffer @@ -1403,7 +1522,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) insert_some_chars (nfd, lendiff, col_lendiff); _rl_last_c_pos += col_lendiff; } - else if (*ols == 0 && lendiff > 0) + else if ((MB_CUR_MAX == 1 || rl_byte_oriented != 0) && *ols == 0 && lendiff > 0) { /* At the end of a line the characters do not have to be "inserted". They can just be placed on the screen. */ @@ -1442,6 +1561,10 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) /* cannot insert chars, write to EOL */ _rl_output_some_chars (nfd, temp); _rl_last_c_pos += col_temp; + /* If we're in a multibyte locale and were before the last invisible + char in the current line (which implies we just output some invisible + characters) we need to adjust _rl_last_c_pos, since it represents + a physical character position. */ } } else /* Delete characters from line. */ @@ -1473,7 +1596,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin) if (temp > 0) { _rl_output_some_chars (nfd, temp); - _rl_last_c_pos += col_temp; + _rl_last_c_pos += col_temp; /* XXX */ } lendiff = (oe - old) - (ne - new); if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) @@ -1535,7 +1658,7 @@ rl_on_new_line_with_prompt () l = strlen (prompt_last_line); if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - _rl_last_c_pos = _rl_col_width (prompt_last_line, 0, l); + _rl_last_c_pos = _rl_col_width (prompt_last_line, 0, l); /* XXX */ else _rl_last_c_pos = l; @@ -1570,10 +1693,11 @@ rl_on_new_line_with_prompt () int rl_forced_update_display () { + register char *temp; + if (visible_line) { - register char *temp = visible_line; - + temp = visible_line; while (*temp) *temp++ = '\0'; } @@ -1584,6 +1708,8 @@ rl_forced_update_display () } /* Move the cursor from _rl_last_c_pos to NEW, which are buffer indices. + (Well, when we don't have multibyte characters, _rl_last_c_pos is a + buffer index.) DATA is the contents of the screen line of interest; i.e., where the movement is being done. */ void @@ -1592,29 +1718,47 @@ _rl_move_cursor_relative (new, data) const char *data; { register int i; + int woff; /* number of invisible chars on current line */ + int cpos, dpos; /* current and desired cursor positions */ - /* If we don't have to do anything, then return. */ + woff = W_OFFSET (_rl_last_v_pos, wrap_offset); + cpos = _rl_last_c_pos; #if defined (HANDLE_MULTIBYTE) /* If we have multibyte characters, NEW is indexed by the buffer point in a multibyte string, but _rl_last_c_pos is the display position. In this case, NEW's display position is not obvious and must be - calculated. */ - if (MB_CUR_MAX == 1 || rl_byte_oriented) + calculated. We need to account for invisible characters in this line, + as long as we are past them and they are counted by _rl_col_width. */ + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) { - if (_rl_last_c_pos == new) - return; + dpos = _rl_col_width (data, 0, new); + if (dpos > prompt_last_invisible) /* XXX - don't use woff here */ + { + dpos -= woff; + /* Since this will be assigned to _rl_last_c_pos at the end (more + precisely, _rl_last_c_pos == dpos when this function returns), + let the caller know. */ + cpos_adjusted = 1; + } } - else if (_rl_last_c_pos == _rl_col_width (data, 0, new)) - return; -#else - if (_rl_last_c_pos == new) return; + else #endif + dpos = new; + + /* If we don't have to do anything, then return. */ + if (cpos == dpos) + return; /* It may be faster to output a CR, and then move forwards instead of moving backwards. */ /* i == current physical cursor position. */ - i = _rl_last_c_pos - W_OFFSET(_rl_last_v_pos, visible_wrap_offset); - if (new == 0 || CR_FASTER (new, _rl_last_c_pos) || +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + i = _rl_last_c_pos; + else +#endif + i = _rl_last_c_pos - woff; + if (dpos == 0 || CR_FASTER (dpos, _rl_last_c_pos) || (_rl_term_autowrap && i == _rl_screenwidth)) { #if defined (__MSDOS__) @@ -1622,10 +1766,10 @@ _rl_move_cursor_relative (new, data) #else tputs (_rl_term_cr, 1, _rl_output_character_function); #endif /* !__MSDOS__ */ - _rl_last_c_pos = 0; + cpos = _rl_last_c_pos = 0; } - if (_rl_last_c_pos < new) + if (cpos < dpos) { /* Move the cursor forward. We do it by printing the command to move the cursor forward if there is one, else print that @@ -1636,67 +1780,43 @@ _rl_move_cursor_relative (new, data) sequence telling the terminal to move forward one character. That kind of control is for people who don't know what the data is underneath the cursor. */ -#if defined (HACK_TERMCAP_MOTION) - if (_rl_term_forward_char) + + /* However, we need a handle on where the current display position is + in the buffer for the immediately preceding comment to be true. + In multibyte locales, we don't currently have that info available. + Without it, we don't know where the data we have to display begins + in the buffer and we have to go back to the beginning of the screen + line. In this case, we can use the terminal sequence to move forward + if it's available. */ + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) { - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + if (_rl_term_forward_char) { - int width; - width = _rl_col_width (data, _rl_last_c_pos, new); - for (i = 0; i < width; i++) - tputs (_rl_term_forward_char, 1, _rl_output_character_function); + for (i = cpos; i < dpos; i++) + tputs (_rl_term_forward_char, 1, _rl_output_character_function); } else { - for (i = _rl_last_c_pos; i < new; i++) - tputs (_rl_term_forward_char, 1, _rl_output_character_function); + tputs (_rl_term_cr, 1, _rl_output_character_function); + for (i = 0; i < new; i++) + putc (data[i], rl_outstream); } } - else if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - { - tputs (_rl_term_cr, 1, _rl_output_character_function); - for (i = 0; i < new; i++) - putc (data[i], rl_outstream); - } else - for (i = _rl_last_c_pos; i < new; i++) + for (i = cpos; i < new; i++) putc (data[i], rl_outstream); - -#else /* !HACK_TERMCAP_MOTION */ - - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - { - tputs (_rl_term_cr, 1, _rl_output_character_function); - for (i = 0; i < new; i++) - putc (data[i], rl_outstream); - } - else - for (i = _rl_last_c_pos; i < new; i++) - putc (data[i], rl_outstream); - -#endif /* !HACK_TERMCAP_MOTION */ - } + #if defined (HANDLE_MULTIBYTE) /* NEW points to the buffer point, but _rl_last_c_pos is the display point. The byte length of the string is probably bigger than the column width of the string, which means that if NEW == _rl_last_c_pos, then NEW's display point is less than _rl_last_c_pos. */ - else if (_rl_last_c_pos >= new) -#else - else if (_rl_last_c_pos > new) #endif - { - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - _rl_backspace (_rl_last_c_pos - _rl_col_width (data, 0, new)); - else - _rl_backspace (_rl_last_c_pos - new); - } + else if (cpos > dpos) + _rl_backspace (cpos - dpos); - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - _rl_last_c_pos = _rl_col_width (data, 0, new); - else - _rl_last_c_pos = new; + _rl_last_c_pos = dpos; } /* PWP: move the cursor up or down. */ @@ -1785,9 +1905,9 @@ rl_character_len (c, pos) return ((ISPRINT (uc)) ? 1 : 2); } - /* How to print things in the "echo-area". The prompt is treated as a mini-modeline. */ +static int msg_saved_prompt = 0; #if defined (USE_VARARGS) int @@ -1818,8 +1938,20 @@ rl_message (va_alist) #endif va_end (args); + if (saved_local_prompt == 0) + { + rl_save_prompt (); + msg_saved_prompt = 1; + } rl_display_prompt = msg_buf; + local_prompt = expand_prompt (msg_buf, &prompt_visible_length, + &prompt_last_invisible, + &prompt_invis_chars_first_line, + &prompt_physical_chars); + local_prompt_prefix = (char *)NULL; + local_prompt_len = local_prompt ? strlen (local_prompt) : 0; (*rl_redisplay_function) (); + return 0; } #else /* !USE_VARARGS */ @@ -1829,8 +1961,21 @@ rl_message (format, arg1, arg2) { sprintf (msg_buf, format, arg1, arg2); msg_buf[sizeof(msg_buf) - 1] = '\0'; /* overflow? */ + rl_display_prompt = msg_buf; + if (saved_local_prompt == 0) + { + rl_save_prompt (); + msg_saved_prompt = 1; + } + local_prompt = expand_prompt (msg_buf, &prompt_visible_length, + &prompt_last_invisible, + &prompt_invis_chars_first_line, + &prompt_physical_chars); + local_prompt_prefix = (char *)NULL; + local_prompt_len = local_prompt ? strlen (local_prompt) : 0; (*rl_redisplay_function) (); + return 0; } #endif /* !USE_VARARGS */ @@ -1840,6 +1985,11 @@ int rl_clear_message () { rl_display_prompt = rl_prompt; + if (msg_saved_prompt) + { + rl_restore_prompt (); + msg_saved_prompt = 0; + } (*rl_redisplay_function) (); return 0; } @@ -1849,32 +1999,26 @@ rl_reset_line_state () { rl_on_new_line (); - rl_display_prompt = rl_prompt ? rl_prompt : (char*) ""; + rl_display_prompt = rl_prompt ? rl_prompt : ""; forced_display = 1; return 0; } -/* These are getting numerous enough that it's time to create a struct. */ - -static char *saved_local_prompt; -static char *saved_local_prefix; -static int saved_last_invisible; -static int saved_visible_length; -static int saved_invis_chars_first_line; -static int saved_physical_chars; - void rl_save_prompt () { saved_local_prompt = local_prompt; saved_local_prefix = local_prompt_prefix; + saved_prefix_length = prompt_prefix_length; + saved_local_length = local_prompt_len; saved_last_invisible = prompt_last_invisible; saved_visible_length = prompt_visible_length; saved_invis_chars_first_line = prompt_invis_chars_first_line; saved_physical_chars = prompt_physical_chars; local_prompt = local_prompt_prefix = (char *)0; - prompt_last_invisible = prompt_visible_length = 0; + local_prompt_len = 0; + prompt_last_invisible = prompt_visible_length = prompt_prefix_length = 0; prompt_invis_chars_first_line = prompt_physical_chars = 0; } @@ -1886,10 +2030,18 @@ rl_restore_prompt () local_prompt = saved_local_prompt; local_prompt_prefix = saved_local_prefix; + local_prompt_len = saved_local_length; + prompt_prefix_length = saved_prefix_length; prompt_last_invisible = saved_last_invisible; prompt_visible_length = saved_visible_length; prompt_invis_chars_first_line = saved_invis_chars_first_line; prompt_physical_chars = saved_physical_chars; + + /* can test saved_local_prompt to see if prompt info has been saved. */ + saved_local_prompt = saved_local_prefix = (char *)0; + saved_local_length = 0; + saved_last_invisible = saved_visible_length = saved_prefix_length = 0; + saved_invis_chars_first_line = saved_physical_chars = 0; } char * @@ -1897,11 +2049,15 @@ _rl_make_prompt_for_search (pchar) int pchar; { int len; - char *pmt; + char *pmt, *p; rl_save_prompt (); - if (saved_local_prompt == 0) + /* We've saved the prompt, and can do anything with the various prompt + strings we need before they're restored. We want the unexpanded + portion of the prompt string after any final newline. */ + p = rl_prompt ? strrchr (rl_prompt, '\n') : 0; + if (p == 0) { len = (rl_prompt && *rl_prompt) ? strlen (rl_prompt) : 0; pmt = (char *)xmalloc (len + 2); @@ -1912,17 +2068,17 @@ _rl_make_prompt_for_search (pchar) } else { - len = *saved_local_prompt ? strlen (saved_local_prompt) : 0; + p++; + len = strlen (p); pmt = (char *)xmalloc (len + 2); if (len) - strcpy (pmt, saved_local_prompt); + strcpy (pmt, p); pmt[len] = pchar; pmt[len+1] = '\0'; - local_prompt = savestring (pmt); - prompt_last_invisible = saved_last_invisible; - prompt_visible_length = saved_visible_length + 1; - } + } + /* will be overwritten by expand_prompt, called from rl_message */ + prompt_physical_chars = saved_physical_chars + 1; return pmt; } @@ -1983,6 +2139,9 @@ insert_some_chars (string, count, col) char *string; int count, col; { +#if defined (__MSDOS__) || defined (__MINGW32__) + _rl_output_some_chars (string, count); +#else /* DEBUGGING */ if (MB_CUR_MAX == 1 || rl_byte_oriented) if (count != col) @@ -2021,6 +2180,7 @@ insert_some_chars (string, count, col) if (_rl_term_ei && *_rl_term_ei) tputs (_rl_term_ei, 1, _rl_output_character_function); } +#endif /* __MSDOS__ || __MINGW32__ */ } /* Delete COUNT characters from the display line. */ @@ -2031,6 +2191,7 @@ delete_chars (count) if (count > _rl_screenwidth) /* XXX */ return; +#if !defined (__MSDOS__) && !defined (__MINGW32__) if (_rl_term_DC && *_rl_term_DC) { char *buffer; @@ -2043,6 +2204,7 @@ delete_chars (count) while (count--) tputs (_rl_term_dc, 1, _rl_output_character_function); } +#endif /* !__MSDOS__ && !__MINGW32__ */ } void @@ -2066,7 +2228,8 @@ _rl_update_final () char *last_line; last_line = &visible_line[vis_lbreaks[_rl_vis_botlin]]; - _rl_move_cursor_relative (_rl_screenwidth - 1, last_line); + cpos_buffer_position = -1; /* don't know where we are in buffer */ + _rl_move_cursor_relative (_rl_screenwidth - 1, last_line); /* XXX */ _rl_clear_to_eol (0); putc (last_line[_rl_screenwidth - 1], rl_outstream); } @@ -2098,18 +2261,10 @@ static void redraw_prompt (t) char *t; { - char *oldp, *oldl, *oldlprefix; - int oldlen, oldlast, oldplen, oldninvis, oldphyschars; + char *oldp; - /* Geez, I should make this a struct. */ oldp = rl_display_prompt; - oldl = local_prompt; - oldlprefix = local_prompt_prefix; - oldlen = prompt_visible_length; - oldplen = prompt_prefix_length; - oldlast = prompt_last_invisible; - oldninvis = prompt_invis_chars_first_line; - oldphyschars = prompt_physical_chars; + rl_save_prompt (); rl_display_prompt = t; local_prompt = expand_prompt (t, &prompt_visible_length, @@ -2117,16 +2272,12 @@ redraw_prompt (t) &prompt_invis_chars_first_line, &prompt_physical_chars); local_prompt_prefix = (char *)NULL; + local_prompt_len = local_prompt ? strlen (local_prompt) : 0; + rl_forced_update_display (); rl_display_prompt = oldp; - local_prompt = oldl; - local_prompt_prefix = oldlprefix; - prompt_visible_length = oldlen; - prompt_prefix_length = oldplen; - prompt_last_invisible = oldlast; - prompt_invis_chars_first_line = oldninvis; - prompt_physical_chars = oldphyschars; + rl_restore_prompt(); } /* Redisplay the current line after a SIGWINCH is received. */ @@ -2230,10 +2381,11 @@ _rl_col_width (str, start, end) if (end <= start) return 0; + memset (&ps, 0, sizeof (mbstate_t)); + point = 0; max = end; - memset (&ps, 0, sizeof(ps)); while (point < start) { tmp = mbrlen (str + point, max, &ps); diff --git a/cmd-line-utils/readline/funmap.c b/cmd-line-utils/readline/funmap.c index d56ffb9fadc..9c760cc3475 100644 --- a/cmd-line-utils/readline/funmap.c +++ b/cmd-line-utils/readline/funmap.c @@ -21,7 +21,9 @@ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #define READLINE_LIBRARY -#include "config_readline.h" +#if defined (HAVE_CONFIG_H) +# include +#endif #if !defined (BUFSIZ) #include @@ -174,6 +176,7 @@ static FUNMAP default_funmap[] = { { "vi-put", rl_vi_put }, { "vi-redo", rl_vi_redo }, { "vi-replace", rl_vi_replace }, + { "vi-rubout", rl_vi_rubout }, { "vi-search", rl_vi_search }, { "vi-search-again", rl_vi_search_again }, { "vi-set-mark", rl_vi_set_mark }, diff --git a/cmd-line-utils/readline/histexpand.c b/cmd-line-utils/readline/histexpand.c index 0a45438990a..f46c0b2a45d 100644 --- a/cmd-line-utils/readline/histexpand.c +++ b/cmd-line-utils/readline/histexpand.c @@ -22,7 +22,9 @@ #define READLINE_LIBRARY -#include "config_readline.h" +#if defined (HAVE_CONFIG_H) +# include +#endif #include @@ -54,8 +56,6 @@ typedef int _hist_search_func_t PARAMS((const char *, int)); -extern int rl_byte_oriented; /* declared in mbutil.c */ - static char error_pointer; static char *subst_lhs; @@ -87,14 +87,14 @@ char history_comment_char = '\0'; /* The list of characters which inhibit the expansion of text if found immediately following history_expansion_char. */ -char *history_no_expand_chars = (char*) " \t\n\r="; +char *history_no_expand_chars = " \t\n\r="; /* If set to a non-zero value, single quotes inhibit history expansion. The default is 0. */ int history_quotes_inhibit_expansion = 0; /* Used to split words by history_tokenize_internal. */ -char *history_word_delimiters = (char*) HISTORY_WORD_DELIMITERS; +char *history_word_delimiters = HISTORY_WORD_DELIMITERS; /* If set, this points to a function that is called to verify that a particular history expansion should be performed. */ @@ -203,24 +203,25 @@ get_history_event (string, caller_index, delimiting_quote) } /* Only a closing `?' or a newline delimit a substring search string. */ - for (local_index = i; (c = string[i]); i++) + for (local_index = i; c = string[i]; i++) + { #if defined (HANDLE_MULTIBYTE) - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - { - int v; - mbstate_t ps; + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + { + int v; + mbstate_t ps; + + memset (&ps, 0, sizeof (mbstate_t)); + /* These produce warnings because we're passing a const string to a + function that takes a non-const string. */ + _rl_adjust_point ((char *)string, i, &ps); + if ((v = _rl_get_char_len ((char *)string + i, &ps)) > 1) + { + i += v - 1; + continue; + } + } - memset (&ps, 0, sizeof (mbstate_t)); - /* These produce warnings because we're passing a const string to a - function that takes a non-const string. */ - _rl_adjust_point ((char *)string, i, &ps); - if ((v = _rl_get_char_len ((char *)string + i, &ps)) > 1) - { - i += v - 1; - continue; - } - } - else #endif /* HANDLE_MULTIBYTE */ if ((!substring_okay && (whitespace (c) || c == ':' || (history_search_delimiter_chars && member (c, history_search_delimiter_chars)) || @@ -228,6 +229,7 @@ get_history_event (string, caller_index, delimiting_quote) string[i] == '\n' || (substring_okay && string[i] == '?')) break; + } which = i - local_index; temp = (char *)xmalloc (1 + which); @@ -560,12 +562,12 @@ history_expand_internal (string, start, end_index_ptr, ret_string, current_line) #if defined (HANDLE_MULTIBYTE) if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) { - int chr, l; + int ch, l; l = _rl_find_prev_mbchar (string, i, MB_FIND_ANY); - chr = string[l]; + ch = string[l]; /* XXX - original patch had i - 1 ??? If i == 0 it would fail. */ - if (i && (chr == '\'' || chr == '"')) - quoted_search_delimiter = chr; + if (i && (ch == '\'' || ch == '"')) + quoted_search_delimiter = ch; } else #endif /* HANDLE_MULTIBYTE */ @@ -1426,6 +1428,8 @@ history_tokenize_word (string, ind) { if (peek == '<' && string[i + 2] == '-') i++; + else if (peek == '<' && string[i + 2] == '<') + i++; i += 2; return i; } diff --git a/cmd-line-utils/readline/histfile.c b/cmd-line-utils/readline/histfile.c index f1822b105a4..2f051a32563 100644 --- a/cmd-line-utils/readline/histfile.c +++ b/cmd-line-utils/readline/histfile.c @@ -30,7 +30,9 @@ # include #endif -#include "config_readline.h" +#if defined (HAVE_CONFIG_H) +# include +#endif #include @@ -184,8 +186,7 @@ read_history_range (filename, from, to) file_size = (size_t)finfo.st_size; /* check for overflow on very large files */ - if ((long long) file_size != (long long) finfo.st_size || - file_size + 1 < file_size) + if (file_size != finfo.st_size || file_size + 1 < file_size) { errno = overflow_errno; goto error_and_exit; @@ -255,7 +256,11 @@ read_history_range (filename, from, to) for (line_end = line_start; line_end < bufend; line_end++) if (*line_end == '\n') { - *line_end = '\0'; + /* Change to allow Windows-like \r\n end of line delimiter. */ + if (line_end > line_start && line_end[-1] == '\r') + line_end[-1] = '\0'; + else + *line_end = '\0'; if (*line_start) { @@ -334,8 +339,7 @@ history_truncate_file (fname, lines) file_size = (size_t)finfo.st_size; /* check for overflow on very large files */ - if ((long long) file_size != (long long) finfo.st_size || - file_size + 1 < file_size) + if (file_size != finfo.st_size || file_size + 1 < file_size) { close (file); #if defined (EFBIG) diff --git a/cmd-line-utils/readline/history.c b/cmd-line-utils/readline/history.c index bb1960d8d99..1ccf4db786c 100644 --- a/cmd-line-utils/readline/history.c +++ b/cmd-line-utils/readline/history.c @@ -1,6 +1,6 @@ /* history.c -- standalone history library */ -/* Copyright (C) 1989-2003 Free Software Foundation, Inc. +/* Copyright (C) 1989-2005 Free Software Foundation, Inc. This file contains the GNU History Library (the Library), a set of routines for managing the text of previously typed lines. @@ -25,7 +25,9 @@ you can call. I think I have done that. */ #define READLINE_LIBRARY -#include "config_readline.h" +#if defined (HAVE_CONFIG_H) +# include +#endif #include @@ -202,11 +204,27 @@ history_get (offset) int local_index; local_index = offset - history_base; - return (local_index >= history_length || local_index < 0 || !the_history) + return (local_index >= history_length || local_index < 0 || the_history == 0) ? (HIST_ENTRY *)NULL : the_history[local_index]; } +HIST_ENTRY * +alloc_history_entry (string, ts) + char *string; + char *ts; +{ + HIST_ENTRY *temp; + + temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY)); + + temp->line = string ? savestring (string) : string; + temp->data = (char *)NULL; + temp->timestamp = ts; + + return temp; +} + time_t history_get_time (hist) HIST_ENTRY *hist; @@ -288,11 +306,7 @@ add_history (string) } } - temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY)); - temp->line = savestring (string); - temp->data = (char *)NULL; - - temp->timestamp = hist_inittime (); + temp = alloc_history_entry (string, hist_inittime ()); the_history[history_length] = (HIST_ENTRY *)NULL; the_history[history_length - 1] = temp; @@ -326,6 +340,26 @@ free_history_entry (hist) free (hist); return (x); } + +HIST_ENTRY * +copy_history_entry (hist) + HIST_ENTRY *hist; +{ + HIST_ENTRY *ret; + char *ts; + + if (hist == 0) + return hist; + + ret = alloc_history_entry (hist->line, (char *)NULL); + + ts = hist->timestamp ? savestring (hist->timestamp) : hist->timestamp; + ret->timestamp = ts; + + ret->data = hist->data; + + return ret; +} /* Make the history entry at WHICH have LINE and DATA. This returns the old entry so you can dispose of the data. In the case of an @@ -338,7 +372,7 @@ replace_history_entry (which, line, data) { HIST_ENTRY *temp, *old_value; - if (which >= history_length) + if (which < 0 || which >= history_length) return ((HIST_ENTRY *)NULL); temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY)); @@ -352,6 +386,51 @@ replace_history_entry (which, line, data) return (old_value); } +/* Replace the DATA in the specified history entries, replacing OLD with + NEW. WHICH says which one(s) to replace: WHICH == -1 means to replace + all of the history entries where entry->data == OLD; WHICH == -2 means + to replace the `newest' history entry where entry->data == OLD; and + WHICH >= 0 means to replace that particular history entry's data, as + long as it matches OLD. */ +void +replace_history_data (which,old, new) + int which; + histdata_t *old, *new; +{ + HIST_ENTRY *entry; + register int i, last; + + if (which < -2 || which >= history_length || history_length == 0 || the_history == 0) + return; + + if (which >= 0) + { + entry = the_history[which]; + if (entry && entry->data == old) + entry->data = new; + return; + } + + last = -1; + for (i = 0; i < history_length; i++) + { + entry = the_history[i]; + if (entry == 0) + continue; + if (entry->data == old) + { + last = i; + if (which == -1) + entry->data = new; + } + } + if (which == -2 && last >= 0) + { + entry = the_history[last]; + entry->data = new; /* XXX - we don't check entry->old */ + } +} + /* Remove history element WHICH from the history. The removed element is returned to you so you can free the line, data, and containing structure. */ @@ -362,17 +441,15 @@ remove_history (which) HIST_ENTRY *return_value; register int i; - if (which >= history_length || !history_length) - return_value = (HIST_ENTRY *)NULL; - else - { - return_value = the_history[which]; + if (which < 0 || which >= history_length || history_length == 0 || the_history == 0) + return ((HIST_ENTRY *)NULL); - for (i = which; i < history_length; i++) - the_history[i] = the_history[i + 1]; + return_value = the_history[which]; - history_length--; - } + for (i = which; i < history_length; i++) + the_history[i] = the_history[i + 1]; + + history_length--; return (return_value); } diff --git a/cmd-line-utils/readline/histsearch.c b/cmd-line-utils/readline/histsearch.c index 778b323afdc..1cc5875a4b4 100644 --- a/cmd-line-utils/readline/histsearch.c +++ b/cmd-line-utils/readline/histsearch.c @@ -22,7 +22,9 @@ #define READLINE_LIBRARY -#include "config_readline.h" +#if defined (HAVE_CONFIG_H) +# include +#endif #include #if defined (HAVE_STDLIB_H) diff --git a/cmd-line-utils/readline/input.c b/cmd-line-utils/readline/input.c index 818f2e8763d..da5d771c481 100644 --- a/cmd-line-utils/readline/input.c +++ b/cmd-line-utils/readline/input.c @@ -1,6 +1,6 @@ /* input.c -- character input functions for readline. */ -/* Copyright (C) 1994 Free Software Foundation, Inc. +/* Copyright (C) 1994-2005 Free Software Foundation, Inc. This file is part of the GNU Readline Library, a library for reading lines of text with interactive input and history editing. @@ -25,7 +25,9 @@ # include #endif -#include "config_readline.h" +#if defined (HAVE_CONFIG_H) +# include +#endif #include #include @@ -177,6 +179,7 @@ rl_gather_tyi () struct timeval timeout; #endif + chars_avail = 0; tty = fileno (rl_instream); #if defined (HAVE_SELECT) @@ -218,6 +221,13 @@ rl_gather_tyi () } #endif /* O_NDELAY */ +#if defined (__MINGW32__) + /* Use getch/_kbhit to check for available console input, in the same way + that we read it normally. */ + chars_avail = isatty (tty) ? _kbhit () : 0; + result = 0; +#endif + /* If there's nothing available, don't waste time trying to read something. */ if (chars_avail <= 0) @@ -261,7 +271,7 @@ rl_set_keyboard_input_timeout (u) int o; o = _keyboard_input_timeout; - if (u > 0) + if (u >= 0) _keyboard_input_timeout = u; return (o); } @@ -301,6 +311,11 @@ _rl_input_available () return (chars_avail); #endif +#endif + +#if defined (__MINGW32__) + if (isatty (tty)) + return (_kbhit ()); #endif return 0; @@ -405,7 +420,7 @@ rl_read_key () else { /* If input is coming from a macro, then use that. */ - if ((c= _rl_next_macro_key ())) + if (c = _rl_next_macro_key ()) return (c); /* If the user has an event function, then call it periodically. */ @@ -442,6 +457,10 @@ rl_getc (stream) while (1) { +#if defined (__MINGW32__) + if (isatty (fileno (stream))) + return (getch ()); +#endif result = read (fileno (stream), &c, sizeof (unsigned char)); if (result == sizeof (unsigned char)) @@ -483,7 +502,7 @@ rl_getc (stream) this is simply an interrupted system call to read (). Otherwise, some error ocurred, also signifying EOF. */ if (errno != EINTR) - return (EOF); + return (RL_ISSTATE (RL_STATE_READCMD) ? READERR : EOF); } } @@ -517,6 +536,12 @@ _rl_read_mbchar (mbchar, size) ps = ps_back; continue; } + else if (mbchar_bytes_length == 0) + { + mbchar[0] = '\0'; /* null wide character */ + mb_len = 1; + break; + } else if (mbchar_bytes_length > (size_t)(0)) break; } @@ -525,21 +550,21 @@ _rl_read_mbchar (mbchar, size) } /* Read a multibyte-character string whose first character is FIRST into - the buffer MB of length MBLEN. Returns the last character read, which + the buffer MB of length MLEN. Returns the last character read, which may be FIRST. Used by the search functions, among others. Very similar to _rl_read_mbchar. */ int -_rl_read_mbstring (first, mb, mb_len) +_rl_read_mbstring (first, mb, mlen) int first; char *mb; - int mb_len; + int mlen; { int i, c; mbstate_t ps; c = first; - memset (mb, 0, mb_len); - for (i = 0; i < mb_len; i++) + memset (mb, 0, mlen); + for (i = 0; i < mlen; i++) { mb[i] = (char)c; memset (&ps, 0, sizeof (mbstate_t)); diff --git a/cmd-line-utils/readline/isearch.c b/cmd-line-utils/readline/isearch.c index 9071695dda8..9f67bfc0801 100644 --- a/cmd-line-utils/readline/isearch.c +++ b/cmd-line-utils/readline/isearch.c @@ -4,7 +4,7 @@ /* */ /* **************************************************************** */ -/* Copyright (C) 1987-2002 Free Software Foundation, Inc. +/* Copyright (C) 1987-2005 Free Software Foundation, Inc. This file contains the Readline Library (the Library), a set of routines for providing Emacs style line input to programs that ask @@ -26,7 +26,9 @@ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #define READLINE_LIBRARY -#include "config_readline.h" +#if defined (HAVE_CONFIG_H) +# include +#endif #include @@ -54,21 +56,77 @@ /* Variables exported to other files in the readline library. */ char *_rl_isearch_terminators = (char *)NULL; +_rl_search_cxt *_rl_iscxt = 0; + /* Variables imported from other files in the readline library. */ extern HIST_ENTRY *_rl_saved_line_for_history; -/* Forward declarations */ static int rl_search_history PARAMS((int, int)); +static _rl_search_cxt *_rl_isearch_init PARAMS((int)); +static void _rl_isearch_fini PARAMS((_rl_search_cxt *)); +static int _rl_isearch_cleanup PARAMS((_rl_search_cxt *, int)); + /* Last line found by the current incremental search, so we don't `find' - identical lines many times in a row. */ -static char *prev_line_found; + identical lines many times in a row. Now part of isearch context. */ +/* static char *prev_line_found; */ /* Last search string and its length. */ static char *last_isearch_string; static int last_isearch_string_len; -static char *default_isearch_terminators = (char*) "\033\012"; +static char *default_isearch_terminators = "\033\012"; + +_rl_search_cxt * +_rl_scxt_alloc (type, flags) + int type, flags; +{ + _rl_search_cxt *cxt; + + cxt = (_rl_search_cxt *)xmalloc (sizeof (_rl_search_cxt)); + + cxt->type = type; + cxt->sflags = flags; + + cxt->search_string = 0; + cxt->search_string_size = cxt->search_string_index = 0; + + cxt->lines = 0; + cxt->allocated_line = 0; + cxt->hlen = cxt->hindex = 0; + + cxt->save_point = rl_point; + cxt->save_mark = rl_mark; + cxt->save_line = where_history (); + cxt->last_found_line = cxt->save_line; + cxt->prev_line_found = 0; + + cxt->save_undo_list = 0; + + cxt->history_pos = 0; + cxt->direction = 0; + + cxt->lastc = 0; + + cxt->sline = 0; + cxt->sline_len = cxt->sline_index = 0; + + cxt->search_terminators = 0; + + return cxt; +} + +void +_rl_scxt_dispose (cxt, flags) + _rl_search_cxt *cxt; + int flags; +{ + FREE (cxt->search_string); + FREE (cxt->allocated_line); + FREE (cxt->lines); + + free (cxt); +} /* Search backwards through the history looking for a string which is typed interactively. Start with the current line. */ @@ -90,12 +148,13 @@ rl_forward_search_history (sign, key) /* Display the current state of the search in the echo-area. SEARCH_STRING contains the string that is being searched for, - DIRECTION is zero for forward, or 1 for reverse, + DIRECTION is zero for forward, or non-zero for reverse, WHERE is the history list number of the current line. If it is -1, then this line is the starting one. */ static void -rl_display_search (char *search_string, int reverse_p, - int where __attribute__((unused))) +rl_display_search (search_string, reverse_p, where) + char *search_string; + int reverse_p, where; { char *message; int msglen, searchlen; @@ -137,65 +196,23 @@ rl_display_search (char *search_string, int reverse_p, (*rl_redisplay_function) (); } -/* Search through the history looking for an interactively typed string. - This is analogous to i-search. We start the search in the current line. - DIRECTION is which direction to search; >= 0 means forward, < 0 means - backwards. */ -static int -rl_search_history (int direction, int invoking_key __attribute__((unused))) +static _rl_search_cxt * +_rl_isearch_init (direction) + int direction; { - /* The string that the user types in to search for. */ - char *search_string; - - /* The current length of SEARCH_STRING. */ - int search_string_index; - - /* The amount of space that SEARCH_STRING has allocated to it. */ - int search_string_size; - - /* The list of lines to search through. */ - char **lines, *allocated_line; - - /* The length of LINES. */ - int hlen; - - /* Where we get LINES from. */ + _rl_search_cxt *cxt; + register int i; HIST_ENTRY **hlist; - register int i; - int orig_point, orig_mark, orig_line, last_found_line; - int c, found, failed, sline_len; - int n, wstart, wlen; -#if defined (HANDLE_MULTIBYTE) - char mb[MB_LEN_MAX]; -#endif + cxt = _rl_scxt_alloc (RL_SEARCH_ISEARCH, 0); + if (direction < 0) + cxt->sflags |= SF_REVERSE; - /* The line currently being searched. */ - char *sline; - - /* Offset in that line. */ - int line_index; - - /* Non-zero if we are doing a reverse search. */ - int reverse; - - /* The list of characters which terminate the search, but are not - subsequently executed. If the variable isearch-terminators has - been set, we use that value, otherwise we use ESC and C-J. */ - char *isearch_terminators; - - RL_SETSTATE(RL_STATE_ISEARCH); - orig_point = rl_point; - orig_mark = rl_mark; - last_found_line = orig_line = where_history (); - reverse = direction < 0; - hlist = history_list (); - allocated_line = (char *)NULL; - - isearch_terminators = _rl_isearch_terminators ? _rl_isearch_terminators + cxt->search_terminators = _rl_isearch_terminators ? _rl_isearch_terminators : default_isearch_terminators; /* Create an arrary of pointers to the lines that we want to search. */ + hlist = history_list (); rl_maybe_replace_line (); i = 0; if (hlist) @@ -203,354 +220,447 @@ rl_search_history (int direction, int invoking_key __attribute__((unused))) /* Allocate space for this many lines, +1 for the current input line, and remember those lines. */ - lines = (char **)xmalloc ((1 + (hlen = i)) * sizeof (char *)); - for (i = 0; i < hlen; i++) - lines[i] = hlist[i]->line; + cxt->lines = (char **)xmalloc ((1 + (cxt->hlen = i)) * sizeof (char *)); + for (i = 0; i < cxt->hlen; i++) + cxt->lines[i] = hlist[i]->line; if (_rl_saved_line_for_history) - lines[i] = _rl_saved_line_for_history->line; + cxt->lines[i] = _rl_saved_line_for_history->line; else { /* Keep track of this so we can free it. */ - allocated_line = (char *)xmalloc (1 + strlen (rl_line_buffer)); - strcpy (allocated_line, &rl_line_buffer[0]); - lines[i] = allocated_line; + cxt->allocated_line = (char *)xmalloc (1 + strlen (rl_line_buffer)); + strcpy (cxt->allocated_line, &rl_line_buffer[0]); + cxt->lines[i] = cxt->allocated_line; } - hlen++; + cxt->hlen++; /* The line where we start the search. */ - i = orig_line; + cxt->history_pos = cxt->save_line; rl_save_prompt (); /* Initialize search parameters. */ - search_string = (char *)xmalloc (search_string_size = 128); - *search_string = '\0'; - search_string_index = 0; - prev_line_found = (char *)0; /* XXX */ + cxt->search_string = (char *)xmalloc (cxt->search_string_size = 128); + cxt->search_string[cxt->search_string_index = 0] = '\0'; /* Normalize DIRECTION into 1 or -1. */ - direction = (direction >= 0) ? 1 : -1; + cxt->direction = (direction >= 0) ? 1 : -1; - rl_display_search (search_string, reverse, -1); + cxt->sline = rl_line_buffer; + cxt->sline_len = strlen (cxt->sline); + cxt->sline_index = rl_point; - sline = rl_line_buffer; - sline_len = strlen (sline); - line_index = rl_point; + _rl_iscxt = cxt; /* save globally */ - found = failed = 0; - for (;;) + return cxt; +} + +static void +_rl_isearch_fini (cxt) + _rl_search_cxt *cxt; +{ + /* First put back the original state. */ + strcpy (rl_line_buffer, cxt->lines[cxt->save_line]); + + rl_restore_prompt (); + + /* Save the search string for possible later use. */ + FREE (last_isearch_string); + last_isearch_string = cxt->search_string; + last_isearch_string_len = cxt->search_string_index; + cxt->search_string = 0; + + if (cxt->last_found_line < cxt->save_line) + rl_get_previous_history (cxt->save_line - cxt->last_found_line, 0); + else + rl_get_next_history (cxt->last_found_line - cxt->save_line, 0); + + /* If the string was not found, put point at the end of the last matching + line. If last_found_line == orig_line, we didn't find any matching + history lines at all, so put point back in its original position. */ + if (cxt->sline_index < 0) { - rl_command_func_t *f = (rl_command_func_t *)NULL; + if (cxt->last_found_line == cxt->save_line) + cxt->sline_index = cxt->save_point; + else + cxt->sline_index = strlen (rl_line_buffer); + rl_mark = cxt->save_mark; + } - /* Read a key and decide how to proceed. */ - RL_SETSTATE(RL_STATE_MOREINPUT); - c = rl_read_key (); - RL_UNSETSTATE(RL_STATE_MOREINPUT); + rl_point = cxt->sline_index; + /* Don't worry about where to put the mark here; rl_get_previous_history + and rl_get_next_history take care of it. */ + + rl_clear_message (); +} + +int +_rl_search_getchar (cxt) + _rl_search_cxt *cxt; +{ + int c; + + /* Read a key and decide how to proceed. */ + RL_SETSTATE(RL_STATE_MOREINPUT); + c = cxt->lastc = rl_read_key (); + RL_UNSETSTATE(RL_STATE_MOREINPUT); #if defined (HANDLE_MULTIBYTE) - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - c = _rl_read_mbstring (c, mb, MB_LEN_MAX); + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + c = cxt->lastc = _rl_read_mbstring (cxt->lastc, cxt->mb, MB_LEN_MAX); #endif - /* Translate the keys we do something with to opcodes. */ - if (c >= 0 && _rl_keymap[c].type == ISFUNC) - { - f = _rl_keymap[c].function; + return c; +} - if (f == rl_reverse_search_history) - c = reverse ? -1 : -2; - else if (f == rl_forward_search_history) - c = !reverse ? -1 : -2; - else if (f == rl_rubout) - c = -3; - else if (c == CTRL ('G')) - c = -4; - else if (c == CTRL ('W')) /* XXX */ - c = -5; - else if (c == CTRL ('Y')) /* XXX */ - c = -6; - } +/* Process just-read character C according to isearch context CXT. Return + -1 if the caller should just free the context and return, 0 if we should + break out of the loop, and 1 if we should continue to read characters. */ +int +_rl_isearch_dispatch (cxt, c) + _rl_search_cxt *cxt; + int c; +{ + int n, wstart, wlen, limit, cval; + rl_command_func_t *f; - /* The characters in isearch_terminators (set from the user-settable - variable isearch-terminators) are used to terminate the search but - not subsequently execute the character as a command. The default - value is "\033\012" (ESC and C-J). */ - if (strchr (isearch_terminators, c)) - { - /* ESC still terminates the search, but if there is pending - input or if input arrives within 0.1 seconds (on systems - with select(2)) it is used as a prefix character - with rl_execute_next. WATCH OUT FOR THIS! This is intended - to allow the arrow keys to be used like ^F and ^B are used - to terminate the search and execute the movement command. - XXX - since _rl_input_available depends on the application- - settable keyboard timeout value, this could alternatively - use _rl_input_queued(100000) */ - if (c == ESC && _rl_input_available ()) - rl_execute_next (ESC); - break; - } + f = (rl_command_func_t *)NULL; + + /* Translate the keys we do something with to opcodes. */ + if (c >= 0 && _rl_keymap[c].type == ISFUNC) + { + f = _rl_keymap[c].function; + + if (f == rl_reverse_search_history) + cxt->lastc = (cxt->sflags & SF_REVERSE) ? -1 : -2; + else if (f == rl_forward_search_history) + cxt->lastc = (cxt->sflags & SF_REVERSE) ? -2 : -1; + else if (f == rl_rubout) + cxt->lastc = -3; + else if (c == CTRL ('G')) + cxt->lastc = -4; + else if (c == CTRL ('W')) /* XXX */ + cxt->lastc = -5; + else if (c == CTRL ('Y')) /* XXX */ + cxt->lastc = -6; + } + + /* The characters in isearch_terminators (set from the user-settable + variable isearch-terminators) are used to terminate the search but + not subsequently execute the character as a command. The default + value is "\033\012" (ESC and C-J). */ + if (strchr (cxt->search_terminators, cxt->lastc)) + { + /* ESC still terminates the search, but if there is pending + input or if input arrives within 0.1 seconds (on systems + with select(2)) it is used as a prefix character + with rl_execute_next. WATCH OUT FOR THIS! This is intended + to allow the arrow keys to be used like ^F and ^B are used + to terminate the search and execute the movement command. + XXX - since _rl_input_available depends on the application- + settable keyboard timeout value, this could alternatively + use _rl_input_queued(100000) */ + if (cxt->lastc == ESC && _rl_input_available ()) + rl_execute_next (ESC); + return (0); + } #define ENDSRCH_CHAR(c) \ ((CTRL_CHAR (c) || META_CHAR (c) || (c) == RUBOUT) && ((c) != CTRL ('G'))) #if defined (HANDLE_MULTIBYTE) - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - { - if (c >= 0 && strlen (mb) == 1 && ENDSRCH_CHAR (c)) - { - /* This sets rl_pending_input to c; it will be picked up the next - time rl_read_key is called. */ - rl_execute_next (c); - break; - } - } - else -#endif - if (c >= 0 && ENDSRCH_CHAR (c)) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + { + if (cxt->lastc >= 0 && (cxt->mb[0] && cxt->mb[1] == '\0') && ENDSRCH_CHAR (cxt->lastc)) { /* This sets rl_pending_input to c; it will be picked up the next time rl_read_key is called. */ - rl_execute_next (c); - break; + rl_execute_next (cxt->lastc); + return (0); } - - switch (c) - { - case -1: - if (search_string_index == 0) - { - if (last_isearch_string) - { - search_string_size = 64 + last_isearch_string_len; - search_string = (char *)xrealloc (search_string, search_string_size); - strcpy (search_string, last_isearch_string); - search_string_index = last_isearch_string_len; - rl_display_search (search_string, reverse, -1); - break; - } - continue; - } - else if (reverse) - --line_index; - else if (line_index != sline_len) - ++line_index; - else - rl_ding (); - break; - - /* switch directions */ - case -2: - direction = -direction; - reverse = direction < 0; - break; - - /* delete character from search string. */ - case -3: /* C-H, DEL */ - /* This is tricky. To do this right, we need to keep a - stack of search positions for the current search, with - sentinels marking the beginning and end. But this will - do until we have a real isearch-undo. */ - if (search_string_index == 0) - rl_ding (); - else - search_string[--search_string_index] = '\0'; - - break; - - case -4: /* C-G */ - rl_replace_line (lines[orig_line], 0); - rl_point = orig_point; - rl_mark = orig_mark; - rl_restore_prompt(); - rl_clear_message (); - if (allocated_line) - free (allocated_line); - free (lines); - RL_UNSETSTATE(RL_STATE_ISEARCH); - return 0; - - case -5: /* C-W */ - /* skip over portion of line we already matched */ - wstart = rl_point + search_string_index; - if (wstart >= rl_end) - { - rl_ding (); - break; - } - - /* if not in a word, move to one. */ - if (rl_alphabetic(rl_line_buffer[wstart]) == 0) - { - rl_ding (); - break; - } - n = wstart; - while (n < rl_end && rl_alphabetic(rl_line_buffer[n])) - n++; - wlen = n - wstart + 1; - if (search_string_index + wlen + 1 >= search_string_size) - { - search_string_size += wlen + 1; - search_string = (char *)xrealloc (search_string, search_string_size); - } - for (; wstart < n; wstart++) - search_string[search_string_index++] = rl_line_buffer[wstart]; - search_string[search_string_index] = '\0'; - break; - - case -6: /* C-Y */ - /* skip over portion of line we already matched */ - wstart = rl_point + search_string_index; - if (wstart >= rl_end) - { - rl_ding (); - break; - } - n = rl_end - wstart + 1; - if (search_string_index + n + 1 >= search_string_size) - { - search_string_size += n + 1; - search_string = (char *)xrealloc (search_string, search_string_size); - } - for (n = wstart; n < rl_end; n++) - search_string[search_string_index++] = rl_line_buffer[n]; - search_string[search_string_index] = '\0'; - break; - - default: - /* Add character to search string and continue search. */ - if (search_string_index + 2 >= search_string_size) - { - search_string_size += 128; - search_string = (char *)xrealloc (search_string, search_string_size); - } -#if defined (HANDLE_MULTIBYTE) - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - { - int j, l; - for (j = 0, l = strlen (mb); j < l; ) - search_string[search_string_index++] = mb[j++]; - } - else + } + else #endif - search_string[search_string_index++] = c; - search_string[search_string_index] = '\0'; + if (cxt->lastc >= 0 && ENDSRCH_CHAR (cxt->lastc)) + { + /* This sets rl_pending_input to LASTC; it will be picked up the next + time rl_read_key is called. */ + rl_execute_next (cxt->lastc); + return (0); + } + + /* Now dispatch on the character. `Opcodes' affect the search string or + state. Other characters are added to the string. */ + switch (cxt->lastc) + { + /* search again */ + case -1: + if (cxt->search_string_index == 0) + { + if (last_isearch_string) + { + cxt->search_string_size = 64 + last_isearch_string_len; + cxt->search_string = (char *)xrealloc (cxt->search_string, cxt->search_string_size); + strcpy (cxt->search_string, last_isearch_string); + cxt->search_string_index = last_isearch_string_len; + rl_display_search (cxt->search_string, (cxt->sflags & SF_REVERSE), -1); + break; + } + return (1); + } + else if (cxt->sflags & SF_REVERSE) + cxt->sline_index--; + else if (cxt->sline_index != cxt->sline_len) + cxt->sline_index++; + else + rl_ding (); + break; + + /* switch directions */ + case -2: + cxt->direction = -cxt->direction; + if (cxt->direction < 0) + cxt->sflags |= SF_REVERSE; + else + cxt->sflags &= ~SF_REVERSE; + break; + + /* delete character from search string. */ + case -3: /* C-H, DEL */ + /* This is tricky. To do this right, we need to keep a + stack of search positions for the current search, with + sentinels marking the beginning and end. But this will + do until we have a real isearch-undo. */ + if (cxt->search_string_index == 0) + rl_ding (); + else + cxt->search_string[--cxt->search_string_index] = '\0'; + break; + + case -4: /* C-G, abort */ + rl_replace_line (cxt->lines[cxt->save_line], 0); + rl_point = cxt->save_point; + rl_mark = cxt->save_mark; + rl_restore_prompt(); + rl_clear_message (); + + return -1; + + case -5: /* C-W */ + /* skip over portion of line we already matched and yank word */ + wstart = rl_point + cxt->search_string_index; + if (wstart >= rl_end) + { + rl_ding (); break; } - for (found = failed = 0;;) + /* if not in a word, move to one. */ + cval = _rl_char_value (rl_line_buffer, wstart); + if (_rl_walphabetic (cval) == 0) { - int limit = sline_len - search_string_index + 1; - - /* Search the current line. */ - while (reverse ? (line_index >= 0) : (line_index < limit)) - { - if (STREQN (search_string, sline + line_index, search_string_index)) - { - found++; - break; - } - else - line_index += direction; - } - if (found) - break; - - /* Move to the next line, but skip new copies of the line - we just found and lines shorter than the string we're - searching for. */ - do - { - /* Move to the next line. */ - i += direction; - - /* At limit for direction? */ - if (reverse ? (i < 0) : (i == hlen)) - { - failed++; - break; - } - - /* We will need these later. */ - sline = lines[i]; - sline_len = strlen (sline); - } - while ((prev_line_found && STREQ (prev_line_found, lines[i])) || - (search_string_index > sline_len)); - - if (failed) - break; - - /* Now set up the line for searching... */ - line_index = reverse ? sline_len - search_string_index : 0; - } - - if (failed) - { - /* We cannot find the search string. Ding the bell. */ rl_ding (); - i = last_found_line; - continue; /* XXX - was break */ + break; } - - /* We have found the search string. Just display it. But don't - actually move there in the history list until the user accepts - the location. */ - if (found) + n = MB_NEXTCHAR (rl_line_buffer, wstart, 1, MB_FIND_NONZERO);; + while (n < rl_end) { - prev_line_found = lines[i]; - rl_replace_line (lines[i], 0); - rl_point = line_index; - last_found_line = i; - rl_display_search (search_string, reverse, (i == orig_line) ? -1 : i); + cval = _rl_char_value (rl_line_buffer, n); + if (_rl_walphabetic (cval) == 0) + break; + n = MB_NEXTCHAR (rl_line_buffer, n, 1, MB_FIND_NONZERO);; } + wlen = n - wstart + 1; + if (cxt->search_string_index + wlen + 1 >= cxt->search_string_size) + { + cxt->search_string_size += wlen + 1; + cxt->search_string = (char *)xrealloc (cxt->search_string, cxt->search_string_size); + } + for (; wstart < n; wstart++) + cxt->search_string[cxt->search_string_index++] = rl_line_buffer[wstart]; + cxt->search_string[cxt->search_string_index] = '\0'; + break; + + case -6: /* C-Y */ + /* skip over portion of line we already matched and yank rest */ + wstart = rl_point + cxt->search_string_index; + if (wstart >= rl_end) + { + rl_ding (); + break; + } + n = rl_end - wstart + 1; + if (cxt->search_string_index + n + 1 >= cxt->search_string_size) + { + cxt->search_string_size += n + 1; + cxt->search_string = (char *)xrealloc (cxt->search_string, cxt->search_string_size); + } + for (n = wstart; n < rl_end; n++) + cxt->search_string[cxt->search_string_index++] = rl_line_buffer[n]; + cxt->search_string[cxt->search_string_index] = '\0'; + break; + + /* Add character to search string and continue search. */ + default: + if (cxt->search_string_index + 2 >= cxt->search_string_size) + { + cxt->search_string_size += 128; + cxt->search_string = (char *)xrealloc (cxt->search_string, cxt->search_string_size); + } +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + { + int j, l; + for (j = 0, l = strlen (cxt->mb); j < l; ) + cxt->search_string[cxt->search_string_index++] = cxt->mb[j++]; + } + else +#endif + cxt->search_string[cxt->search_string_index++] = c; + cxt->search_string[cxt->search_string_index] = '\0'; + break; + } + + for (cxt->sflags &= ~(SF_FOUND|SF_FAILED);; ) + { + limit = cxt->sline_len - cxt->search_string_index + 1; + + /* Search the current line. */ + while ((cxt->sflags & SF_REVERSE) ? (cxt->sline_index >= 0) : (cxt->sline_index < limit)) + { + if (STREQN (cxt->search_string, cxt->sline + cxt->sline_index, cxt->search_string_index)) + { + cxt->sflags |= SF_FOUND; + break; + } + else + cxt->sline_index += cxt->direction; + } + if (cxt->sflags & SF_FOUND) + break; + + /* Move to the next line, but skip new copies of the line + we just found and lines shorter than the string we're + searching for. */ + do + { + /* Move to the next line. */ + cxt->history_pos += cxt->direction; + + /* At limit for direction? */ + if ((cxt->sflags & SF_REVERSE) ? (cxt->history_pos < 0) : (cxt->history_pos == cxt->hlen)) + { + cxt->sflags |= SF_FAILED; + break; + } + + /* We will need these later. */ + cxt->sline = cxt->lines[cxt->history_pos]; + cxt->sline_len = strlen (cxt->sline); + } + while ((cxt->prev_line_found && STREQ (cxt->prev_line_found, cxt->lines[cxt->history_pos])) || + (cxt->search_string_index > cxt->sline_len)); + + if (cxt->sflags & SF_FAILED) + break; + + /* Now set up the line for searching... */ + cxt->sline_index = (cxt->sflags & SF_REVERSE) ? cxt->sline_len - cxt->search_string_index : 0; + } + + if (cxt->sflags & SF_FAILED) + { + /* We cannot find the search string. Ding the bell. */ + rl_ding (); + cxt->history_pos = cxt->last_found_line; + return 1; + } + + /* We have found the search string. Just display it. But don't + actually move there in the history list until the user accepts + the location. */ + if (cxt->sflags & SF_FOUND) + { + cxt->prev_line_found = cxt->lines[cxt->history_pos]; + rl_replace_line (cxt->lines[cxt->history_pos], 0); + rl_point = cxt->sline_index; + cxt->last_found_line = cxt->history_pos; + rl_display_search (cxt->search_string, (cxt->sflags & SF_REVERSE), (cxt->history_pos == cxt->save_line) ? -1 : cxt->history_pos); + } + + return 1; +} + +static int +_rl_isearch_cleanup (cxt, r) + _rl_search_cxt *cxt; + int r; +{ + if (r >= 0) + _rl_isearch_fini (cxt); + _rl_scxt_dispose (cxt, 0); + _rl_iscxt = 0; + + RL_UNSETSTATE(RL_STATE_ISEARCH); + + return (r != 0); +} + +/* Search through the history looking for an interactively typed string. + This is analogous to i-search. We start the search in the current line. + DIRECTION is which direction to search; >= 0 means forward, < 0 means + backwards. */ +static int +rl_search_history (direction, invoking_key) + int direction, invoking_key; +{ + _rl_search_cxt *cxt; /* local for now, but saved globally */ + int c, r; + + RL_SETSTATE(RL_STATE_ISEARCH); + cxt = _rl_isearch_init (direction); + + rl_display_search (cxt->search_string, (cxt->sflags & SF_REVERSE), -1); + + /* If we are using the callback interface, all we do is set up here and + return. The key is that we leave RL_STATE_ISEARCH set. */ + if (RL_ISSTATE (RL_STATE_CALLBACK)) + return (0); + + r = -1; + for (;;) + { + c = _rl_search_getchar (cxt); + /* We might want to handle EOF here (c == 0) */ + r = _rl_isearch_dispatch (cxt, cxt->lastc); + if (r <= 0) + break; } /* The searching is over. The user may have found the string that she was looking for, or else she may have exited a failing search. If LINE_INDEX is -1, then that shows that the string searched for was not found. We use this to determine where to place rl_point. */ - - /* First put back the original state. */ - strcpy (rl_line_buffer, lines[orig_line]); - - rl_restore_prompt (); - - /* Save the search string for possible later use. */ - FREE (last_isearch_string); - last_isearch_string = search_string; - last_isearch_string_len = search_string_index; - - if (last_found_line < orig_line) - rl_get_previous_history (orig_line - last_found_line, 0); - else - rl_get_next_history (last_found_line - orig_line, 0); - - /* If the string was not found, put point at the end of the last matching - line. If last_found_line == orig_line, we didn't find any matching - history lines at all, so put point back in its original position. */ - if (line_index < 0) - { - if (last_found_line == orig_line) - line_index = orig_point; - else - line_index = strlen (rl_line_buffer); - rl_mark = orig_mark; - } - - rl_point = line_index; - /* Don't worry about where to put the mark here; rl_get_previous_history - and rl_get_next_history take care of it. */ - - rl_clear_message (); - - FREE (allocated_line); - free (lines); - - RL_UNSETSTATE(RL_STATE_ISEARCH); - - return 0; + return (_rl_isearch_cleanup (cxt, r)); } + +#if defined (READLINE_CALLBACKS) +/* Called from the callback functions when we are ready to read a key. The + callback functions know to call this because RL_ISSTATE(RL_STATE_ISEARCH). + If _rl_isearch_dispatch finishes searching, this function is responsible + for turning off RL_STATE_ISEARCH, which it does using _rl_isearch_cleanup. */ +int +_rl_isearch_callback (cxt) + _rl_search_cxt *cxt; +{ + int c, r; + + c = _rl_search_getchar (cxt); + /* We might want to handle EOF here */ + r = _rl_isearch_dispatch (cxt, cxt->lastc); + + return (r <= 0) ? _rl_isearch_cleanup (cxt, r) : 0; +} +#endif diff --git a/cmd-line-utils/readline/keymaps.c b/cmd-line-utils/readline/keymaps.c index 2be03f7086f..70d0cc08d3f 100644 --- a/cmd-line-utils/readline/keymaps.c +++ b/cmd-line-utils/readline/keymaps.c @@ -20,7 +20,9 @@ Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #define READLINE_LIBRARY -#include "config_readline.h" +#if defined (HAVE_CONFIG_H) +# include +#endif #if defined (HAVE_STDLIB_H) # include diff --git a/cmd-line-utils/readline/kill.c b/cmd-line-utils/readline/kill.c index 4d31a8ff170..031ddf47c5b 100644 --- a/cmd-line-utils/readline/kill.c +++ b/cmd-line-utils/readline/kill.c @@ -21,7 +21,9 @@ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #define READLINE_LIBRARY -#include "config_readline.h" +#if defined (HAVE_CONFIG_H) +# include +#endif #include @@ -76,7 +78,8 @@ static int rl_yank_nth_arg_internal PARAMS((int, int, int)); /* How to say that you only want to save a certain amount of kill material. */ int -rl_set_retained_kills (int num __attribute__((unused))) +rl_set_retained_kills (num) + int num; { return 0; } @@ -292,8 +295,8 @@ rl_backward_kill_line (direction, ignore) /* Kill the whole line, no matter where point is. */ int -rl_kill_full_line (int count __attribute__((unused)), - int ignore __attribute__((unused))) +rl_kill_full_line (count, ignore) + int count, ignore; { rl_begin_undo_group (); rl_point = 0; @@ -310,7 +313,8 @@ rl_kill_full_line (int count __attribute__((unused)), /* This does what C-w does in Unix. We can't prevent people from using behaviour that they expect. */ int -rl_unix_word_rubout (int count, int key __attribute__((unused))) +rl_unix_word_rubout (count, key) + int count, key; { int orig_point; @@ -342,7 +346,8 @@ rl_unix_word_rubout (int count, int key __attribute__((unused))) /* This deletes one filename component in a Unix pathname. That is, it deletes backward to directory separator (`/') or whitespace. */ int -rl_unix_filename_rubout (int count, int key __attribute__((unused))) +rl_unix_filename_rubout (count, key) + int count, key; { int orig_point, c; @@ -385,8 +390,8 @@ rl_unix_filename_rubout (int count, int key __attribute__((unused))) into the line at all, and if you aren't, then you know what you are doing. */ int -rl_unix_line_discard (int count __attribute__((unused)), - int key __attribute__((unused))) +rl_unix_line_discard (count, key) + int count, key; { if (rl_point == 0) rl_ding (); @@ -422,16 +427,16 @@ region_kill_internal (delete) /* Copy the text in the region to the kill ring. */ int -rl_copy_region_to_kill (int count __attribute__((unused)), - int key __attribute__((unused))) +rl_copy_region_to_kill (count, ignore) + int count, ignore; { return (region_kill_internal (0)); } /* Kill the text between the point and mark. */ int -rl_kill_region (int count __attribute__((unused)), - int ignore __attribute__((unused))) +rl_kill_region (count, ignore) + int count, ignore; { int r, npoint; @@ -495,7 +500,8 @@ rl_copy_backward_word (count, key) /* Yank back the last killed text. This ignores arguments. */ int -rl_yank (int count __attribute__((unused)), int ignore __attribute__((unused))) +rl_yank (count, ignore) + int count, ignore; { if (rl_kill_ring == 0) { @@ -513,7 +519,8 @@ rl_yank (int count __attribute__((unused)), int ignore __attribute__((unused))) delete that text from the line, rotate the index down, and yank back some other text. */ int -rl_yank_pop (int count __attribute__((unused)), int key __attribute__((unused))) +rl_yank_pop (count, key) + int count, key; { int l, n; @@ -575,6 +582,7 @@ rl_yank_nth_arg_internal (count, ignore, history_skip) if (!arg || !*arg) { rl_ding (); + FREE (arg); return -1; } diff --git a/cmd-line-utils/readline/macro.c b/cmd-line-utils/readline/macro.c index 8727285e181..00cd58d628c 100644 --- a/cmd-line-utils/readline/macro.c +++ b/cmd-line-utils/readline/macro.c @@ -21,7 +21,9 @@ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #define READLINE_LIBRARY -#include "config_readline.h" +#if defined (HAVE_CONFIG_H) +# include +#endif #include @@ -98,6 +100,8 @@ _rl_with_macro_input (string) int _rl_next_macro_key () { + int c; + if (rl_executing_macro == 0) return (0); @@ -107,7 +111,14 @@ _rl_next_macro_key () return (_rl_next_macro_key ()); } +#if defined (READLINE_CALLBACKS) + c = rl_executing_macro[executing_macro_index++]; + if (RL_ISSTATE (RL_STATE_CALLBACK) && RL_ISSTATE (RL_STATE_READCMD|RL_STATE_MOREINPUT) && rl_executing_macro[executing_macro_index] == 0) + _rl_pop_executing_macro (); + return c; +#else return (rl_executing_macro[executing_macro_index++]); +#endif } /* Save the currently executing macro on a stack of saved macros. */ @@ -189,8 +200,8 @@ _rl_kill_kbd_macro () definition to the end of the existing macro, and start by re-executing the existing macro. */ int -rl_start_kbd_macro (int ignore1 __attribute__((unused)), - int ignore2 __attribute__((unused))) +rl_start_kbd_macro (ignore1, ignore2) + int ignore1, ignore2; { if (RL_ISSTATE (RL_STATE_MACRODEF)) { @@ -214,7 +225,8 @@ rl_start_kbd_macro (int ignore1 __attribute__((unused)), A numeric argument says to execute the macro right now, that many times, counting the definition as the first time. */ int -rl_end_kbd_macro (int count, int ignore __attribute__((unused))) +rl_end_kbd_macro (count, ignore) + int count, ignore; { if (RL_ISSTATE (RL_STATE_MACRODEF) == 0) { @@ -233,7 +245,8 @@ rl_end_kbd_macro (int count, int ignore __attribute__((unused))) /* Execute the most recently defined keyboard macro. COUNT says how many times to execute it. */ int -rl_call_last_kbd_macro (int count, int ignore __attribute__((unused))) +rl_call_last_kbd_macro (count, ignore) + int count, ignore; { if (current_macro == 0) _rl_abort_internal (); diff --git a/cmd-line-utils/readline/mbutil.c b/cmd-line-utils/readline/mbutil.c index 284ea63aae4..17dde53ed7b 100644 --- a/cmd-line-utils/readline/mbutil.c +++ b/cmd-line-utils/readline/mbutil.c @@ -1,6 +1,6 @@ /* mbutil.c -- readline multibyte character utility functions */ -/* Copyright (C) 2001-2004 Free Software Foundation, Inc. +/* Copyright (C) 2001-2005 Free Software Foundation, Inc. This file is part of the GNU Readline Library, a library for reading lines of text with interactive input and history editing. @@ -21,16 +21,11 @@ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #define READLINE_LIBRARY -#ifndef _XOPEN_SOURCE -#define _XOPEN_SOURCE 500 +#if defined (HAVE_CONFIG_H) +# include #endif -#include "config_readline.h" - #include - -/* To get SuSE 9.3 to define wcwidth() (in wchar.h) */ - #include #include "posixjmp.h" @@ -82,18 +77,20 @@ _rl_find_next_mbchar_internal (string, seed, count, find_non_zero) char *string; int seed, count, find_non_zero; { - size_t tmp = 0; + size_t tmp; mbstate_t ps; - int point = 0; + int point; wchar_t wc; + tmp = 0; + memset(&ps, 0, sizeof (mbstate_t)); if (seed < 0) seed = 0; if (count <= 0) return seed; - point = seed + _rl_adjust_point(string, seed, &ps); + point = seed + _rl_adjust_point (string, seed, &ps); /* if this is true, means that seed was not pointed character started byte. So correct the point and consume count */ if (seed < point) @@ -131,15 +128,16 @@ _rl_find_next_mbchar_internal (string, seed, count, find_non_zero) if (find_non_zero) { tmp = mbrtowc (&wc, string + point, strlen (string + point), &ps); - while (wcwidth (wc) == 0) + while (tmp > 0 && wcwidth (wc) == 0) { point += tmp; tmp = mbrtowc (&wc, string + point, strlen (string + point), &ps); - if (tmp == (size_t)(0) || tmp == (size_t)(-1) || tmp == (size_t)(-2)) + if (MB_NULLWCH (tmp) || MB_INVALIDCH (tmp)) break; } } - return point; + + return point; } static int @@ -318,6 +316,28 @@ _rl_is_mbchar_matched (string, seed, end, mbchar, length) return 0; return 1; } + +wchar_t +_rl_char_value (buf, ind) + char *buf; + int ind; +{ + size_t tmp; + wchar_t wc; + mbstate_t ps; + int l; + + if (MB_LEN_MAX == 1 || rl_byte_oriented) + return ((wchar_t) buf[ind]); + l = strlen (buf); + if (ind >= l - 1) + return ((wchar_t) buf[ind]); + memset (&ps, 0, sizeof (mbstate_t)); + tmp = mbrtowc (&wc, buf + ind, l - ind, &ps); + if (MB_INVALIDCH (tmp) || MB_NULLWCH (tmp)) + return ((wchar_t) buf[ind]); + return wc; +} #endif /* HANDLE_MULTIBYTE */ /* Find next `count' characters started byte point of the specified seed. diff --git a/cmd-line-utils/readline/misc.c b/cmd-line-utils/readline/misc.c index c8739d0d750..94ecb25900a 100644 --- a/cmd-line-utils/readline/misc.c +++ b/cmd-line-utils/readline/misc.c @@ -1,6 +1,6 @@ /* misc.c -- miscellaneous bindable readline functions. */ -/* Copyright (C) 1987-2004 Free Software Foundation, Inc. +/* Copyright (C) 1987-2005 Free Software Foundation, Inc. This file is part of the GNU Readline Library, a library for reading lines of text with interactive input and history editing. @@ -21,7 +21,9 @@ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #define READLINE_LIBRARY -#include "config_readline.h" +#if defined (HAVE_CONFIG_H) +# include +#endif #if defined (HAVE_UNISTD_H) # include @@ -61,6 +63,8 @@ void _rl_free_history_entry PARAMS((HIST_ENTRY *)); to preserve the value of rl_point from line to line. */ int _rl_history_preserve_point = 0; +_rl_arg_cxt _rl_argcxt; + /* Saved target point for when _rl_history_preserve_point is set. Special value of -1 means that point is at the end of the line. */ int _rl_history_saved_point = -1; @@ -71,77 +75,74 @@ int _rl_history_saved_point = -1; /* */ /* **************************************************************** */ -/* Handle C-u style numeric args, as well as M--, and M-digits. */ -static int -rl_digit_loop () +int +_rl_arg_overflow () { - int key, c, sawminus, sawdigits; - - rl_save_prompt (); - - RL_SETSTATE(RL_STATE_NUMERICARG); - sawminus = sawdigits = 0; - while (1) + if (rl_numeric_arg > 1000000) { - if (rl_numeric_arg > 1000000) + _rl_argcxt = 0; + rl_explicit_arg = rl_numeric_arg = 0; + rl_ding (); + rl_restore_prompt (); + rl_clear_message (); + RL_UNSETSTATE(RL_STATE_NUMERICARG); + return 1; + } + return 0; +} + +void +_rl_arg_init () +{ + rl_save_prompt (); + _rl_argcxt = 0; + RL_SETSTATE(RL_STATE_NUMERICARG); +} + +int +_rl_arg_getchar () +{ + int c; + + rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg); + RL_SETSTATE(RL_STATE_MOREINPUT); + c = rl_read_key (); + RL_UNSETSTATE(RL_STATE_MOREINPUT); + + return c; +} + +/* Process C as part of the current numeric argument. Return -1 if the + argument should be aborted, 0 if we should not read any more chars, and + 1 if we should continue to read chars. */ +int +_rl_arg_dispatch (cxt, c) + _rl_arg_cxt cxt; + int c; +{ + int key, r; + + key = c; + + /* If we see a key bound to `universal-argument' after seeing digits, + it ends the argument but is otherwise ignored. */ + if (_rl_keymap[c].type == ISFUNC && _rl_keymap[c].function == rl_universal_argument) + { + if ((cxt & NUM_SAWDIGITS) == 0) { - sawdigits = rl_explicit_arg = rl_numeric_arg = 0; - rl_ding (); - rl_restore_prompt (); - rl_clear_message (); - RL_UNSETSTATE(RL_STATE_NUMERICARG); + rl_numeric_arg *= 4; return 1; } - rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg); - RL_SETSTATE(RL_STATE_MOREINPUT); - key = c = rl_read_key (); - RL_UNSETSTATE(RL_STATE_MOREINPUT); - - if (c < 0) - { - _rl_abort_internal (); - return -1; - } - - /* If we see a key bound to `universal-argument' after seeing digits, - it ends the argument but is otherwise ignored. */ - if (_rl_keymap[c].type == ISFUNC && - _rl_keymap[c].function == rl_universal_argument) - { - if (sawdigits == 0) - { - rl_numeric_arg *= 4; - continue; - } - else - { - RL_SETSTATE(RL_STATE_MOREINPUT); - key = rl_read_key (); - RL_UNSETSTATE(RL_STATE_MOREINPUT); - rl_restore_prompt (); - rl_clear_message (); - RL_UNSETSTATE(RL_STATE_NUMERICARG); - return (_rl_dispatch (key, _rl_keymap)); - } - } - - c = UNMETA (c); - - if (_rl_digit_p (c)) - { - rl_numeric_arg = rl_explicit_arg ? (rl_numeric_arg * 10) + c - '0' : c - '0'; - sawdigits = rl_explicit_arg = 1; - } - else if (c == '-' && rl_explicit_arg == 0) - { - rl_numeric_arg = sawminus = 1; - rl_arg_sign = -1; - } + else if (RL_ISSTATE (RL_STATE_CALLBACK)) + { + _rl_argcxt |= NUM_READONE; + return 0; /* XXX */ + } else { - /* Make M-- command equivalent to M--1 command. */ - if (sawminus && rl_numeric_arg == 1 && rl_explicit_arg == 0) - rl_explicit_arg = 1; + RL_SETSTATE(RL_STATE_MOREINPUT); + key = rl_read_key (); + RL_UNSETSTATE(RL_STATE_MOREINPUT); rl_restore_prompt (); rl_clear_message (); RL_UNSETSTATE(RL_STATE_NUMERICARG); @@ -149,15 +150,133 @@ rl_digit_loop () } } - /*NOTREACHED*/ + c = UNMETA (c); + + if (_rl_digit_p (c)) + { + r = _rl_digit_value (c); + rl_numeric_arg = rl_explicit_arg ? (rl_numeric_arg * 10) + r : r; + rl_explicit_arg = 1; + _rl_argcxt |= NUM_SAWDIGITS; + } + else if (c == '-' && rl_explicit_arg == 0) + { + rl_numeric_arg = 1; + _rl_argcxt |= NUM_SAWMINUS; + rl_arg_sign = -1; + } + else + { + /* Make M-- command equivalent to M--1 command. */ + if ((_rl_argcxt & NUM_SAWMINUS) && rl_numeric_arg == 1 && rl_explicit_arg == 0) + rl_explicit_arg = 1; + rl_restore_prompt (); + rl_clear_message (); + RL_UNSETSTATE(RL_STATE_NUMERICARG); + + r = _rl_dispatch (key, _rl_keymap); + if (RL_ISSTATE (RL_STATE_CALLBACK)) + { + /* At worst, this will cause an extra redisplay. Otherwise, + we have to wait until the next character comes in. */ + if (rl_done == 0) + (*rl_redisplay_function) (); + r = 0; + } + return r; + } + + return 1; } -/* Add the current digit to the argument in progress. */ -int -rl_digit_argument (int ignore __attribute__((unused)), int key) +/* Handle C-u style numeric args, as well as M--, and M-digits. */ +static int +rl_digit_loop () { - rl_execute_next (key); - return (rl_digit_loop ()); + int c, r; + + while (1) + { + if (_rl_arg_overflow ()) + return 1; + + c = _rl_arg_getchar (); + + if (c < 0) + { + _rl_abort_internal (); + return -1; + } + + r = _rl_arg_dispatch (_rl_argcxt, c); + if (r <= 0 || (RL_ISSTATE (RL_STATE_NUMERICARG) == 0)) + break; + } + + return r; +} + +/* Create a default argument. */ +void +_rl_reset_argument () +{ + rl_numeric_arg = rl_arg_sign = 1; + rl_explicit_arg = 0; + _rl_argcxt = 0; +} + +/* Start a numeric argument with initial value KEY */ +int +rl_digit_argument (ignore, key) + int ignore, key; +{ + _rl_arg_init (); + if (RL_ISSTATE (RL_STATE_CALLBACK)) + { + _rl_arg_dispatch (_rl_argcxt, key); + rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg); + return 0; + } + else + { + rl_execute_next (key); + return (rl_digit_loop ()); + } +} + +/* C-u, universal argument. Multiply the current argument by 4. + Read a key. If the key has nothing to do with arguments, then + dispatch on it. If the key is the abort character then abort. */ +int +rl_universal_argument (count, key) + int count, key; +{ + _rl_arg_init (); + rl_numeric_arg *= 4; + + return (RL_ISSTATE (RL_STATE_CALLBACK) ? 0 : rl_digit_loop ()); +} + +int +_rl_arg_callback (cxt) + _rl_arg_cxt cxt; +{ + int c, r; + + c = _rl_arg_getchar (); + + if (_rl_argcxt & NUM_READONE) + { + _rl_argcxt &= ~NUM_READONE; + rl_restore_prompt (); + rl_clear_message (); + RL_UNSETSTATE(RL_STATE_NUMERICARG); + rl_execute_next (c); + return 0; + } + + r = _rl_arg_dispatch (cxt, c); + return (r != 1); } /* What to do when you abort reading an argument. */ @@ -166,30 +285,11 @@ rl_discard_argument () { rl_ding (); rl_clear_message (); - _rl_init_argument (); - return 0; -} + _rl_reset_argument (); -/* Create a default argument. */ -int -_rl_init_argument () -{ - rl_numeric_arg = rl_arg_sign = 1; - rl_explicit_arg = 0; return 0; } -/* C-u, universal argument. Multiply the current argument by 4. - Read a key. If the key has nothing to do with arguments, then - dispatch on it. If the key is the abort character then abort. */ -int -rl_universal_argument (int count __attribute__((unused)), - int key __attribute__((unused))) -{ - rl_numeric_arg *= 4; - return (rl_digit_loop ()); -} - /* **************************************************************** */ /* */ /* History Utilities */ @@ -222,8 +322,10 @@ _rl_free_history_entry (entry) { if (entry == 0) return; - if (entry->line) - free (entry->line); + + FREE (entry->line); + FREE (entry->timestamp); + free (entry); } @@ -239,6 +341,7 @@ rl_maybe_replace_line () { temp = replace_history_entry (where_history (), rl_line_buffer, (histdata_t)rl_undo_list); free (temp->line); + FREE (temp->timestamp); free (temp); } return 0; @@ -271,14 +374,9 @@ rl_maybe_save_line () { _rl_saved_line_for_history = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY)); _rl_saved_line_for_history->line = savestring (rl_line_buffer); + _rl_saved_line_for_history->timestamp = (char *)NULL; _rl_saved_line_for_history->data = (char *)rl_undo_list; } - else if (STREQ (rl_line_buffer, _rl_saved_line_for_history->line) == 0) - { - free (_rl_saved_line_for_history->line); - _rl_saved_line_for_history->line = savestring (rl_line_buffer); - _rl_saved_line_for_history->data = (char *)rl_undo_list; /* XXX possible memleak */ - } return 0; } @@ -313,7 +411,9 @@ _rl_history_set_point () } void -rl_replace_from_history (HIST_ENTRY *entry, int flags __attribute__((unused))) +rl_replace_from_history (entry, flags) + HIST_ENTRY *entry; + int flags; /* currently unused */ { /* Can't call with `1' because rl_undo_list might point to an undo list from a history entry, just like we're setting up here. */ @@ -339,15 +439,16 @@ rl_replace_from_history (HIST_ENTRY *entry, int flags __attribute__((unused))) /* Meta-< goes to the start of the history. */ int -rl_beginning_of_history (int count __attribute__((unused)), int key) +rl_beginning_of_history (count, key) + int count, key; { return (rl_get_previous_history (1 + where_history (), key)); } /* Meta-> goes to the end of the history. (The current line). */ int -rl_end_of_history (int count __attribute__((unused)), - int key __attribute__((unused))) +rl_end_of_history (count, key) + int count, key; { rl_maybe_replace_line (); using_history (); @@ -451,7 +552,8 @@ rl_get_previous_history (count, key) /* **************************************************************** */ /* How to toggle back and forth between editing modes. */ int -rl_vi_editing_mode (int count __attribute__((unused)), int key) +rl_vi_editing_mode (count, key) + int count, key; { #if defined (VI_MODE) _rl_set_insert_mode (RL_IM_INSERT, 1); /* vi mode ignores insert mode */ @@ -463,8 +565,8 @@ rl_vi_editing_mode (int count __attribute__((unused)), int key) } int -rl_emacs_editing_mode (int count __attribute__((unused)), - int key __attribute__((unused))) +rl_emacs_editing_mode (count, key) + int count, key; { rl_editing_mode = emacs_mode; _rl_set_insert_mode (RL_IM_INSERT, 1); /* emacs mode default is insert mode */ @@ -474,7 +576,8 @@ rl_emacs_editing_mode (int count __attribute__((unused)), /* Function for the rest of the library to use to set insert/overwrite mode. */ void -_rl_set_insert_mode (int im, int force __attribute__((unused))) +_rl_set_insert_mode (im, force) + int im, force; { #ifdef CURSOR_MODE _rl_set_cursor (im, force); @@ -486,7 +589,8 @@ _rl_set_insert_mode (int im, int force __attribute__((unused))) /* Toggle overwrite mode. A positive explicit argument selects overwrite mode. A negative or zero explicit argument selects insert mode. */ int -rl_overwrite_mode (int count, int key __attribute__((unused))) +rl_overwrite_mode (count, key) + int count, key; { if (rl_explicit_arg == 0) _rl_set_insert_mode (rl_insert_mode ^ 1, 0); diff --git a/cmd-line-utils/readline/nls.c b/cmd-line-utils/readline/nls.c index 73ad0227195..bcee87561aa 100644 --- a/cmd-line-utils/readline/nls.c +++ b/cmd-line-utils/readline/nls.c @@ -21,7 +21,9 @@ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #define READLINE_LIBRARY -#include "config_readline.h" +#if defined (HAVE_CONFIG_H) +# include +#endif #include @@ -111,7 +113,7 @@ _rl_init_eightbit () if (lspec == 0 || *lspec == 0) lspec = setlocale (LC_CTYPE, (char *)NULL); if (lspec == 0) - lspec = (char*) ""; + lspec = ""; t = setlocale (LC_CTYPE, lspec); if (t && *t && (t[0] != 'C' || t[1]) && (STREQ (t, "POSIX") == 0)) diff --git a/cmd-line-utils/readline/parens.c b/cmd-line-utils/readline/parens.c index bb893ac1bfb..737f7675e93 100644 --- a/cmd-line-utils/readline/parens.c +++ b/cmd-line-utils/readline/parens.c @@ -27,7 +27,9 @@ #include "rlconf.h" -#include "config_readline.h" +#if defined (HAVE_CONFIG_H) +# include +#endif #include #include diff --git a/cmd-line-utils/readline/readline.c b/cmd-line-utils/readline/readline.c index dd3724a86d7..c2b74006b05 100644 --- a/cmd-line-utils/readline/readline.c +++ b/cmd-line-utils/readline/readline.c @@ -1,7 +1,7 @@ /* readline.c -- a general facility for reading lines of input with emacs style editing and completion. */ -/* Copyright (C) 1987-2002 Free Software Foundation, Inc. +/* Copyright (C) 1987-2005 Free Software Foundation, Inc. This file is part of the GNU Readline Library, a library for reading lines of text with interactive input and history editing. @@ -22,7 +22,9 @@ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #define READLINE_LIBRARY -#include "config_readline.h" +#if defined (HAVE_CONFIG_H) +# include +#endif #include #include "posixstat.h" @@ -47,6 +49,11 @@ #include #include "posixjmp.h" +#include + +#if !defined (errno) +extern int errno; +#endif /* !errno */ /* System-specific feature definitions and include files. */ #include "rldefs.h" @@ -66,11 +73,11 @@ #include "xmalloc.h" #ifndef RL_LIBRARY_VERSION -# define RL_LIBRARY_VERSION "5.0" +# define RL_LIBRARY_VERSION "5.1" #endif #ifndef RL_READLINE_VERSION -# define RL_READLINE_VERSION 0x0500 +# define RL_READLINE_VERSION 0x0501 #endif extern void _rl_free_history_entry PARAMS((HIST_ENTRY *)); @@ -83,9 +90,10 @@ static void bind_arrow_keys_internal PARAMS((Keymap)); static void bind_arrow_keys PARAMS((void)); static void readline_default_bindings PARAMS((void)); -#ifdef NOT_USED static void reset_default_bindings PARAMS((void)); -#endif + +static int _rl_subseq_result PARAMS((int, Keymap, int, int)); +static int _rl_subseq_getchar PARAMS((int)); /* **************************************************************** */ /* */ @@ -104,6 +112,7 @@ int rl_gnu_readline_p = 1; By default, it is the standard emacs keymap. */ Keymap _rl_keymap = emacs_standard_keymap; + /* The current style of editing. */ int rl_editing_mode = emacs_mode; @@ -219,6 +228,9 @@ char *_rl_comment_begin; /* Keymap holding the function currently being executed. */ Keymap rl_executing_keymap; +/* Keymap we're currently using to dispatch. */ +Keymap _rl_dispatching_keymap; + /* Non-zero means to erase entire line, including prompt, on empty input lines. */ int rl_erase_empty_line = 0; @@ -230,6 +242,9 @@ int rl_num_chars_to_read; char *rl_line_buffer = (char *)NULL; int rl_line_buffer_len = 0; +/* Key sequence `contexts' */ +_rl_keyseq_cxt *_rl_kscxt = 0; + /* Forward declarations used by the display, termcap, and history code. */ /* **************************************************************** */ @@ -251,6 +266,10 @@ int _rl_convert_meta_chars_to_ascii = 1; rather than as a meta-prefixed escape sequence. */ int _rl_output_meta_chars = 0; +/* Non-zero means to look at the termios special characters and bind + them to equivalent readline functions at startup. */ +int _rl_bind_stty_chars = 1; + /* **************************************************************** */ /* */ /* Top Level Functions */ @@ -268,6 +287,7 @@ rl_set_prompt (prompt) { FREE (rl_prompt); rl_prompt = prompt ? savestring (prompt) : (char *)NULL; + rl_display_prompt = rl_prompt ? rl_prompt : ""; rl_visible_prompt_length = rl_expand_prompt (rl_prompt); return 0; @@ -291,14 +311,16 @@ readline (prompt) rl_set_prompt (prompt); rl_initialize (); - (*rl_prep_term_function) (_rl_meta_flag); + if (rl_prep_term_function) + (*rl_prep_term_function) (_rl_meta_flag); #if defined (HANDLE_SIGNALS) rl_set_signals (); #endif value = readline_internal (); - (*rl_deprep_term_function) (); + if (rl_deprep_term_function) + (*rl_deprep_term_function) (); #if defined (HANDLE_SIGNALS) rl_clear_signals (); @@ -388,6 +410,36 @@ readline_internal_teardown (eof) return (eof ? (char *)NULL : savestring (the_line)); } +void +_rl_internal_char_cleanup () +{ +#if defined (VI_MODE) + /* In vi mode, when you exit insert mode, the cursor moves back + over the previous character. We explicitly check for that here. */ + if (rl_editing_mode == vi_mode && _rl_keymap == vi_movement_keymap) + rl_vi_check (); +#endif /* VI_MODE */ + + if (rl_num_chars_to_read && rl_end >= rl_num_chars_to_read) + { + (*rl_redisplay_function) (); + _rl_want_redisplay = 0; + rl_newline (1, '\n'); + } + + if (rl_done == 0) + { + (*rl_redisplay_function) (); + _rl_want_redisplay = 0; + } + + /* If the application writer has told us to erase the entire line if + the only character typed was something bound to rl_newline, do so. */ + if (rl_erase_empty_line && rl_done && rl_last_func == rl_newline && + rl_point == 0 && rl_end == 0) + _rl_erase_entire_line (); +} + STATIC_CALLBACK int #if defined (READLINE_CALLBACKS) readline_internal_char () @@ -410,12 +462,21 @@ readline_internal_charloop () code = setjmp (readline_top_level); if (code) - (*rl_redisplay_function) (); + { + (*rl_redisplay_function) (); + _rl_want_redisplay = 0; + /* If we get here, we're not being called from something dispatched + from _rl_callback_read_char(), which sets up its own value of + readline_top_level (saving and restoring the old, of course), so + we can just return here. */ + if (RL_ISSTATE (RL_STATE_CALLBACK)) + return (0); + } if (rl_pending_input == 0) { /* Then initialize the argument and number of keys read. */ - _rl_init_argument (); + _rl_reset_argument (); rl_key_sequence_length = 0; } @@ -423,6 +484,20 @@ readline_internal_charloop () c = rl_read_key (); RL_UNSETSTATE(RL_STATE_READCMD); + /* look at input.c:rl_getc() for the circumstances under which this will + be returned; punt immediately on read error without converting it to + a newline. */ + if (c == READERR) + { +#if defined (READLINE_CALLBACKS) + RL_SETSTATE(RL_STATE_DONE); + return (rl_done = 1); +#else + eof_found = 1; + break; +#endif + } + /* EOF typed to a non-blank line is a . */ if (c == EOF && rl_end) c = NEWLINE; @@ -449,27 +524,7 @@ readline_internal_charloop () if (rl_pending_input == 0 && lk == _rl_last_command_was_kill) _rl_last_command_was_kill = 0; -#if defined (VI_MODE) - /* In vi mode, when you exit insert mode, the cursor moves back - over the previous character. We explicitly check for that here. */ - if (rl_editing_mode == vi_mode && _rl_keymap == vi_movement_keymap) - rl_vi_check (); -#endif /* VI_MODE */ - - if (rl_num_chars_to_read && rl_end >= rl_num_chars_to_read) - { - (*rl_redisplay_function) (); - rl_newline (1, '\n'); - } - - if (rl_done == 0) - (*rl_redisplay_function) (); - - /* If the application writer has told us to erase the entire line if - the only character typed was something bound to rl_newline, do so. */ - if (rl_erase_empty_line && rl_done && rl_last_func == rl_newline && - rl_point == 0 && rl_end == 0) - _rl_erase_entire_line (); + _rl_internal_char_cleanup (); #if defined (READLINE_CALLBACKS) return 0; @@ -519,6 +574,107 @@ _rl_set_the_line () the_line = rl_line_buffer; } +#if defined (READLINE_CALLBACKS) +_rl_keyseq_cxt * +_rl_keyseq_cxt_alloc () +{ + _rl_keyseq_cxt *cxt; + + cxt = (_rl_keyseq_cxt *)xmalloc (sizeof (_rl_keyseq_cxt)); + + cxt->flags = cxt->subseq_arg = cxt->subseq_retval = 0; + + cxt->okey = 0; + cxt->ocxt = _rl_kscxt; + cxt->childval = 42; /* sentinel value */ + + return cxt; +} + +void +_rl_keyseq_cxt_dispose (cxt) + _rl_keyseq_cxt *cxt; +{ + free (cxt); +} + +void +_rl_keyseq_chain_dispose () +{ + _rl_keyseq_cxt *cxt; + + while (_rl_kscxt) + { + cxt = _rl_kscxt; + _rl_kscxt = _rl_kscxt->ocxt; + _rl_keyseq_cxt_dispose (cxt); + } +} +#endif + +static int +_rl_subseq_getchar (key) + int key; +{ + int k; + + if (key == ESC) + RL_SETSTATE(RL_STATE_METANEXT); + RL_SETSTATE(RL_STATE_MOREINPUT); + k = rl_read_key (); + RL_UNSETSTATE(RL_STATE_MOREINPUT); + if (key == ESC) + RL_UNSETSTATE(RL_STATE_METANEXT); + + return k; +} + +#if defined (READLINE_CALLBACKS) +int +_rl_dispatch_callback (cxt) + _rl_keyseq_cxt *cxt; +{ + int nkey, r; + + /* For now */ +#if 1 + /* The first time this context is used, we want to read input and dispatch + on it. When traversing the chain of contexts back `up', we want to use + the value from the next context down. We're simulating recursion using + a chain of contexts. */ + if ((cxt->flags & KSEQ_DISPATCHED) == 0) + { + nkey = _rl_subseq_getchar (cxt->okey); + r = _rl_dispatch_subseq (nkey, cxt->dmap, cxt->subseq_arg); + cxt->flags |= KSEQ_DISPATCHED; + } + else + r = cxt->childval; +#else + r = _rl_dispatch_subseq (nkey, cxt->dmap, cxt->subseq_arg); +#endif + + /* For now */ + r = _rl_subseq_result (r, cxt->oldmap, cxt->okey, (cxt->flags & KSEQ_SUBSEQ)); + + if (r == 0) /* success! */ + { + _rl_keyseq_chain_dispose (); + RL_UNSETSTATE (RL_STATE_MULTIKEY); + return r; + } + + if (r != -3) /* magic value that says we added to the chain */ + _rl_kscxt = cxt->ocxt; + if (_rl_kscxt) + _rl_kscxt->childval = r; + if (r != -3) + _rl_keyseq_cxt_dispose (cxt); + + return r; +} +#endif /* READLINE_CALLBACKS */ + /* Do the command associated with KEY in MAP. If the associated command is really a keymap, then read another key, and dispatch into that map. */ @@ -527,6 +683,7 @@ _rl_dispatch (key, map) register int key; Keymap map; { + _rl_dispatching_keymap = map; return _rl_dispatch_subseq (key, map, 0); } @@ -539,6 +696,9 @@ _rl_dispatch_subseq (key, map, got_subseq) int r, newkey; char *macro; rl_command_func_t *func; +#if defined (READLINE_CALLBACKS) + _rl_keyseq_cxt *cxt; +#endif if (META_CHAR (key) && _rl_convert_meta_chars_to_ascii) { @@ -572,13 +732,9 @@ _rl_dispatch_subseq (key, map, got_subseq) rl_executing_keymap = map; -#if 0 - _rl_suppress_redisplay = (map[key].function == rl_insert) && _rl_input_available (); -#endif - rl_dispatching = 1; RL_SETSTATE(RL_STATE_DISPATCHING); - r = (*map[key].function)(rl_numeric_arg * rl_arg_sign, key); + (*map[key].function)(rl_numeric_arg * rl_arg_sign, key); RL_UNSETSTATE(RL_STATE_DISPATCHING); rl_dispatching = 0; @@ -607,6 +763,10 @@ _rl_dispatch_subseq (key, map, got_subseq) } else { +#if defined (READLINE_CALLBACKS) + RL_UNSETSTATE (RL_STATE_MULTIKEY); + _rl_keyseq_chain_dispose (); +#endif _rl_abort_internal (); return -1; } @@ -628,58 +788,43 @@ _rl_dispatch_subseq (key, map, got_subseq) #endif rl_key_sequence_length++; + _rl_dispatching_keymap = FUNCTION_TO_KEYMAP (map, key); - if (key == ESC) - RL_SETSTATE(RL_STATE_METANEXT); - RL_SETSTATE(RL_STATE_MOREINPUT); - newkey = rl_read_key (); - RL_UNSETSTATE(RL_STATE_MOREINPUT); - if (key == ESC) - RL_UNSETSTATE(RL_STATE_METANEXT); + /* Allocate new context here. Use linked contexts (linked through + cxt->ocxt) to simulate recursion */ +#if defined (READLINE_CALLBACKS) + if (RL_ISSTATE (RL_STATE_CALLBACK)) + { + /* Return 0 only the first time, to indicate success to + _rl_callback_read_char. The rest of the time, we're called + from _rl_dispatch_callback, so we return 3 to indicate + special handling is necessary. */ + r = RL_ISSTATE (RL_STATE_MULTIKEY) ? -3 : 0; + cxt = _rl_keyseq_cxt_alloc (); + if (got_subseq) + cxt->flags |= KSEQ_SUBSEQ; + cxt->okey = key; + cxt->oldmap = map; + cxt->dmap = _rl_dispatching_keymap; + cxt->subseq_arg = got_subseq || cxt->dmap[ANYOTHERKEY].function; + + RL_SETSTATE (RL_STATE_MULTIKEY); + _rl_kscxt = cxt; + + return r; /* don't indicate immediate success */ + } +#endif + + newkey = _rl_subseq_getchar (key); if (newkey < 0) { _rl_abort_internal (); return -1; } - r = _rl_dispatch_subseq (newkey, FUNCTION_TO_KEYMAP (map, key), got_subseq || map[ANYOTHERKEY].function); - - if (r == -2) - /* We didn't match anything, and the keymap we're indexed into - shadowed a function previously bound to that prefix. Call - the function. The recursive call to _rl_dispatch_subseq has - already taken care of pushing any necessary input back onto - the input queue with _rl_unget_char. */ - { -#if 0 - r = _rl_dispatch (ANYOTHERKEY, FUNCTION_TO_KEYMAP (map, key)); -#else - /* XXX - experimental code -- might never be executed. Save - for later. */ - Keymap m = FUNCTION_TO_KEYMAP (map, key); - int type = m[ANYOTHERKEY].type; - func = m[ANYOTHERKEY].function; - if (type == ISFUNC && func == rl_do_lowercase_version) - r = _rl_dispatch (_rl_to_lower (key), map); - else - r = _rl_dispatch (ANYOTHERKEY, m); -#endif - } - else if (r && map[ANYOTHERKEY].function) - { - /* We didn't match (r is probably -1), so return something to - tell the caller that it should try ANYOTHERKEY for an - overridden function. */ - _rl_unget_char (key); - return -2; - } - else if (r && got_subseq) - { - /* OK, back up the chain. */ - _rl_unget_char (key); - return -1; - } + r = _rl_dispatch_subseq (newkey, _rl_dispatching_keymap, got_subseq || map[ANYOTHERKEY].function); + return _rl_subseq_result (r, map, key, got_subseq); } else { @@ -703,9 +848,69 @@ _rl_dispatch_subseq (key, map, got_subseq) _rl_vi_textmod_command (key)) _rl_vi_set_last (key, rl_numeric_arg, rl_arg_sign); #endif + return (r); } +static int +_rl_subseq_result (r, map, key, got_subseq) + int r; + Keymap map; + int key, got_subseq; +{ + Keymap m; + int type, nt; + rl_command_func_t *func, *nf; + + if (r == -2) + /* We didn't match anything, and the keymap we're indexed into + shadowed a function previously bound to that prefix. Call + the function. The recursive call to _rl_dispatch_subseq has + already taken care of pushing any necessary input back onto + the input queue with _rl_unget_char. */ + { + m = _rl_dispatching_keymap; + type = m[ANYOTHERKEY].type; + func = m[ANYOTHERKEY].function; + if (type == ISFUNC && func == rl_do_lowercase_version) + r = _rl_dispatch (_rl_to_lower (key), map); + else if (type == ISFUNC && func == rl_insert) + { + /* If the function that was shadowed was self-insert, we + somehow need a keymap with map[key].func == self-insert. + Let's use this one. */ + nt = m[key].type; + nf = m[key].function; + + m[key].type = type; + m[key].function = func; + r = _rl_dispatch (key, m); + m[key].type = nt; + m[key].function = nf; + } + else + r = _rl_dispatch (ANYOTHERKEY, m); + } + else if (r && map[ANYOTHERKEY].function) + { + /* We didn't match (r is probably -1), so return something to + tell the caller that it should try ANYOTHERKEY for an + overridden function. */ + _rl_unget_char (key); + _rl_dispatching_keymap = map; + return -2; + } + else if (r && got_subseq) + { + /* OK, back up the chain. */ + _rl_unget_char (key); + _rl_dispatching_keymap = map; + return -1; + } + + return r; +} + /* **************************************************************** */ /* */ /* Initializations */ @@ -863,19 +1068,21 @@ readline_initialize_everything () static void readline_default_bindings () { - rl_tty_set_default_bindings (_rl_keymap); + if (_rl_bind_stty_chars) + rl_tty_set_default_bindings (_rl_keymap); } /* Reset the default bindings for the terminal special characters we're interested in back to rl_insert and read the new ones. */ -#ifdef NOT_USED static void reset_default_bindings () { - rl_tty_unset_default_bindings (_rl_keymap); - rl_tty_set_default_bindings (_rl_keymap); + if (_rl_bind_stty_chars) + { + rl_tty_unset_default_bindings (_rl_keymap); + rl_tty_set_default_bindings (_rl_keymap); + } } -#endif /* Bind some common arrow key sequences in MAP. */ static void @@ -908,6 +1115,13 @@ bind_arrow_keys_internal (map) rl_bind_keyseq_if_unbound ("\033OH", rl_beg_of_line); rl_bind_keyseq_if_unbound ("\033OF", rl_end_of_line); +#if defined (__MINGW32__) + rl_bind_keyseq_if_unbound ("\340H", rl_get_previous_history); + rl_bind_keyseq_if_unbound ("\340P", rl_get_next_history); + rl_bind_keyseq_if_unbound ("\340M", rl_forward_char); + rl_bind_keyseq_if_unbound ("\340K", rl_backward_char); +#endif + _rl_keymap = xkeymap; } diff --git a/cmd-line-utils/readline/readline.h b/cmd-line-utils/readline/readline.h index 222b317c4a8..b71bf98d204 100644 --- a/cmd-line-utils/readline/readline.h +++ b/cmd-line-utils/readline/readline.h @@ -1,6 +1,6 @@ /* Readline.h -- the names of functions callable from within readline. */ -/* Copyright (C) 1987-2004 Free Software Foundation, Inc. +/* Copyright (C) 1987-2005 Free Software Foundation, Inc. This file is part of the GNU Readline Library, a library for reading lines of text with interactive input and history editing. @@ -40,9 +40,9 @@ extern "C" { #endif /* Hex-encoded Readline version number. */ -#define RL_READLINE_VERSION 0x0500 /* Readline 5.0 */ +#define RL_READLINE_VERSION 0x0502 /* Readline 5.2 */ #define RL_VERSION_MAJOR 5 -#define RL_VERSION_MINOR 0 +#define RL_VERSION_MINOR 2 /* Readline data structures. */ @@ -241,6 +241,7 @@ extern int rl_vi_column PARAMS((int, int)); extern int rl_vi_delete_to PARAMS((int, int)); extern int rl_vi_change_to PARAMS((int, int)); extern int rl_vi_yank_to PARAMS((int, int)); +extern int rl_vi_rubout PARAMS((int, int)); extern int rl_vi_delete PARAMS((int, int)); extern int rl_vi_back_to_indent PARAMS((int, int)); extern int rl_vi_first_print PARAMS((int, int)); @@ -302,6 +303,8 @@ extern int rl_bind_keyseq_in_map PARAMS((const char *, rl_command_func_t *, Keym extern int rl_bind_keyseq_if_unbound PARAMS((const char *, rl_command_func_t *)); extern int rl_bind_keyseq_if_unbound_in_map PARAMS((const char *, rl_command_func_t *, Keymap)); extern int rl_generic_bind PARAMS((int, const char *, char *, Keymap)); + +extern char *rl_variable_value PARAMS((const char *)); extern int rl_variable_bind PARAMS((const char *, const char *)); /* Backwards compatibility, use rl_bind_keyseq_in_map instead. */ @@ -401,6 +404,7 @@ extern int rl_reset_terminal PARAMS((const char *)); extern void rl_resize_terminal PARAMS((void)); extern void rl_set_screen_size PARAMS((int, int)); extern void rl_get_screen_size PARAMS((int *, int *)); +extern void rl_reset_screen_size PARAMS((void)); extern char *rl_get_termcap PARAMS((const char *)); @@ -528,6 +532,11 @@ extern const char *rl_terminal_name; extern FILE *rl_instream; extern FILE *rl_outstream; +/* If non-zero, Readline gives values of LINES and COLUMNS from the environment + greater precedence than values fetched from the kernel when computing the + screen dimensions. */ +extern int rl_prefer_env_winsize; + /* If non-zero, then this is the address of a function to call just before readline_internal () prints the first prompt. */ extern rl_hook_func_t *rl_startup_hook; @@ -748,6 +757,10 @@ extern int rl_ignore_completion_duplicates; completion character will be inserted as any other. */ extern int rl_inhibit_completion; +/* Input error; can be returned by (*rl_getc_function) if readline is reading + a top-level command (RL_ISSTATE (RL_STATE_READCMD)). */ +#define READERR (-2) + /* Definitions available for use by readline clients. */ #define RL_PROMPT_START_IGNORE '\001' #define RL_PROMPT_END_IGNORE '\002' @@ -759,29 +772,33 @@ extern int rl_inhibit_completion; #define MULT_MATCH 2 /* Possible state values for rl_readline_state */ -#define RL_STATE_NONE 0x00000 /* no state; before first call */ +#define RL_STATE_NONE 0x000000 /* no state; before first call */ -#define RL_STATE_INITIALIZING 0x00001 /* initializing */ -#define RL_STATE_INITIALIZED 0x00002 /* initialization done */ -#define RL_STATE_TERMPREPPED 0x00004 /* terminal is prepped */ -#define RL_STATE_READCMD 0x00008 /* reading a command key */ -#define RL_STATE_METANEXT 0x00010 /* reading input after ESC */ -#define RL_STATE_DISPATCHING 0x00020 /* dispatching to a command */ -#define RL_STATE_MOREINPUT 0x00040 /* reading more input in a command function */ -#define RL_STATE_ISEARCH 0x00080 /* doing incremental search */ -#define RL_STATE_NSEARCH 0x00100 /* doing non-inc search */ -#define RL_STATE_SEARCH 0x00200 /* doing a history search */ -#define RL_STATE_NUMERICARG 0x00400 /* reading numeric argument */ -#define RL_STATE_MACROINPUT 0x00800 /* getting input from a macro */ -#define RL_STATE_MACRODEF 0x01000 /* defining keyboard macro */ -#define RL_STATE_OVERWRITE 0x02000 /* overwrite mode */ -#define RL_STATE_COMPLETING 0x04000 /* doing completion */ -#define RL_STATE_SIGHANDLER 0x08000 /* in readline sighandler */ -#define RL_STATE_UNDOING 0x10000 /* doing an undo */ -#define RL_STATE_INPUTPENDING 0x20000 /* rl_execute_next called */ -#define RL_STATE_TTYCSAVED 0x40000 /* tty special chars saved */ +#define RL_STATE_INITIALIZING 0x000001 /* initializing */ +#define RL_STATE_INITIALIZED 0x000002 /* initialization done */ +#define RL_STATE_TERMPREPPED 0x000004 /* terminal is prepped */ +#define RL_STATE_READCMD 0x000008 /* reading a command key */ +#define RL_STATE_METANEXT 0x000010 /* reading input after ESC */ +#define RL_STATE_DISPATCHING 0x000020 /* dispatching to a command */ +#define RL_STATE_MOREINPUT 0x000040 /* reading more input in a command function */ +#define RL_STATE_ISEARCH 0x000080 /* doing incremental search */ +#define RL_STATE_NSEARCH 0x000100 /* doing non-inc search */ +#define RL_STATE_SEARCH 0x000200 /* doing a history search */ +#define RL_STATE_NUMERICARG 0x000400 /* reading numeric argument */ +#define RL_STATE_MACROINPUT 0x000800 /* getting input from a macro */ +#define RL_STATE_MACRODEF 0x001000 /* defining keyboard macro */ +#define RL_STATE_OVERWRITE 0x002000 /* overwrite mode */ +#define RL_STATE_COMPLETING 0x004000 /* doing completion */ +#define RL_STATE_SIGHANDLER 0x008000 /* in readline sighandler */ +#define RL_STATE_UNDOING 0x010000 /* doing an undo */ +#define RL_STATE_INPUTPENDING 0x020000 /* rl_execute_next called */ +#define RL_STATE_TTYCSAVED 0x040000 /* tty special chars saved */ +#define RL_STATE_CALLBACK 0x080000 /* using the callback interface */ +#define RL_STATE_VIMOTION 0x100000 /* reading vi motion arg */ +#define RL_STATE_MULTIKEY 0x200000 /* reading multiple-key command */ +#define RL_STATE_VICMDONCE 0x400000 /* entered vi command mode at least once */ -#define RL_STATE_DONE 0x80000 /* done; accepted line */ +#define RL_STATE_DONE 0x800000 /* done; accepted line */ #define RL_SETSTATE(x) (rl_readline_state |= (x)) #define RL_UNSETSTATE(x) (rl_readline_state &= ~(x)) diff --git a/cmd-line-utils/readline/rlconf.h b/cmd-line-utils/readline/rlconf.h index c651fd8b41f..ff3929e0bf5 100644 --- a/cmd-line-utils/readline/rlconf.h +++ b/cmd-line-utils/readline/rlconf.h @@ -37,9 +37,12 @@ /* Ugly but working hack for binding prefix meta. */ #define PREFIX_META_HACK -/* The final, last-ditch effort file name for an init file. */ +/* The next-to-last-ditch effort file name for a user-specific init file. */ #define DEFAULT_INPUTRC "~/.inputrc" +/* The ultimate last-ditch filenname for an init file -- system-wide. */ +#define SYS_INPUTRC "/etc/inputrc" + /* If defined, expand tabs to spaces. */ #define DISPLAY_TABS diff --git a/cmd-line-utils/readline/rldefs.h b/cmd-line-utils/readline/rldefs.h index 0d600407b5f..0f6c87446dd 100644 --- a/cmd-line-utils/readline/rldefs.h +++ b/cmd-line-utils/readline/rldefs.h @@ -2,7 +2,7 @@ for readline. This should be included after any files that define system-specific constants like _POSIX_VERSION or USG. */ -/* Copyright (C) 1987,1989 Free Software Foundation, Inc. +/* Copyright (C) 1987-2005 Free Software Foundation, Inc. This file contains the Readline Library (the Library), a set of routines for providing Emacs style line input to programs that ask @@ -38,7 +38,11 @@ # if defined (HAVE_TERMIO_H) # define TERMIO_TTY_DRIVER # else -# define NEW_TTY_DRIVER +# if !defined (__MINGW32__) +# define NEW_TTY_DRIVER +# else +# define NO_TTY_DRIVER +# endif # endif #endif diff --git a/cmd-line-utils/readline/rlmbutil.h b/cmd-line-utils/readline/rlmbutil.h index 77cc026e3e8..dd317e2a090 100644 --- a/cmd-line-utils/readline/rlmbutil.h +++ b/cmd-line-utils/readline/rlmbutil.h @@ -32,10 +32,19 @@ /* For platforms which support the ISO C amendement 1 functionality we support user defined character classes. */ /* Solaris 2.5 has a bug: must be included before . */ -#if defined (HAVE_WCTYPE_H) && defined (HAVE_WCHAR_H) +#if defined (HAVE_WCTYPE_H) && defined (HAVE_WCHAR_H) && defined (HAVE_LOCALE_H) # include # include -# if defined (HAVE_MBSRTOWCS) && defined (HAVE_MBRTOWC) && defined (HAVE_MBRLEN) && defined (HAVE_WCWIDTH) +# if defined (HAVE_ISWCTYPE) && \ + defined (HAVE_ISWLOWER) && \ + defined (HAVE_ISWUPPER) && \ + defined (HAVE_MBSRTOWCS) && \ + defined (HAVE_MBRTOWC) && \ + defined (HAVE_MBRLEN) && \ + defined (HAVE_TOWLOWER) && \ + defined (HAVE_TOWUPPER) && \ + defined (HAVE_WCHAR_T) && \ + defined (HAVE_WCWIDTH) /* system is supposed to support XPG5 */ # define HANDLE_MULTIBYTE 1 # endif @@ -97,6 +106,21 @@ extern int _rl_read_mbstring PARAMS((int, char *, int)); extern int _rl_is_mbchar_matched PARAMS((char *, int, int, char *, int)); +extern wchar_t _rl_char_value PARAMS((char *, int)); +extern int _rl_walphabetic PARAMS((wchar_t)); + +#define _rl_to_wupper(wc) (iswlower (wc) ? towupper (wc) : (wc)) +#define _rl_to_wlower(wc) (iswupper (wc) ? towlower (wc) : (wc)) + +#define MB_NEXTCHAR(b,s,c,f) \ + ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) \ + ? _rl_find_next_mbchar ((b), (s), (c), (f)) \ + : ((s) + (c))) +#define MB_PREVCHAR(b,s,f) \ + ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) \ + ? _rl_find_prev_mbchar ((b), (s), (f)) \ + : ((s) - 1)) + #define MB_INVALIDCH(x) ((x) == (size_t)-1 || (x) == (size_t)-2) #define MB_NULLWCH(x) ((x) == 0) @@ -111,6 +135,16 @@ extern int _rl_is_mbchar_matched PARAMS((char *, int, int, char *, int)); #define _rl_find_prev_mbchar(b, i, f) (((i) == 0) ? (i) : ((i) - 1)) #define _rl_find_next_mbchar(b, i1, i2, f) ((i1) + (i2)) +#define _rl_char_value(buf,ind) ((buf)[(ind)]) + +#define _rl_walphabetic(c) (rl_alphabetic (c)) + +#define _rl_to_wupper(c) (_rl_to_upper (c)) +#define _rl_to_wlower(c) (_rl_to_lower (c)) + +#define MB_NEXTCHAR(b,s,c,f) ((s) + (c)) +#define MB_PREVCHAR(b,s,f) ((s) - 1) + #define MB_INVALIDCH(x) (0) #define MB_NULLWCH(x) (0) diff --git a/cmd-line-utils/readline/rlprivate.h b/cmd-line-utils/readline/rlprivate.h index c3cee917b76..64aa7bdd3fa 100644 --- a/cmd-line-utils/readline/rlprivate.h +++ b/cmd-line-utils/readline/rlprivate.h @@ -1,7 +1,7 @@ /* rlprivate.h -- functions and variables global to the readline library, but not intended for use by applications. */ -/* Copyright (C) 1999-2004 Free Software Foundation, Inc. +/* Copyright (C) 1999-2005 Free Software Foundation, Inc. This file is part of the GNU Readline Library, a library for reading lines of text with interactive input and history editing. @@ -28,6 +28,95 @@ #include "rlstdc.h" #include "posixjmp.h" /* defines procenv_t */ +/************************************************************************* + * * + * Global structs undocumented in texinfo manual and not in readline.h * + * * + *************************************************************************/ +/* search types */ +#define RL_SEARCH_ISEARCH 0x01 /* incremental search */ +#define RL_SEARCH_NSEARCH 0x02 /* non-incremental search */ +#define RL_SEARCH_CSEARCH 0x04 /* intra-line char search */ + +/* search flags */ +#define SF_REVERSE 0x01 +#define SF_FOUND 0x02 +#define SF_FAILED 0x04 + +typedef struct __rl_search_context +{ + int type; + int sflags; + + char *search_string; + int search_string_index; + int search_string_size; + + char **lines; + char *allocated_line; + int hlen; + int hindex; + + int save_point; + int save_mark; + int save_line; + int last_found_line; + char *prev_line_found; + + UNDO_LIST *save_undo_list; + + int history_pos; + int direction; + + int lastc; +#if defined (HANDLE_MULTIBYTE) + char mb[MB_LEN_MAX]; +#endif + + char *sline; + int sline_len; + int sline_index; + + char *search_terminators; +} _rl_search_cxt; + +/* Callback data for reading numeric arguments */ +#define NUM_SAWMINUS 0x01 +#define NUM_SAWDIGITS 0x02 +#define NUM_READONE 0x04 + +typedef int _rl_arg_cxt; + +/* A context for reading key sequences longer than a single character when + using the callback interface. */ +#define KSEQ_DISPATCHED 0x01 +#define KSEQ_SUBSEQ 0x02 +#define KSEQ_RECURSIVE 0x04 + +typedef struct __rl_keyseq_context +{ + int flags; + int subseq_arg; + int subseq_retval; /* XXX */ + Keymap dmap; + + Keymap oldmap; + int okey; + struct __rl_keyseq_context *ocxt; + int childval; +} _rl_keyseq_cxt; + + /* fill in more as needed */ +/* `Generic' callback data and functions */ +typedef struct __rl_callback_generic_arg +{ + int count; + int i1, i2; + /* add here as needed */ +} _rl_callback_generic_arg; + +typedef int _rl_callback_func_t PARAMS((_rl_callback_generic_arg *)); + /************************************************************************* * * * Global functions undocumented in texinfo manual and not in readline.h * @@ -54,6 +143,8 @@ extern int readline_echoing_p; extern int rl_key_sequence_length; extern int rl_byte_oriented; +extern _rl_keyseq_cxt *_rl_kscxt; + /* display.c */ extern int rl_display_fixed; @@ -100,6 +191,16 @@ extern void readline_internal_setup PARAMS((void)); extern char *readline_internal_teardown PARAMS((int)); extern int readline_internal_char PARAMS((void)); +extern _rl_keyseq_cxt *_rl_keyseq_cxt_alloc PARAMS((void)); +extern void _rl_keyseq_cxt_dispose PARAMS((_rl_keyseq_cxt *)); +extern void _rl_keyseq_chain_dispose PARAMS((void)); + +extern int _rl_dispatch_callback PARAMS((_rl_keyseq_cxt *)); + +/* callback.c */ +extern _rl_callback_generic_arg *_rl_callback_data_alloc PARAMS((int)); +extern void _rl_callback_data_dispose PARAMS((_rl_callback_generic_arg *)); + #endif /* READLINE_CALLBACKS */ /* bind.c */ @@ -132,6 +233,15 @@ extern void _rl_insert_typein PARAMS((int)); extern int _rl_unget_char PARAMS((int)); extern int _rl_pushed_input_available PARAMS((void)); +/* isearch.c */ +extern _rl_search_cxt *_rl_scxt_alloc PARAMS((int, int)); +extern void _rl_scxt_dispose PARAMS((_rl_search_cxt *, int)); + +extern int _rl_isearch_dispatch PARAMS((_rl_search_cxt *, int)); +extern int _rl_isearch_callback PARAMS((_rl_search_cxt *)); + +extern int _rl_search_getchar PARAMS((_rl_search_cxt *)); + /* macro.c */ extern void _rl_with_macro_input PARAMS((char *)); extern int _rl_next_macro_key PARAMS((void)); @@ -141,7 +251,12 @@ extern void _rl_add_macro_char PARAMS((int)); extern void _rl_kill_kbd_macro PARAMS((void)); /* misc.c */ -extern int _rl_init_argument PARAMS((void)); +extern int _rl_arg_overflow PARAMS((void)); +extern void _rl_arg_init PARAMS((void)); +extern int _rl_arg_getchar PARAMS((void)); +extern int _rl_arg_callback PARAMS((_rl_arg_cxt)); +extern void _rl_reset_argument PARAMS((void)); + extern void _rl_start_using_history PARAMS((void)); extern int _rl_free_saved_history_line PARAMS((void)); extern void _rl_set_insert_mode PARAMS((int, int)); @@ -157,11 +272,15 @@ extern void _rl_init_line_state PARAMS((void)); extern void _rl_set_the_line PARAMS((void)); extern int _rl_dispatch PARAMS((int, Keymap)); extern int _rl_dispatch_subseq PARAMS((int, Keymap, int)); +extern void _rl_internal_char_cleanup PARAMS((void)); /* rltty.c */ extern int _rl_disable_tty_signals PARAMS((void)); extern int _rl_restore_tty_signals PARAMS((void)); +/* search.c */ +extern int _rl_nsearch_callback PARAMS((_rl_search_cxt *)); + /* terminal.c */ extern void _rl_get_screen_size PARAMS((int, int)); extern int _rl_init_terminal_io PARAMS((const char *)); @@ -190,6 +309,10 @@ extern int _rl_char_search_internal PARAMS((int, int, int)); #endif extern int _rl_set_mark_at_pos PARAMS((int)); +/* undo.c */ +extern UNDO_LIST *_rl_copy_undo_entry PARAMS((UNDO_LIST *)); +extern UNDO_LIST *_rl_copy_undo_list PARAMS((UNDO_LIST *)); + /* util.c */ extern int _rl_abort_internal PARAMS((void)); extern char *_rl_strindex PARAMS((const char *, const char *)); @@ -217,6 +340,10 @@ extern void _rl_vi_done_inserting PARAMS((void)); extern const char *_rl_possible_control_prefixes[]; extern const char *_rl_possible_meta_prefixes[]; +/* callback.c */ +extern _rl_callback_func_t *_rl_callback_func; +extern _rl_callback_generic_arg *_rl_callback_data; + /* complete.c */ extern int _rl_complete_show_all; extern int _rl_complete_show_unmodified; @@ -231,11 +358,14 @@ extern int _rl_page_completions; extern int _rl_vis_botlin; extern int _rl_last_c_pos; extern int _rl_suppress_redisplay; +extern int _rl_want_redisplay; extern char *rl_display_prompt; /* isearch.c */ extern char *_rl_isearch_terminators; +extern _rl_search_cxt *_rl_iscxt; + /* macro.c */ extern char *_rl_executing_macro; @@ -243,6 +373,8 @@ extern char *_rl_executing_macro; extern int _rl_history_preserve_point; extern int _rl_history_saved_point; +extern _rl_arg_cxt _rl_argcxt; + /* readline.c */ extern int _rl_horizontal_scroll_mode; extern int _rl_mark_modified_lines; @@ -250,6 +382,7 @@ extern int _rl_bell_preference; extern int _rl_meta_flag; extern int _rl_convert_meta_chars_to_ascii; extern int _rl_output_meta_chars; +extern int _rl_bind_stty_chars; extern char *_rl_comment_begin; extern unsigned char _rl_parsing_conditionalized_out; extern Keymap _rl_keymap; @@ -259,6 +392,9 @@ extern int _rl_last_command_was_kill; extern int _rl_eof_char; extern procenv_t readline_top_level; +/* search.c */ +extern _rl_search_cxt *_rl_nscxt; + /* terminal.c */ extern int _rl_enable_keypad; extern int _rl_enable_meta; @@ -272,6 +408,7 @@ extern char *_rl_term_up; extern char *_rl_term_dc; extern char *_rl_term_cr; extern char *_rl_term_IC; +extern char *_rl_term_forward_char; extern int _rl_screenheight; extern int _rl_screenwidth; extern int _rl_screenchars; diff --git a/cmd-line-utils/readline/rltty.c b/cmd-line-utils/readline/rltty.c index 869538af9ab..12f3a93e524 100644 --- a/cmd-line-utils/readline/rltty.c +++ b/cmd-line-utils/readline/rltty.c @@ -1,7 +1,7 @@ /* rltty.c -- functions to prepare and restore the terminal for readline's use. */ -/* Copyright (C) 1992 Free Software Foundation, Inc. +/* Copyright (C) 1992-2005 Free Software Foundation, Inc. This file is part of the GNU Readline Library, a library for reading lines of text with interactive input and history editing. @@ -22,7 +22,9 @@ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #define READLINE_LIBRARY -#include "config_readline.h" +#if defined (HAVE_CONFIG_H) +# include +#endif #include #include @@ -149,7 +151,9 @@ set_winsize (int tty __attribute__((unused))) #endif /* TIOCGWINSZ */ } -#if defined (NEW_TTY_DRIVER) +#if defined (NO_TTY_DRIVER) +/* Nothing */ +#elif defined (NEW_TTY_DRIVER) /* Values for the `flags' field of a struct bsdtty. This tells which elements of the struct bsdtty have been fetched from the system and @@ -230,6 +234,7 @@ get_tty_settings (tty, tiop) tiop->flags = tiop->lflag = 0; + errno = 0; if (ioctl (tty, TIOCGETP, &(tiop->sgttyb)) < 0) return -1; tiop->flags |= SGTTY_SET; @@ -515,6 +520,7 @@ get_tty_settings (tty, tiop) { set_winsize (tty); + errno = 0; if (_get_tty_settings (tty, tiop) < 0) return -1; @@ -628,9 +634,23 @@ prepare_terminal_settings (meta_flag, oldtio, tiop) #endif /* TERMIOS_TTY_DRIVER && _POSIX_VDISABLE */ } -#endif /* NEW_TTY_DRIVER */ +#endif /* !NEW_TTY_DRIVER */ /* Put the terminal in CBREAK mode so that we can detect key presses. */ +#if defined (NO_TTY_DRIVER) +void +rl_prep_terminal (meta_flag) + int meta_flag; +{ + readline_echoing_p = 1; +} + +void +rl_deprep_terminal () +{ +} + +#else /* ! NO_TTY_DRIVER */ void rl_prep_terminal (meta_flag) int meta_flag; @@ -648,16 +668,43 @@ rl_prep_terminal (meta_flag) if (get_tty_settings (tty, &tio) < 0) { +#if defined (ENOTSUP) + /* MacOS X, at least, lies about the value of errno if tcgetattr fails. */ + if (errno == ENOTTY || errno == ENOTSUP) +#else + if (errno == ENOTTY) +#endif + readline_echoing_p = 1; /* XXX */ release_sigint (); return; } otio = tio; - rl_tty_unset_default_bindings (_rl_keymap); + if (_rl_bind_stty_chars) + { +#if defined (VI_MODE) + /* If editing in vi mode, make sure we restore the bindings in the + insertion keymap no matter what keymap we ended up in. */ + if (rl_editing_mode == vi_mode) + rl_tty_unset_default_bindings (vi_insertion_keymap); + else +#endif + rl_tty_unset_default_bindings (_rl_keymap); + } save_tty_chars (&otio); RL_SETSTATE(RL_STATE_TTYCSAVED); - _rl_bind_tty_special_chars (_rl_keymap, tio); + if (_rl_bind_stty_chars) + { +#if defined (VI_MODE) + /* If editing in vi mode, make sure we set the bindings in the + insertion keymap no matter what keymap we ended up in. */ + if (rl_editing_mode == vi_mode) + _rl_bind_tty_special_chars (vi_insertion_keymap, tio); + else +#endif + _rl_bind_tty_special_chars (_rl_keymap, tio); + } prepare_terminal_settings (meta_flag, otio, &tio); @@ -707,6 +754,7 @@ rl_deprep_terminal () release_sigint (); } +#endif /* !NO_TTY_DRIVER */ /* **************************************************************** */ /* */ @@ -715,8 +763,13 @@ rl_deprep_terminal () /* **************************************************************** */ int -rl_restart_output(int count __attribute__((unused)), int key __attribute__((unused))) +rl_restart_output (count, key) + int count, key; { +#if defined (__MINGW32__) + return 0; +#else /* !__MING32__ */ + int fildes = fileno (rl_outstream); #if defined (TIOCSTART) #if defined (apollo) @@ -744,11 +797,17 @@ rl_restart_output(int count __attribute__((unused)), int key __attribute__((unus #endif /* !TIOCSTART */ return 0; +#endif /* !__MINGW32__ */ } int -rl_stop_output(int count __attribute__((unused)), int key __attribute__((unused))) +rl_stop_output (count, key) + int count, key; { +#if defined (__MINGW32__) + return 0; +#else + int fildes = fileno (rl_instream); #if defined (TIOCSTOP) @@ -771,6 +830,7 @@ rl_stop_output(int count __attribute__((unused)), int key __attribute__((unused) #endif /* !TIOCSTOP */ return 0; +#endif /* !__MINGW32__ */ } /* **************************************************************** */ @@ -779,9 +839,16 @@ rl_stop_output(int count __attribute__((unused)), int key __attribute__((unused) /* */ /* **************************************************************** */ +#if !defined (NO_TTY_DRIVER) #define SET_SPECIAL(sc, func) set_special_char(kmap, &ttybuff, sc, func) +#endif -#if defined (NEW_TTY_DRIVER) +#if defined (NO_TTY_DRIVER) + +#define SET_SPECIAL(sc, func) +#define RESET_SPECIAL(c) + +#elif defined (NEW_TTY_DRIVER) static void set_special_char (kmap, tiop, sc, func) Keymap kmap; @@ -862,6 +929,7 @@ void rltty_set_default_bindings (kmap) Keymap kmap; { +#if !defined (NO_TTY_DRIVER) TIOTYPE ttybuff; int tty; @@ -869,6 +937,7 @@ rltty_set_default_bindings (kmap) if (get_tty_settings (tty, &ttybuff) == 0) _rl_bind_tty_special_chars (kmap, ttybuff); +#endif } /* New public way to set the system default editing chars to their readline @@ -906,7 +975,7 @@ rl_tty_unset_default_bindings (kmap) #if defined (HANDLE_SIGNALS) -#if defined (NEW_TTY_DRIVER) +#if defined (NEW_TTY_DRIVER) || defined (NO_TTY_DRIVER) int _rl_disable_tty_signals () { diff --git a/cmd-line-utils/readline/savestring.c b/cmd-line-utils/readline/savestring.c index ae605374d13..820428d8881 100644 --- a/cmd-line-utils/readline/savestring.c +++ b/cmd-line-utils/readline/savestring.c @@ -21,8 +21,7 @@ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #define READLINE_LIBRARY -#include "config_readline.h" - +#include #ifdef HAVE_STRING_H # include #endif diff --git a/cmd-line-utils/readline/search.c b/cmd-line-utils/readline/search.c index 6479427be2f..33cc4fc1e73 100644 --- a/cmd-line-utils/readline/search.c +++ b/cmd-line-utils/readline/search.c @@ -1,6 +1,6 @@ /* search.c - code for non-incremental searching in emacs and vi modes. */ -/* Copyright (C) 1992 Free Software Foundation, Inc. +/* Copyright (C) 1992-2005 Free Software Foundation, Inc. This file is part of the Readline Library (the Library), a set of routines for providing Emacs style line input to programs that ask @@ -22,7 +22,9 @@ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #define READLINE_LIBRARY -#include "config_readline.h" +#if defined (HAVE_CONFIG_H) +# include +#endif #include #include @@ -51,6 +53,8 @@ #endif #define abs(x) (((x) >= 0) ? (x) : -(x)) +_rl_search_cxt *_rl_nscxt = 0; + extern HIST_ENTRY *_rl_saved_line_for_history; /* Functions imported from the rest of the library. */ @@ -68,11 +72,16 @@ static int history_string_size; static void make_history_line_current PARAMS((HIST_ENTRY *)); static int noninc_search_from_pos PARAMS((char *, int, int)); -static void noninc_dosearch PARAMS((char *, int)); -static void noninc_search PARAMS((int, int)); +static int noninc_dosearch PARAMS((char *, int)); +static int noninc_search PARAMS((int, int)); static int rl_history_search_internal PARAMS((int, int)); static void rl_history_search_reinit PARAMS((void)); +static _rl_search_cxt *_rl_nsearch_init PARAMS((int, int)); +static int _rl_nsearch_cleanup PARAMS((_rl_search_cxt *, int)); +static void _rl_nsearch_abort PARAMS((_rl_search_cxt *)); +static int _rl_nsearch_dispatch PARAMS((_rl_search_cxt *, int)); + /* Make the data from the history entry ENTRY be the contents of the current line. This doesn't do anything with rl_point; the caller must set it. */ @@ -80,12 +89,15 @@ static void make_history_line_current (entry) HIST_ENTRY *entry; { -#if 0 - rl_replace_line (entry->line, 1); - rl_undo_list = (UNDO_LIST *)entry->data; -#else _rl_replace_text (entry->line, 0, rl_end); _rl_fix_point (1); +#if defined (VI_MODE) + if (rl_editing_mode == vi_mode) + /* POSIX.2 says that the `U' command doesn't affect the copy of any + command lines to the edit line. We're going to implement that by + making the undo list start after the matching line is copied to the + current editing buffer. */ + rl_free_undo_list (); #endif if (_rl_saved_line_for_history) @@ -128,8 +140,8 @@ noninc_search_from_pos (string, pos, dir) /* Search for a line in the history containing STRING. If DIR is < 0, the search is backwards through previous entries, else through subsequent - entries. */ -static void + entries. Returns 1 if the search was successful, 0 otherwise. */ +static int noninc_dosearch (string, dir) char *string; int dir; @@ -140,7 +152,7 @@ noninc_dosearch (string, dir) if (string == 0 || *string == '\0' || noninc_history_pos < 0) { rl_ding (); - return; + return 0; } pos = noninc_search_from_pos (string, noninc_history_pos + dir, dir); @@ -151,7 +163,7 @@ noninc_dosearch (string, dir) rl_clear_message (); rl_point = 0; rl_ding (); - return; + return 0; } noninc_history_pos = pos; @@ -162,7 +174,7 @@ noninc_dosearch (string, dir) #if defined (VI_MODE) if (rl_editing_mode != vi_mode) #endif - history_set_pos (oldpos); + history_set_pos (oldpos); make_history_line_current (entry); @@ -170,27 +182,24 @@ noninc_dosearch (string, dir) rl_mark = rl_end; rl_clear_message (); + return 1; } -/* Search non-interactively through the history list. DIR < 0 means to - search backwards through the history of previous commands; otherwise - the search is for commands subsequent to the current position in the - history list. PCHAR is the character to use for prompting when reading - the search string; if not specified (0), it defaults to `:'. */ -static void -noninc_search (dir, pchar) - int dir; - int pchar; +static _rl_search_cxt * +_rl_nsearch_init (dir, pchar) + int dir, pchar; { - int saved_point, saved_mark, c; + _rl_search_cxt *cxt; char *p; -#if defined (HANDLE_MULTIBYTE) - char mb[MB_LEN_MAX]; -#endif + + cxt = _rl_scxt_alloc (RL_SEARCH_NSEARCH, 0); + if (dir < 0) + cxt->sflags |= SF_REVERSE; /* not strictly needed */ + + cxt->direction = dir; + cxt->history_pos = cxt->save_line; rl_maybe_save_line (); - saved_point = rl_point; - saved_mark = rl_mark; /* Clear the undo list, since reading the search string should create its own undo list, and the whole list will end up being freed when we @@ -202,152 +211,243 @@ noninc_search (dir, pchar) rl_end = rl_point = 0; p = _rl_make_prompt_for_search (pchar ? pchar : ':'); - rl_message (p, 0, 0); + rl_message ("%s", p, 0); free (p); -#define SEARCH_RETURN rl_restore_prompt (); RL_UNSETSTATE(RL_STATE_NSEARCH); return - RL_SETSTATE(RL_STATE_NSEARCH); - /* Read the search string. */ - while (1) - { - RL_SETSTATE(RL_STATE_MOREINPUT); - c = rl_read_key (); - RL_UNSETSTATE(RL_STATE_MOREINPUT); + _rl_nscxt = cxt; + + return cxt; +} + +static int +_rl_nsearch_cleanup (cxt, r) + _rl_search_cxt *cxt; + int r; +{ + _rl_scxt_dispose (cxt, 0); + _rl_nscxt = 0; + + RL_UNSETSTATE(RL_STATE_NSEARCH); + + return (r != 1); +} + +static void +_rl_nsearch_abort (cxt) + _rl_search_cxt *cxt; +{ + rl_maybe_unsave_line (); + rl_clear_message (); + rl_point = cxt->save_point; + rl_mark = cxt->save_mark; + rl_restore_prompt (); + + RL_UNSETSTATE (RL_STATE_NSEARCH); +} + +/* Process just-read character C according to search context CXT. Return -1 + if the caller should abort the search, 0 if we should break out of the + loop, and 1 if we should continue to read characters. */ +static int +_rl_nsearch_dispatch (cxt, c) + _rl_search_cxt *cxt; + int c; +{ + switch (c) + { + case CTRL('W'): + rl_unix_word_rubout (1, c); + break; + + case CTRL('U'): + rl_unix_line_discard (1, c); + break; + + case RETURN: + case NEWLINE: + return 0; + + case CTRL('H'): + case RUBOUT: + if (rl_point == 0) + { + _rl_nsearch_abort (cxt); + return -1; + } + _rl_rubout_char (1, c); + break; + + case CTRL('C'): + case CTRL('G'): + rl_ding (); + _rl_nsearch_abort (cxt); + return -1; + + default: #if defined (HANDLE_MULTIBYTE) if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - c = _rl_read_mbstring (c, mb, MB_LEN_MAX); + rl_insert_text (cxt->mb); + else #endif - - if (c == 0) - break; - - switch (c) - { - case CTRL('H'): - case RUBOUT: - if (rl_point == 0) - { - rl_maybe_unsave_line (); - rl_clear_message (); - rl_point = saved_point; - rl_mark = saved_mark; - SEARCH_RETURN; - } - _rl_rubout_char (1, c); - break; - - case CTRL('W'): - rl_unix_word_rubout (1, c); - break; - - case CTRL('U'): - rl_unix_line_discard (1, c); - break; - - case RETURN: - case NEWLINE: - goto dosearch; - /* NOTREACHED */ - break; - - case CTRL('C'): - case CTRL('G'): - rl_maybe_unsave_line (); - rl_clear_message (); - rl_point = saved_point; - rl_mark = saved_mark; - rl_ding (); - SEARCH_RETURN; - - default: -#if defined (HANDLE_MULTIBYTE) - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - rl_insert_text (mb); - else -#endif - _rl_insert_char (1, c); - break; - } - (*rl_redisplay_function) (); + _rl_insert_char (1, c); + break; } - dosearch: - rl_mark = saved_mark; + (*rl_redisplay_function) (); + return 1; +} + +/* Perform one search according to CXT, using NONINC_SEARCH_STRING. Return + -1 if the search should be aborted, any other value means to clean up + using _rl_nsearch_cleanup (). Returns 1 if the search was successful, + 0 otherwise. */ +static int +_rl_nsearch_dosearch (cxt) + _rl_search_cxt *cxt; +{ + rl_mark = cxt->save_mark; /* If rl_point == 0, we want to re-use the previous search string and start from the saved history position. If there's no previous search string, punt. */ if (rl_point == 0) { - if (!noninc_search_string) + if (noninc_search_string == 0) { rl_ding (); - SEARCH_RETURN; + rl_restore_prompt (); + RL_UNSETSTATE (RL_STATE_NSEARCH); + return -1; } } else { /* We want to start the search from the current history position. */ - noninc_history_pos = where_history (); + noninc_history_pos = cxt->save_line; FREE (noninc_search_string); noninc_search_string = savestring (rl_line_buffer); + + /* If we don't want the subsequent undo list generated by the search + matching a history line to include the contents of the search string, + we need to clear rl_line_buffer here. For now, we just clear the + undo list generated by reading the search string. (If the search + fails, the old undo list will be restored by rl_maybe_unsave_line.) */ + rl_free_undo_list (); } rl_restore_prompt (); - noninc_dosearch (noninc_search_string, dir); - RL_UNSETSTATE(RL_STATE_NSEARCH); + return (noninc_dosearch (noninc_search_string, cxt->direction)); +} + +/* Search non-interactively through the history list. DIR < 0 means to + search backwards through the history of previous commands; otherwise + the search is for commands subsequent to the current position in the + history list. PCHAR is the character to use for prompting when reading + the search string; if not specified (0), it defaults to `:'. */ +static int +noninc_search (dir, pchar) + int dir; + int pchar; +{ + _rl_search_cxt *cxt; + int c, r; + + cxt = _rl_nsearch_init (dir, pchar); + + if (RL_ISSTATE (RL_STATE_CALLBACK)) + return (0); + + /* Read the search string. */ + r = 0; + while (1) + { + c = _rl_search_getchar (cxt); + + if (c == 0) + break; + + r = _rl_nsearch_dispatch (cxt, c); + if (r < 0) + return 1; + else if (r == 0) + break; + } + + r = _rl_nsearch_dosearch (cxt); + return ((r >= 0) ? _rl_nsearch_cleanup (cxt, r) : (r != 1)); } /* Search forward through the history list for a string. If the vi-mode code calls this, KEY will be `?'. */ int -rl_noninc_forward_search (int count __attribute__((unused)), int key) +rl_noninc_forward_search (count, key) + int count, key; { - noninc_search (1, (key == '?') ? '?' : 0); - return 0; + return noninc_search (1, (key == '?') ? '?' : 0); } /* Reverse search the history list for a string. If the vi-mode code calls this, KEY will be `/'. */ int -rl_noninc_reverse_search (int count __attribute__((unused)), int key) +rl_noninc_reverse_search (count, key) + int count, key; { - noninc_search (-1, (key == '/') ? '/' : 0); - return 0; + return noninc_search (-1, (key == '/') ? '/' : 0); } /* Search forward through the history list for the last string searched for. If there is no saved search string, abort. */ int -rl_noninc_forward_search_again (int count __attribute__((unused)), - int key __attribute__((unused))) +rl_noninc_forward_search_again (count, key) + int count, key; { + int r; + if (!noninc_search_string) { rl_ding (); return (-1); } - noninc_dosearch (noninc_search_string, 1); - return 0; + r = noninc_dosearch (noninc_search_string, 1); + return (r != 1); } /* Reverse search in the history list for the last string searched for. If there is no saved search string, abort. */ int -rl_noninc_reverse_search_again (int count __attribute__((unused)), - int key __attribute__((unused))) +rl_noninc_reverse_search_again (count, key) + int count, key; { + int r; + if (!noninc_search_string) { rl_ding (); return (-1); } - noninc_dosearch (noninc_search_string, -1); - return 0; + r = noninc_dosearch (noninc_search_string, -1); + return (r != 1); } +#if defined (READLINE_CALLBACKS) +int +_rl_nsearch_callback (cxt) + _rl_search_cxt *cxt; +{ + int c, r; + + c = _rl_search_getchar (cxt); + r = _rl_nsearch_dispatch (cxt, c); + if (r != 0) + return 1; + + r = _rl_nsearch_dosearch (cxt); + return ((r >= 0) ? _rl_nsearch_cleanup (cxt, r) : (r != 1)); +} +#endif + static int rl_history_search_internal (count, dir) int count, dir; diff --git a/cmd-line-utils/readline/shell.c b/cmd-line-utils/readline/shell.c index 41668d70ab5..346f8113d43 100644 --- a/cmd-line-utils/readline/shell.c +++ b/cmd-line-utils/readline/shell.c @@ -22,7 +22,9 @@ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #define READLINE_LIBRARY -#include "config_readline.h" +#if defined (HAVE_CONFIG_H) +# include +#endif #include @@ -46,8 +48,12 @@ # include #endif +#if defined (HAVE_FCNTL_H) #include +#endif +#if defined (HAVE_PWD_H) #include +#endif #include @@ -55,9 +61,9 @@ #include "rlshell.h" #include "xmalloc.h" -#if !defined (HAVE_GETPW_DECLS) +#if defined (HAVE_GETPWUID) && !defined (HAVE_GETPW_DECLS) extern struct passwd *getpwuid PARAMS((uid_t)); -#endif /* !HAVE_GETPW_DECLS */ +#endif /* HAVE_GETPWUID && !HAVE_GETPW_DECLS */ #ifndef NULL # define NULL 0 @@ -120,16 +126,7 @@ sh_set_lines_and_columns (lines, cols) { char *b; -#if defined (HAVE_PUTENV) - b = (char *)xmalloc (INT_STRLEN_BOUND (int) + sizeof ("LINES=") + 1); - sprintf (b, "LINES=%d", lines); - putenv (b); - - b = (char *)xmalloc (INT_STRLEN_BOUND (int) + sizeof ("COLUMNS=") + 1); - sprintf (b, "COLUMNS=%d", cols); - putenv (b); -#else /* !HAVE_PUTENV */ -# if defined (HAVE_SETENV) +#if defined (HAVE_SETENV) b = (char *)xmalloc (INT_STRLEN_BOUND (int) + 1); sprintf (b, "%d", lines); setenv ("LINES", b, 1); @@ -139,8 +136,17 @@ sh_set_lines_and_columns (lines, cols) sprintf (b, "%d", cols); setenv ("COLUMNS", b, 1); free (b); -# endif /* HAVE_SETENV */ -#endif /* !HAVE_PUTENV */ +#else /* !HAVE_SETENV */ +# if defined (HAVE_PUTENV) + b = (char *)xmalloc (INT_STRLEN_BOUND (int) + sizeof ("LINES=") + 1); + sprintf (b, "LINES=%d", lines); + putenv (b); + + b = (char *)xmalloc (INT_STRLEN_BOUND (int) + sizeof ("COLUMNS=") + 1); + sprintf (b, "COLUMNS=%d", cols); + putenv (b); +# endif /* HAVE_PUTENV */ +#endif /* !HAVE_SETENV */ } char * @@ -157,9 +163,11 @@ sh_get_home_dir () struct passwd *entry; home_dir = (char *)NULL; +#if defined (HAVE_GETPWUID) entry = getpwuid (getuid ()); if (entry) home_dir = entry->pw_dir; +#endif return (home_dir); } @@ -173,6 +181,7 @@ int sh_unset_nodelay_mode (fd) int fd; { +#if defined (HAVE_FCNTL) int flags, bflags; if ((flags = fcntl (fd, F_GETFL, 0)) < 0) @@ -193,6 +202,7 @@ sh_unset_nodelay_mode (fd) flags &= ~bflags; return (fcntl (fd, F_SETFL, flags)); } +#endif return 0; } diff --git a/cmd-line-utils/readline/signals.c b/cmd-line-utils/readline/signals.c index be1150f6c54..54f2a642846 100644 --- a/cmd-line-utils/readline/signals.c +++ b/cmd-line-utils/readline/signals.c @@ -1,6 +1,6 @@ /* signals.c -- signal handling support for readline. */ -/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc. +/* Copyright (C) 1987-2005 Free Software Foundation, Inc. This file is part of the GNU Readline Library, a library for reading lines of text with interactive input and history editing. @@ -21,7 +21,9 @@ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #define READLINE_LIBRARY -#include "config_readline.h" +#if defined (HAVE_CONFIG_H) +# include +#endif #include /* Just for NULL. Yuck. */ #include @@ -129,7 +131,11 @@ rl_signal_handler (sig) #if !defined (HAVE_BSD_SIGNALS) && !defined (HAVE_POSIX_SIGNALS) /* Since the signal will not be blocked while we are in the signal handler, ignore it until rl_clear_signals resets the catcher. */ +# if defined (SIGALRM) if (sig == SIGINT || sig == SIGALRM) +# else + if (sig == SIGINT) +# endif rl_set_sighandler (sig, SIG_IGN, &dummy_cxt); #endif /* !HAVE_BSD_SIGNALS && !HAVE_POSIX_SIGNALS */ @@ -139,17 +145,22 @@ rl_signal_handler (sig) rl_free_line_state (); /* FALLTHROUGH */ + case SIGTERM: #if defined (SIGTSTP) case SIGTSTP: case SIGTTOU: case SIGTTIN: #endif /* SIGTSTP */ +#if defined (SIGALRM) case SIGALRM: - case SIGTERM: +#endif +#if defined (SIGQUIT) case SIGQUIT: +#endif rl_cleanup_after_signal (); #if defined (HAVE_POSIX_SIGNALS) + sigemptyset (&set); sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &set); sigdelset (&set, sig); #else /* !HAVE_POSIX_SIGNALS */ @@ -162,7 +173,11 @@ rl_signal_handler (sig) signal (sig, SIG_ACK); #endif +#if defined (HAVE_KILL) kill (getpid (), sig); +#else + raise (sig); /* assume we have raise */ +#endif /* Let the signal that we just sent through. */ #if defined (HAVE_POSIX_SIGNALS) @@ -274,13 +289,51 @@ rl_set_signals () { sighandler_cxt dummy; SigHandler *oh; +#if defined (HAVE_POSIX_SIGNALS) + static int sigmask_set = 0; + static sigset_t bset, oset; +#endif + +#if defined (HAVE_POSIX_SIGNALS) + if (rl_catch_signals && sigmask_set == 0) + { + sigemptyset (&bset); + + sigaddset (&bset, SIGINT); + sigaddset (&bset, SIGINT); +#if defined (SIGQUIT) + sigaddset (&bset, SIGQUIT); +#endif +#if defined (SIGALRM) + sigaddset (&bset, SIGALRM); +#endif +#if defined (SIGTSTP) + sigaddset (&bset, SIGTSTP); +#endif +#if defined (SIGTTIN) + sigaddset (&bset, SIGTTIN); +#endif +#if defined (SIGTTOU) + sigaddset (&bset, SIGTTOU); +#endif + sigmask_set = 1; + } +#endif /* HAVE_POSIX_SIGNALS */ if (rl_catch_signals && signals_set_flag == 0) { +#if defined (HAVE_POSIX_SIGNALS) + sigemptyset (&oset); + sigprocmask (SIG_BLOCK, &bset, &oset); +#endif + rl_maybe_set_sighandler (SIGINT, rl_signal_handler, &old_int); rl_maybe_set_sighandler (SIGTERM, rl_signal_handler, &old_term); +#if defined (SIGQUIT) rl_maybe_set_sighandler (SIGQUIT, rl_signal_handler, &old_quit); +#endif +#if defined (SIGALRM) oh = rl_set_sighandler (SIGALRM, rl_signal_handler, &old_alrm); if (oh == (SigHandler *)SIG_IGN) rl_sigaction (SIGALRM, &old_alrm, &dummy); @@ -292,6 +345,7 @@ rl_set_signals () if (oh != (SigHandler *)SIG_DFL && (old_alrm.sa_flags & SA_RESTART)) rl_sigaction (SIGALRM, &old_alrm, &dummy); #endif /* HAVE_POSIX_SIGNALS */ +#endif /* SIGALRM */ #if defined (SIGTSTP) rl_maybe_set_sighandler (SIGTSTP, rl_signal_handler, &old_tstp); @@ -306,6 +360,10 @@ rl_set_signals () #endif /* SIGTTIN */ signals_set_flag = 1; + +#if defined (HAVE_POSIX_SIGNALS) + sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL); +#endif } #if defined (SIGWINCH) @@ -330,8 +388,12 @@ rl_clear_signals () rl_sigaction (SIGINT, &old_int, &dummy); rl_sigaction (SIGTERM, &old_term, &dummy); +#if defined (SIGQUIT) rl_sigaction (SIGQUIT, &old_quit, &dummy); +#endif +#if defined (SIGALRM) rl_sigaction (SIGALRM, &old_alrm, &dummy); +#endif #if defined (SIGTSTP) rl_sigaction (SIGTSTP, &old_tstp, &dummy); @@ -366,16 +428,18 @@ void rl_cleanup_after_signal () { _rl_clean_up_for_exit (); - (*rl_deprep_term_function) (); - rl_clear_signals (); + if (rl_deprep_term_function) + (*rl_deprep_term_function) (); rl_clear_pending_input (); + rl_clear_signals (); } /* Reset the terminal and readline state after a signal handler returns. */ void rl_reset_after_signal () { - (*rl_prep_term_function) (_rl_meta_flag); + if (rl_prep_term_function) + (*rl_prep_term_function) (_rl_meta_flag); rl_set_signals (); } @@ -396,7 +460,7 @@ rl_free_line_state () _rl_kill_kbd_macro (); rl_clear_message (); - _rl_init_argument (); + _rl_reset_argument (); } #endif /* HANDLE_SIGNALS */ diff --git a/cmd-line-utils/readline/terminal.c b/cmd-line-utils/readline/terminal.c index 4b900c5d860..547f6f5dfe5 100644 --- a/cmd-line-utils/readline/terminal.c +++ b/cmd-line-utils/readline/terminal.c @@ -1,6 +1,6 @@ /* terminal.c -- controlling the terminal with termcap. */ -/* Copyright (C) 1996 Free Software Foundation, Inc. +/* Copyright (C) 1996-2006 Free Software Foundation, Inc. This file is part of the GNU Readline Library, a library for reading lines of text with interactive input and history editing. @@ -21,7 +21,9 @@ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #define READLINE_LIBRARY -#include "config_readline.h" +#if defined (HAVE_CONFIG_H) +# include +#endif #include #include "posixstat.h" @@ -64,9 +66,25 @@ #include "rlshell.h" #include "xmalloc.h" +#if defined (__MINGW32__) +# include +# include + +static void _win_get_screensize PARAMS((int *, int *)); +#endif + +#if defined (__EMX__) +static void _emx_get_screensize PARAMS((int *, int *)); +#endif + #define CUSTOM_REDISPLAY_FUNC() (rl_redisplay_function != rl_redisplay) #define CUSTOM_INPUT_FUNC() (rl_getc_function != rl_getc) +/* If the calling application sets this to a non-zero value, readline will + use the $LINES and $COLUMNS environment variables to set its idea of the + window size before interrogating the kernel. */ +int rl_prefer_env_winsize = 0; + /* **************************************************************** */ /* */ /* Terminal and Termcap */ @@ -107,9 +125,7 @@ char *_rl_term_IC; char *_rl_term_dc; char *_rl_term_DC; -#if defined (HACK_TERMCAP_MOTION) char *_rl_term_forward_char; -#endif /* HACK_TERMCAP_MOTION */ /* How to go up a line. */ char *_rl_term_up; @@ -118,7 +134,7 @@ char *_rl_term_up; static char *_rl_visible_bell; /* Non-zero means the terminal can auto-wrap lines. */ -int _rl_term_autowrap; +int _rl_term_autowrap = -1; /* Non-zero means that this terminal has a meta key. */ static int term_has_meta; @@ -143,6 +159,9 @@ static char *_rl_term_kh; static char *_rl_term_kH; static char *_rl_term_at7; /* @7 */ +/* Delete key */ +static char *_rl_term_kD; + /* Insert key */ static char *_rl_term_kI; @@ -177,6 +196,26 @@ _emx_get_screensize (swp, shp) } #endif +#if defined (__MINGW32__) +static void +_win_get_screensize (swp, shp) + int *swp, *shp; +{ + HANDLE hConOut; + CONSOLE_SCREEN_BUFFER_INFO scr; + + hConOut = GetStdHandle (STD_OUTPUT_HANDLE); + if (hConOut != INVALID_HANDLE_VALUE) + { + if (GetConsoleScreenBufferInfo (hConOut, &scr)) + { + *swp = scr.dwSize.X; + *shp = scr.srWindow.Bottom - scr.srWindow.Top + 1; + } + } +} +#endif + /* Get readline's idea of the screen size. TTY is a file descriptor open to the terminal. If IGNORE_ENV is true, we do not pay attention to the values of $LINES and $COLUMNS. The tests for TERM_STRING_BUFFER being @@ -189,26 +228,42 @@ _rl_get_screen_size (tty, ignore_env) #if defined (TIOCGWINSZ) struct winsize window_size; #endif /* TIOCGWINSZ */ + int wr, wc; + wr = wc = -1; #if defined (TIOCGWINSZ) if (ioctl (tty, TIOCGWINSZ, &window_size) == 0) { - _rl_screenwidth = (int) window_size.ws_col; - _rl_screenheight = (int) window_size.ws_row; + wc = (int) window_size.ws_col; + wr = (int) window_size.ws_row; } #endif /* TIOCGWINSZ */ #if defined (__EMX__) - _emx_get_screensize (&_rl_screenwidth, &_rl_screenheight); + _emx_get_screensize (&wc, &wr); +#elif defined (__MINGW32__) + _win_get_screensize (&wc, &wr); #endif + if (ignore_env || rl_prefer_env_winsize == 0) + { + _rl_screenwidth = wc; + _rl_screenheight = wr; + } + else + _rl_screenwidth = _rl_screenheight = -1; + /* Environment variable COLUMNS overrides setting of "co" if IGNORE_ENV - is unset. */ + is unset. If we prefer the environment, check it first before + assigning the value returned by the kernel. */ if (_rl_screenwidth <= 0) { if (ignore_env == 0 && (ss = sh_get_env_value ("COLUMNS"))) _rl_screenwidth = atoi (ss); + if (_rl_screenwidth <= 0) + _rl_screenwidth = wc; + #if !defined (__DJGPP__) if (_rl_screenwidth <= 0 && term_string_buffer) _rl_screenwidth = tgetnum ("co"); @@ -222,6 +277,9 @@ _rl_get_screen_size (tty, ignore_env) if (ignore_env == 0 && (ss = sh_get_env_value ("LINES"))) _rl_screenheight = atoi (ss); + if (_rl_screenheight <= 0) + _rl_screenheight = wr; + #if !defined (__DJGPP__) if (_rl_screenheight <= 0 && term_string_buffer) _rl_screenheight = tgetnum ("li"); @@ -250,16 +308,20 @@ void _rl_set_screen_size (rows, cols) int rows, cols; { - if (rows == 0 || cols == 0) - return; + if (_rl_term_autowrap == -1) + _rl_init_terminal_io (rl_terminal_name); - _rl_screenheight = rows; - _rl_screenwidth = cols; + if (rows > 0) + _rl_screenheight = rows; + if (cols > 0) + { + _rl_screenwidth = cols; + if (_rl_term_autowrap == 0) + _rl_screenwidth--; + } - if (_rl_term_autowrap == 0) - _rl_screenwidth--; - - _rl_screenchars = _rl_screenwidth * _rl_screenheight; + if (rows > 0 || cols > 0) + _rl_screenchars = _rl_screenwidth * _rl_screenheight; } void @@ -278,6 +340,12 @@ rl_get_screen_size (rows, cols) if (cols) *cols = _rl_screenwidth; } + +void +rl_reset_screen_size () +{ + _rl_get_screen_size (fileno (rl_instream), 0); +} void rl_resize_terminal () @@ -311,6 +379,7 @@ static struct _tc_string tc_strings[] = { "ei", &_rl_term_ei }, { "ic", &_rl_term_ic }, { "im", &_rl_term_im }, + { "kD", &_rl_term_kD }, /* delete */ { "kH", &_rl_term_kH }, /* home down ?? */ { "kI", &_rl_term_kI }, /* insert */ { "kd", &_rl_term_kd }, @@ -323,9 +392,7 @@ static struct _tc_string tc_strings[] = { "le", &_rl_term_backspace }, { "mm", &_rl_term_mm }, { "mo", &_rl_term_mo }, -#if defined (HACK_TERMCAP_MOTION) { "nd", &_rl_term_forward_char }, -#endif { "pc", &_rl_term_pc }, { "up", &_rl_term_up }, { "vb", &_rl_visible_bell }, @@ -344,7 +411,7 @@ get_term_capabilities (bp) #if !defined (__DJGPP__) /* XXX - doesn't DJGPP have a termcap library? */ register int i; - for (i = 0; i < (int) NUM_TC_STRINGS; i++) + for (i = 0; i < NUM_TC_STRINGS; i++) *(tc_strings[i].tc_value) = tgetstr ((char *)tc_strings[i].tc_var, bp); #endif tcap_initialized = 1; @@ -361,7 +428,6 @@ _rl_init_terminal_io (terminal_name) term = terminal_name ? terminal_name : sh_get_env_value ("TERM"); _rl_term_clrpag = _rl_term_cr = _rl_term_clreol = (char *)NULL; tty = rl_instream ? fileno (rl_instream) : 0; - _rl_screenwidth = _rl_screenheight = 0; if (term == 0) term = "dumb"; @@ -394,12 +460,17 @@ _rl_init_terminal_io (terminal_name) _rl_term_autowrap = 0; /* used by _rl_get_screen_size */ + /* Allow calling application to set default height and width, using + rl_set_screen_size */ + if (_rl_screenwidth <= 0 || _rl_screenheight <= 0) + { #if defined (__EMX__) - _emx_get_screensize (&_rl_screenwidth, &_rl_screenheight); - _rl_screenwidth--; + _emx_get_screensize (&_rl_screenwidth, &_rl_screenheight); + _rl_screenwidth--; #else /* !__EMX__ */ - _rl_get_screen_size (tty, 0); + _rl_get_screen_size (tty, 0); #endif /* !__EMX__ */ + } /* Defaults. */ if (_rl_screenwidth <= 0 || _rl_screenheight <= 0) @@ -410,24 +481,22 @@ _rl_init_terminal_io (terminal_name) /* Everything below here is used by the redisplay code (tputs). */ _rl_screenchars = _rl_screenwidth * _rl_screenheight; - _rl_term_cr = (char*) "\r"; + _rl_term_cr = "\r"; _rl_term_im = _rl_term_ei = _rl_term_ic = _rl_term_IC = (char *)NULL; _rl_term_up = _rl_term_dc = _rl_term_DC = _rl_visible_bell = (char *)NULL; _rl_term_ku = _rl_term_kd = _rl_term_kl = _rl_term_kr = (char *)NULL; - _rl_term_kh = _rl_term_kH = _rl_term_kI = (char *)NULL; + _rl_term_kh = _rl_term_kH = _rl_term_kI = _rl_term_kD = (char *)NULL; _rl_term_ks = _rl_term_ke = _rl_term_at7 = (char *)NULL; _rl_term_mm = _rl_term_mo = (char *)NULL; _rl_term_ve = _rl_term_vs = (char *)NULL; -#if defined (HACK_TERMCAP_MOTION) - term_forward_char = (char *)NULL; -#endif + _rl_term_forward_char = (char *)NULL; _rl_terminal_can_insert = term_has_meta = 0; /* Reasonable defaults for tgoto(). Readline currently only uses tgoto if _rl_term_IC or _rl_term_DC is defined, but just in case we change that later... */ PC = '\0'; - BC = _rl_term_backspace = (char*) "\b"; + BC = _rl_term_backspace = "\b"; UP = _rl_term_up; return 0; @@ -442,11 +511,14 @@ _rl_init_terminal_io (terminal_name) UP = _rl_term_up; if (!_rl_term_cr) - _rl_term_cr = (char*) "\r"; + _rl_term_cr = "\r"; _rl_term_autowrap = tgetflag ("am") && tgetflag ("xn"); - _rl_get_screen_size (tty, 0); + /* Allow calling application to set default height and width, using + rl_set_screen_size */ + if (_rl_screenwidth <= 0 || _rl_screenheight <= 0) + _rl_get_screen_size (tty, 0); /* "An application program can assume that the terminal can do character insertion if *any one of* the capabilities `IC', @@ -491,6 +563,8 @@ bind_termcap_arrow_keys (map) rl_bind_keyseq_if_unbound (_rl_term_kh, rl_beg_of_line); /* Home */ rl_bind_keyseq_if_unbound (_rl_term_at7, rl_end_of_line); /* End */ + rl_bind_keyseq_if_unbound (_rl_term_kD, rl_delete); + _rl_keymap = xkeymap; } @@ -502,7 +576,7 @@ rl_get_termcap (cap) if (tcap_initialized == 0) return ((char *)NULL); - for (i = 0; i < (int) NUM_TC_STRINGS; i++) + for (i = 0; i < NUM_TC_STRINGS; i++) { if (tc_strings[i].tc_var[0] == cap[0] && strcmp (tc_strings[i].tc_var, cap) == 0) return *(tc_strings[i].tc_value); @@ -516,6 +590,7 @@ int rl_reset_terminal (terminal_name) const char *terminal_name; { + _rl_screenwidth = _rl_screenheight = 0; _rl_init_terminal_io (terminal_name); return 0; } diff --git a/cmd-line-utils/readline/text.c b/cmd-line-utils/readline/text.c index cf9223df844..399a48c5f1e 100644 --- a/cmd-line-utils/readline/text.c +++ b/cmd-line-utils/readline/text.c @@ -1,6 +1,6 @@ /* text.c -- text handling commands for readline. */ -/* Copyright (C) 1987-2004 Free Software Foundation, Inc. +/* Copyright (C) 1987-2005 Free Software Foundation, Inc. This file is part of the GNU Readline Library, a library for reading lines of text with interactive input and history editing. @@ -21,7 +21,9 @@ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #define READLINE_LIBRARY -#include "config_readline.h" +#if defined (HAVE_CONFIG_H) +# include +#endif #if defined (HAVE_UNISTD_H) # include @@ -60,6 +62,11 @@ static int rl_change_case PARAMS((int, int)); static int _rl_char_search PARAMS((int, int, int)); +#if defined (READLINE_CALLBACKS) +static int _rl_insert_next_callback PARAMS((_rl_callback_generic_arg *)); +static int _rl_char_search_callback PARAMS((_rl_callback_generic_arg *)); +#endif + /* **************************************************************** */ /* */ /* Insert and Delete */ @@ -402,7 +409,8 @@ rl_backward (count, key) /* Move to the beginning of the line. */ int -rl_beg_of_line (int count __attribute__((unused)), int key __attribute__((unused))) +rl_beg_of_line (count, key) + int count, key; { rl_point = 0; return 0; @@ -410,14 +418,14 @@ rl_beg_of_line (int count __attribute__((unused)), int key __attribute__((unused /* Move to the end of the line. */ int -rl_end_of_line (int count __attribute__((unused)), int key __attribute__((unused))) +rl_end_of_line (count, key) + int count, key; { rl_point = rl_end; return 0; } -/* XXX - these might need changes for multibyte characters */ -/* Move forward a word. We do what Emacs does. */ +/* Move forward a word. We do what Emacs does. Handles multibyte chars. */ int rl_forward_word (count, key) int count, key; @@ -434,68 +442,80 @@ rl_forward_word (count, key) /* If we are not in a word, move forward until we are in one. Then, move forward until we hit a non-alphabetic character. */ - c = rl_line_buffer[rl_point]; - if (rl_alphabetic (c) == 0) + c = _rl_char_value (rl_line_buffer, rl_point); + + if (_rl_walphabetic (c) == 0) { - while (++rl_point < rl_end) + rl_point = MB_NEXTCHAR (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO); + while (rl_point < rl_end) { - c = rl_line_buffer[rl_point]; - if (rl_alphabetic (c)) + c = _rl_char_value (rl_line_buffer, rl_point); + if (_rl_walphabetic (c)) break; + rl_point = MB_NEXTCHAR (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO); } } if (rl_point == rl_end) return 0; - while (++rl_point < rl_end) + rl_point = MB_NEXTCHAR (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO); + while (rl_point < rl_end) { - c = rl_line_buffer[rl_point]; - if (rl_alphabetic (c) == 0) + c = _rl_char_value (rl_line_buffer, rl_point); + if (_rl_walphabetic (c) == 0) break; + rl_point = MB_NEXTCHAR (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO); } + --count; } return 0; } -/* Move backward a word. We do what Emacs does. */ +/* Move backward a word. We do what Emacs does. Handles multibyte chars. */ int rl_backward_word (count, key) int count, key; { - int c; + int c, p; if (count < 0) return (rl_forward_word (-count, key)); while (count) { - if (!rl_point) + if (rl_point == 0) return 0; /* Like rl_forward_word (), except that we look at the characters just before point. */ - c = rl_line_buffer[rl_point - 1]; - if (rl_alphabetic (c) == 0) + p = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_NONZERO); + c = _rl_char_value (rl_line_buffer, p); + + if (_rl_walphabetic (c) == 0) { - while (--rl_point) + rl_point = p; + while (rl_point > 0) { - c = rl_line_buffer[rl_point - 1]; - if (rl_alphabetic (c)) + p = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_NONZERO); + c = _rl_char_value (rl_line_buffer, p); + if (_rl_walphabetic (c)) break; + rl_point = p; } } while (rl_point) { - c = rl_line_buffer[rl_point - 1]; - if (rl_alphabetic (c) == 0) + p = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_NONZERO); + c = _rl_char_value (rl_line_buffer, p); + if (_rl_walphabetic (c) == 0) break; else - --rl_point; + rl_point = p; } --count; @@ -506,7 +526,8 @@ rl_backward_word (count, key) /* Clear the current line. Numeric argument to C-l does this. */ int -rl_refresh_line (int count __attribute__((unused)), int key __attribute__((unused))) +rl_refresh_line (ignore1, ignore2) + int ignore1, ignore2; { int curr_line; @@ -544,7 +565,8 @@ rl_clear_screen (count, key) } int -rl_arrow_keys (int count, int c __attribute__((unused))) +rl_arrow_keys (count, c) + int count, c; { int ch; @@ -592,7 +614,7 @@ rl_arrow_keys (int count, int c __attribute__((unused))) #ifdef HANDLE_MULTIBYTE static char pending_bytes[MB_LEN_MAX]; static int pending_bytes_length = 0; -static mbstate_t ps; +static mbstate_t ps = {0}; #endif /* Insert the character C at the current location, moving point forward. @@ -750,10 +772,8 @@ _rl_insert_char (count, c) return 0; } -#if defined (HANDLE_MULTIBYTE) if (MB_CUR_MAX == 1 || rl_byte_oriented) { -#endif /* We are inserting a single character. If there is pending input, then make a string of all of the pending characters that are bound to rl_insert, and insert @@ -769,8 +789,8 @@ _rl_insert_char (count, c) str[0] = c; rl_insert_text (str); } -#if defined (HANDLE_MULTIBYTE) } +#if defined (HANDLE_MULTIBYTE) else { rl_insert_text (incoming); @@ -827,29 +847,67 @@ rl_insert (count, c) } /* Insert the next typed character verbatim. */ -int -rl_quoted_insert (int count, int key __attribute__((unused))) +static int +_rl_insert_next (count) + int count; { int c; -#if defined (HANDLE_SIGNALS) - _rl_disable_tty_signals (); -#endif - RL_SETSTATE(RL_STATE_MOREINPUT); c = rl_read_key (); RL_UNSETSTATE(RL_STATE_MOREINPUT); #if defined (HANDLE_SIGNALS) - _rl_restore_tty_signals (); + if (RL_ISSTATE (RL_STATE_CALLBACK) == 0) + _rl_restore_tty_signals (); #endif return (_rl_insert_char (count, c)); } +#if defined (READLINE_CALLBACKS) +static int +_rl_insert_next_callback (data) + _rl_callback_generic_arg *data; +{ + int count; + + count = data->count; + + /* Deregister function, let rl_callback_read_char deallocate data */ + _rl_callback_func = 0; + _rl_want_redisplay = 1; + + return _rl_insert_next (count); +} +#endif + +int +rl_quoted_insert (count, key) + int count, key; +{ + /* Let's see...should the callback interface futz with signal handling? */ +#if defined (HANDLE_SIGNALS) + if (RL_ISSTATE (RL_STATE_CALLBACK) == 0) + _rl_disable_tty_signals (); +#endif + +#if defined (READLINE_CALLBACKS) + if (RL_ISSTATE (RL_STATE_CALLBACK)) + { + _rl_callback_data = _rl_callback_data_alloc (count); + _rl_callback_func = _rl_insert_next_callback; + return (0); + } +#endif + + return _rl_insert_next (count); +} + /* Insert a tab character. */ int -rl_tab_insert (int count, int key __attribute__((unused))) +rl_tab_insert (count, key) + int count, key; { return (_rl_insert_char (count, '\t')); } @@ -858,7 +916,8 @@ rl_tab_insert (int count, int key __attribute__((unused))) KEY is the key that invoked this command. I guess it could have meaning in the future. */ int -rl_newline (int count __attribute__((unused)), int key __attribute__((unused))) +rl_newline (count, key) + int count, key; { rl_done = 1; @@ -891,8 +950,8 @@ rl_newline (int count __attribute__((unused)), int key __attribute__((unused))) is just a stub, you bind keys to it and the code in _rl_dispatch () is special cased. */ int -rl_do_lowercase_version (int count __attribute__((unused)), - int key __attribute__((unused))) +rl_do_lowercase_version (ignore1, ignore2) + int ignore1, ignore2; { return 0; } @@ -979,43 +1038,17 @@ _rl_rubout_char (count, key) return -1; } + orig_point = rl_point; if (count > 1 || rl_explicit_arg) { - orig_point = rl_point; -#if defined (HANDLE_MULTIBYTE) - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - rl_backward_char (count, key); - else -#endif - rl_backward_byte (count, key); + rl_backward_char (count, key); rl_kill_text (orig_point, rl_point); } - else + else if (MB_CUR_MAX == 1 || rl_byte_oriented) { -#if defined (HANDLE_MULTIBYTE) - if (MB_CUR_MAX == 1 || rl_byte_oriented) - { -#endif - c = rl_line_buffer[--rl_point]; - rl_delete_text (rl_point, rl_point + 1); -#if defined (HANDLE_MULTIBYTE) - } - else - { - int orig_point2; - - orig_point2 = rl_point; - rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO); - c = rl_line_buffer[rl_point]; - rl_delete_text (rl_point, orig_point2); - } -#endif /* HANDLE_MULTIBYTE */ - - /* I don't think that the hack for end of line is needed for - multibyte chars. */ -#if defined (HANDLE_MULTIBYTE) - if (MB_CUR_MAX == 1 || rl_byte_oriented) -#endif + c = rl_line_buffer[--rl_point]; + rl_delete_text (rl_point, orig_point); + /* The erase-at-end-of-line hack is of questionable merit now. */ if (rl_point == rl_end && ISPRINT (c) && _rl_last_c_pos) { int l; @@ -1023,6 +1056,11 @@ _rl_rubout_char (count, key) _rl_erase_at_end_of_line (l); } } + else + { + rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO); + rl_delete_text (rl_point, orig_point); + } return 0; } @@ -1033,7 +1071,7 @@ int rl_delete (count, key) int count, key; { - int r; + int xpoint; if (count < 0) return (_rl_rubout_char (-count, key)); @@ -1046,28 +1084,21 @@ rl_delete (count, key) if (count > 1 || rl_explicit_arg) { - int orig_point = rl_point; -#if defined (HANDLE_MULTIBYTE) + xpoint = rl_point; if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) rl_forward_char (count, key); else -#endif rl_forward_byte (count, key); - r = rl_kill_text (orig_point, rl_point); - rl_point = orig_point; - return r; + rl_kill_text (xpoint, rl_point); + rl_point = xpoint; } else { - int new_point; - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - new_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO); - else - new_point = rl_point + 1; - - return (rl_delete_text (rl_point, new_point)); + xpoint = MB_NEXTCHAR (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO); + rl_delete_text (rl_point, xpoint); } + return 0; } /* Delete the character under the cursor, unless the insertion @@ -1086,8 +1117,8 @@ rl_rubout_or_delete (count, key) /* Delete all spaces and tabs around point. */ int -rl_delete_horizontal_space (int count __attribute__((unused)), - int key __attribute__((unused))) +rl_delete_horizontal_space (count, ignore) + int count, ignore; { int start = rl_point; @@ -1104,6 +1135,10 @@ rl_delete_horizontal_space (int count __attribute__((unused)), rl_delete_text (start, rl_point); rl_point = start; } + + if (rl_point < 0) + rl_point = 0; + return 0; } @@ -1127,13 +1162,14 @@ rl_delete_or_show_completions (count, key) /* Turn the current line into a comment in shell history. A K*rn shell style function. */ int -rl_insert_comment (int count __attribute__((unused)), int key) +rl_insert_comment (count, key) + int count, key; { char *rl_comment_text; int rl_comment_len; rl_beg_of_line (1, key); - rl_comment_text = _rl_comment_begin ? _rl_comment_begin : (char*) RL_COMMENT_BEGIN_DEFAULT; + rl_comment_text = _rl_comment_begin ? _rl_comment_begin : RL_COMMENT_BEGIN_DEFAULT; if (rl_explicit_arg == 0) rl_insert_text (rl_comment_text); @@ -1165,21 +1201,24 @@ rl_insert_comment (int count __attribute__((unused)), int key) /* Uppercase the word at point. */ int -rl_upcase_word (int count, int key __attribute__((unused))) +rl_upcase_word (count, key) + int count, key; { return (rl_change_case (count, UpCase)); } /* Lowercase the word at point. */ int -rl_downcase_word (int count, int key __attribute__((unused))) +rl_downcase_word (count, key) + int count, key; { return (rl_change_case (count, DownCase)); } /* Upcase the first letter, downcase the rest. */ int -rl_capitalize_word (int count, int key __attribute__((unused))) +rl_capitalize_word (count, key) + int count, key; { return (rl_change_case (count, CapCase)); } @@ -1193,42 +1232,80 @@ static int rl_change_case (count, op) int count, op; { - register int start, end; - int inword, c; + int start, next, end; + int inword, c, nc, nop; +#if defined (HANDLE_MULTIBYTE) + wchar_t wc, nwc; + char mb[MB_LEN_MAX+1]; + int mlen; + mbstate_t mps; +#endif start = rl_point; rl_forward_word (count, 0); end = rl_point; + if (op != UpCase && op != DownCase && op != CapCase) + { + rl_ding (); + return -1; + } + if (count < 0) SWAP (start, end); +#if defined (HANDLE_MULTIBYTE) + memset (&mps, 0, sizeof (mbstate_t)); +#endif + /* We are going to modify some text, so let's prepare to undo it. */ rl_modifying (start, end); - for (inword = 0; start < end; start++) + inword = 0; + while (start < end) { - c = rl_line_buffer[start]; - switch (op) + c = _rl_char_value (rl_line_buffer, start); + /* This assumes that the upper and lower case versions are the same width. */ + next = MB_NEXTCHAR (rl_line_buffer, start, 1, MB_FIND_NONZERO); + + if (_rl_walphabetic (c) == 0) { - case UpCase: - rl_line_buffer[start] = _rl_to_upper (c); - break; - - case DownCase: - rl_line_buffer[start] = _rl_to_lower (c); - break; - - case CapCase: - rl_line_buffer[start] = (inword == 0) ? _rl_to_upper (c) : _rl_to_lower (c); - inword = rl_alphabetic (rl_line_buffer[start]); - break; - - default: - rl_ding (); - return -1; + inword = 0; + start = next; + continue; } + + if (op == CapCase) + { + nop = inword ? DownCase : UpCase; + inword = 1; + } + else + nop = op; + if (MB_CUR_MAX == 1 || rl_byte_oriented || isascii (c)) + { + nc = (nop == UpCase) ? _rl_to_upper (c) : _rl_to_lower (c); + rl_line_buffer[start] = nc; + } +#if defined (HANDLE_MULTIBYTE) + else + { + mbrtowc (&wc, rl_line_buffer + start, end - start, &mps); + nwc = (nop == UpCase) ? _rl_to_wupper (wc) : _rl_to_wlower (wc); + if (nwc != wc) /* just skip unchanged characters */ + { + mlen = wcrtomb (mb, nwc, &mps); + if (mlen > 0) + mb[mlen] = '\0'; + /* Assume the same width */ + strncpy (rl_line_buffer + start, mb, mlen); + } + } +#endif + + start = next; } + rl_point = end; return 0; } @@ -1303,15 +1380,16 @@ rl_transpose_words (count, key) /* Transpose the characters at point. If point is at the end of the line, then transpose the characters before point. */ int -rl_transpose_chars (int count, int key __attribute__((unused))) +rl_transpose_chars (count, key) + int count, key; { #if defined (HANDLE_MULTIBYTE) char *dummy; - int i, prev_point; + int i; #else char dummy[2]; #endif - int char_length; + int char_length, prev_point; if (count == 0) return 0; @@ -1326,20 +1404,12 @@ rl_transpose_chars (int count, int key __attribute__((unused))) if (rl_point == rl_end) { - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO); - else - --rl_point; + rl_point = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_NONZERO); count = 1; } -#if defined (HANDLE_MULTIBYTE) prev_point = rl_point; - if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO); - else -#endif - rl_point--; + rl_point = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_NONZERO); #if defined (HANDLE_MULTIBYTE) char_length = prev_point - rl_point; @@ -1473,15 +1543,51 @@ _rl_char_search (count, fdir, bdir) } #endif /* !HANDLE_MULTIBYTE */ -int -rl_char_search (int count, int key __attribute__((unused))) +#if defined (READLINE_CALLBACKS) +static int +_rl_char_search_callback (data) + _rl_callback_generic_arg *data; { + _rl_callback_func = 0; + _rl_want_redisplay = 1; + + return (_rl_char_search (data->count, data->i1, data->i2)); +} +#endif + +int +rl_char_search (count, key) + int count, key; +{ +#if defined (READLINE_CALLBACKS) + if (RL_ISSTATE (RL_STATE_CALLBACK)) + { + _rl_callback_data = _rl_callback_data_alloc (count); + _rl_callback_data->i1 = FFIND; + _rl_callback_data->i2 = BFIND; + _rl_callback_func = _rl_char_search_callback; + return (0); + } +#endif + return (_rl_char_search (count, FFIND, BFIND)); } int -rl_backward_char_search (int count, int key __attribute__((unused))) +rl_backward_char_search (count, key) + int count, key; { +#if defined (READLINE_CALLBACKS) + if (RL_ISSTATE (RL_STATE_CALLBACK)) + { + _rl_callback_data = _rl_callback_data_alloc (count); + _rl_callback_data->i1 = BFIND; + _rl_callback_data->i2 = FFIND; + _rl_callback_func = _rl_char_search_callback; + return (0); + } +#endif + return (_rl_char_search (count, BFIND, FFIND)); } @@ -1505,15 +1611,16 @@ _rl_set_mark_at_pos (position) /* A bindable command to set the mark. */ int -rl_set_mark (int count, int key __attribute__((unused))) +rl_set_mark (count, key) + int count, key; { return (_rl_set_mark_at_pos (rl_explicit_arg ? count : rl_point)); } /* Exchange the position of mark and point. */ int -rl_exchange_point_and_mark (int count __attribute__((unused)), - int key __attribute__((unused))) +rl_exchange_point_and_mark (count, key) + int count, key; { if (rl_mark > rl_end) rl_mark = -1; diff --git a/cmd-line-utils/readline/tilde.c b/cmd-line-utils/readline/tilde.c index 91eead0d9e2..1b76c9f2404 100644 --- a/cmd-line-utils/readline/tilde.c +++ b/cmd-line-utils/readline/tilde.c @@ -19,9 +19,9 @@ along with Readline; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ -#define READLINE_LIBRARY - -#include "config_readline.h" +#if defined (HAVE_CONFIG_H) +# include +#endif #if defined (HAVE_UNISTD_H) # ifdef _MINIX @@ -43,7 +43,9 @@ #endif /* HAVE_STDLIB_H */ #include +#if defined (HAVE_PWD_H) #include +#endif #include "tilde.h" @@ -54,8 +56,12 @@ static void *xmalloc (), *xrealloc (); #endif /* TEST || STATIC_MALLOC */ #if !defined (HAVE_GETPW_DECLS) +# if defined (HAVE_GETPWUID) extern struct passwd *getpwuid PARAMS((uid_t)); +# endif +# if defined (HAVE_GETPWNAM) extern struct passwd *getpwnam PARAMS((const char *)); +# endif #endif /* !HAVE_GETPW_DECLS */ #if !defined (savestring) @@ -190,7 +196,7 @@ tilde_expand (string) int result_size, result_index; result_index = result_size = 0; - if ((result = strchr (string, '~'))) + if (result = strchr (string, '~')) result = (char *)xmalloc (result_size = (strlen (string) + 16)); else result = (char *)xmalloc (result_size = (strlen (string) + 1)); @@ -277,6 +283,39 @@ isolate_tilde_prefix (fname, lenp) return ret; } +#if 0 +/* Public function to scan a string (FNAME) beginning with a tilde and find + the portion of the string that should be passed to the tilde expansion + function. Right now, it just calls tilde_find_suffix and allocates new + memory, but it can be expanded to do different things later. */ +char * +tilde_find_word (fname, flags, lenp) + const char *fname; + int flags, *lenp; +{ + int x; + char *r; + + x = tilde_find_suffix (fname); + if (x == 0) + { + r = savestring (fname); + if (lenp) + *lenp = 0; + } + else + { + r = (char *)xmalloc (1 + x); + strncpy (r, fname, x); + r[x] = '\0'; + if (lenp) + *lenp = x; + } + + return r; +} +#endif + /* Return a string that is PREFIX concatenated with SUFFIX starting at SUFFIND. */ static char * @@ -347,7 +386,11 @@ tilde_expand_word (filename) /* No preexpansion hook, or the preexpansion hook failed. Look in the password database. */ dirname = (char *)NULL; +#if defined (HAVE_GETPWNAM) user_entry = getpwnam (username); +#else + user_entry = 0; +#endif if (user_entry == 0) { /* If the calling program has a special syntax for expanding tildes, @@ -361,19 +404,20 @@ tilde_expand_word (filename) free (expansion); } } - free (username); /* If we don't have a failure hook, or if the failure hook did not expand the tilde, return a copy of what we were passed. */ if (dirname == 0) dirname = savestring (filename); } +#if defined (HAVE_GETPWENT) else - { - free (username); - dirname = glue_prefix_and_suffix (user_entry->pw_dir, filename, user_len); - } + dirname = glue_prefix_and_suffix (user_entry->pw_dir, filename, user_len); +#endif + free (username); +#if defined (HAVE_GETPWENT) endpwent (); +#endif return (dirname); } diff --git a/cmd-line-utils/readline/tilde.h b/cmd-line-utils/readline/tilde.h index f8182c999d9..c58ce20e7a2 100644 --- a/cmd-line-utils/readline/tilde.h +++ b/cmd-line-utils/readline/tilde.h @@ -71,6 +71,9 @@ extern char *tilde_expand PARAMS((const char *)); tilde. If there is no expansion, call tilde_expansion_failure_hook. */ extern char *tilde_expand_word PARAMS((const char *)); +/* Find the portion of the string beginning with ~ that should be expanded. */ +extern char *tilde_find_word PARAMS((const char *, int, int *)); + #ifdef __cplusplus } #endif diff --git a/cmd-line-utils/readline/undo.c b/cmd-line-utils/readline/undo.c index 4d256f492b8..9d9bd25ba8f 100644 --- a/cmd-line-utils/readline/undo.c +++ b/cmd-line-utils/readline/undo.c @@ -1,7 +1,7 @@ /* readline.c -- a general facility for reading lines of input with emacs style editing and completion. */ -/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc. +/* Copyright (C) 1987, 1989, 1992, 2006 Free Software Foundation, Inc. This file is part of the GNU Readline Library, a library for reading lines of text with interactive input and history editing. @@ -22,7 +22,9 @@ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #define READLINE_LIBRARY -#include "config_readline.h" +#if defined (HAVE_CONFIG_H) +# include +#endif #include @@ -48,6 +50,8 @@ #include "rlprivate.h" #include "xmalloc.h" +extern void replace_history_data PARAMS((int, histdata_t *, histdata_t *)); + /* Non-zero tells rl_delete_text and rl_insert_text to not add to the undo list. */ int _rl_doing_an_undo = 0; @@ -64,6 +68,24 @@ UNDO_LIST *rl_undo_list = (UNDO_LIST *)NULL; /* */ /* **************************************************************** */ +static UNDO_LIST * +alloc_undo_entry (what, start, end, text) + enum undo_code what; + int start, end; + char *text; +{ + UNDO_LIST *temp; + + temp = (UNDO_LIST *)xmalloc (sizeof (UNDO_LIST)); + temp->what = what; + temp->start = start; + temp->end = end; + temp->text = text; + + temp->next = (UNDO_LIST *)NULL; + return temp; +} + /* Remember how to undo something. Concatenate some undos if that seems right. */ void @@ -72,11 +94,9 @@ rl_add_undo (what, start, end, text) int start, end; char *text; { - UNDO_LIST *temp = (UNDO_LIST *)xmalloc (sizeof (UNDO_LIST)); - temp->what = what; - temp->start = start; - temp->end = end; - temp->text = text; + UNDO_LIST *temp; + + temp = alloc_undo_entry (what, start, end, text); temp->next = rl_undo_list; rl_undo_list = temp; } @@ -85,9 +105,12 @@ rl_add_undo (what, start, end, text) void rl_free_undo_list () { + UNDO_LIST *release, *orig_list; + + orig_list = rl_undo_list; while (rl_undo_list) { - UNDO_LIST *release = rl_undo_list; + release = rl_undo_list; rl_undo_list = rl_undo_list->next; if (release->what == UNDO_DELETE) @@ -96,6 +119,43 @@ rl_free_undo_list () free (release); } rl_undo_list = (UNDO_LIST *)NULL; + replace_history_data (-1, (histdata_t *)orig_list, (histdata_t *)NULL); +} + +UNDO_LIST * +_rl_copy_undo_entry (entry) + UNDO_LIST *entry; +{ + UNDO_LIST *new; + + new = alloc_undo_entry (entry->what, entry->start, entry->end, (char *)NULL); + new->text = entry->text ? savestring (entry->text) : 0; + return new; +} + +UNDO_LIST * +_rl_copy_undo_list (head) + UNDO_LIST *head; +{ + UNDO_LIST *list, *new, *roving, *c; + + list = head; + new = 0; + while (list) + { + c = _rl_copy_undo_entry (list); + if (new == 0) + roving = new = c; + else + { + roving->next = c; + roving = roving->next; + } + list = list->next; + } + + roving->next = 0; + return new; } /* Undo the next thing in the list. Return 0 if there @@ -159,6 +219,8 @@ rl_do_undo () release = rl_undo_list; rl_undo_list = rl_undo_list->next; + replace_history_data (-1, (histdata_t *)release, (histdata_t *)rl_undo_list); + free (release); } while (waiting_for_begin); @@ -175,7 +237,7 @@ _rl_fix_last_undo_of_type (type, start, end) for (rl = rl_undo_list; rl; rl = rl->next) { - if (rl->what == (unsigned int) type) + if (rl->what == type) { rl->start = start; rl->end = end; @@ -226,7 +288,8 @@ rl_modifying (start, end) /* Revert the current line to its previous state. */ int -rl_revert_line (int count __attribute__((unused)), int key __attribute__((unused))) +rl_revert_line (count, key) + int count, key; { if (!rl_undo_list) rl_ding (); @@ -234,13 +297,19 @@ rl_revert_line (int count __attribute__((unused)), int key __attribute__((unuse { while (rl_undo_list) rl_do_undo (); +#if defined (VI_MODE) + if (rl_editing_mode == vi_mode) + rl_point = rl_mark = 0; /* rl_end should be set correctly */ +#endif } + return 0; } /* Do some undoing of things that were done. */ int -rl_undo_command (int count, int key __attribute__((unused))) +rl_undo_command (count, key) + int count, key; { if (count < 0) return 0; /* Nothing to do. */ diff --git a/cmd-line-utils/readline/util.c b/cmd-line-utils/readline/util.c index d5fe51a7bf2..e44ef64349d 100644 --- a/cmd-line-utils/readline/util.c +++ b/cmd-line-utils/readline/util.c @@ -1,6 +1,6 @@ /* util.c -- readline utility functions */ -/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc. +/* Copyright (C) 1987-2005 Free Software Foundation, Inc. This file is part of the GNU Readline Library, a library for reading lines of text with interactive input and history editing. @@ -21,7 +21,9 @@ 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #define READLINE_LIBRARY -#include "config_readline.h" +#if defined (HAVE_CONFIG_H) +# include +#endif #include #include @@ -42,6 +44,7 @@ /* System-specific feature definitions and include files. */ #include "rldefs.h" +#include "rlmbutil.h" #if defined (TIOCSTAT_IN_SYS_IOCTL) # include @@ -76,13 +79,29 @@ rl_alphabetic (c) strchr (pathname_alphabetic_chars, c) != NULL); } +#if defined (HANDLE_MULTIBYTE) +int +_rl_walphabetic (wc) + wchar_t wc; +{ + int c; + + if (iswalnum (wc)) + return (1); + + c = wc & 0177; + return (_rl_allow_pathname_alphabetic_chars && + strchr (pathname_alphabetic_chars, c) != NULL); +} +#endif + /* How to abort things. */ int _rl_abort_internal () { rl_ding (); rl_clear_message (); - _rl_init_argument (); + _rl_reset_argument (); rl_clear_pending_input (); RL_UNSETSTATE (RL_STATE_MACRODEF); @@ -95,13 +114,15 @@ _rl_abort_internal () } int -rl_abort (int count __attribute__((unused)), int key __attribute__((unused))) +rl_abort (count, key) + int count, key; { return (_rl_abort_internal ()); } int -rl_tty_status (int count __attribute__((unused)), int key __attribute__((unused))) +rl_tty_status (count, key) + int count, key; { #if defined (TIOCSTAT) ioctl (1, TIOCSTAT, (char *)0); @@ -150,7 +171,8 @@ rl_extend_line_buffer (len) /* A function for simple tilde expansion. */ int -rl_tilde_expand (int ignore __attribute__((unused)), int key __attribute__((unused))) +rl_tilde_expand (ignore, key) + int ignore, key; { register int start, end; char *homedir, *temp; diff --git a/cmd-line-utils/readline/vi_keymap.c b/cmd-line-utils/readline/vi_keymap.c index 53a67c674ce..4b48c75cc5d 100644 --- a/cmd-line-utils/readline/vi_keymap.c +++ b/cmd-line-utils/readline/vi_keymap.c @@ -130,7 +130,7 @@ KEYMAP_ENTRY_ARRAY vi_movement_keymap = { { ISFUNC, rl_revert_line }, /* U */ { ISFUNC, (rl_command_func_t *)0x0 }, /* V */ { ISFUNC, rl_vi_next_word }, /* W */ - { ISFUNC, rl_rubout }, /* X */ + { ISFUNC, rl_vi_rubout }, /* X */ { ISFUNC, rl_vi_yank_to }, /* Y */ { ISFUNC, (rl_command_func_t *)0x0 }, /* Z */ diff --git a/cmd-line-utils/readline/vi_mode.c b/cmd-line-utils/readline/vi_mode.c index a277fe2c237..d0b7e330adc 100644 --- a/cmd-line-utils/readline/vi_mode.c +++ b/cmd-line-utils/readline/vi_mode.c @@ -1,7 +1,7 @@ /* vi_mode.c -- A vi emulation mode for Bash. Derived from code written by Jeff Sparkes (jsparkes@bnr.ca). */ -/* Copyright (C) 1987-2004 Free Software Foundation, Inc. +/* Copyright (C) 1987-2005 Free Software Foundation, Inc. This file is part of the GNU Readline Library, a library for reading lines of text with interactive input and history editing. @@ -31,7 +31,9 @@ #if defined (VI_MODE) -#include "config_readline.h" +#if defined (HAVE_CONFIG_H) +# include +#endif #include @@ -88,6 +90,7 @@ static int _rl_vi_last_arg_sign = 1; static int _rl_vi_last_motion; #if defined (HANDLE_MULTIBYTE) static char _rl_vi_last_search_mbchar[MB_LEN_MAX]; +static int _rl_vi_last_search_mblen; #else static int _rl_vi_last_search_char; #endif @@ -105,15 +108,35 @@ static int vi_mark_chars['z' - 'a' + 1]; static void _rl_vi_stuff_insert PARAMS((int)); static void _rl_vi_save_insert PARAMS((UNDO_LIST *)); + +static void _rl_vi_backup PARAMS((void)); + +static int _rl_vi_arg_dispatch PARAMS((int)); static int rl_digit_loop1 PARAMS((void)); +static int _rl_vi_set_mark PARAMS((void)); +static int _rl_vi_goto_mark PARAMS((void)); + +static void _rl_vi_append_forward PARAMS((int)); + +static int _rl_vi_callback_getchar PARAMS((char *, int)); + +#if defined (READLINE_CALLBACKS) +static int _rl_vi_callback_set_mark PARAMS((_rl_callback_generic_arg *)); +static int _rl_vi_callback_goto_mark PARAMS((_rl_callback_generic_arg *)); +static int _rl_vi_callback_change_char PARAMS((_rl_callback_generic_arg *)); +static int _rl_vi_callback_char_search PARAMS((_rl_callback_generic_arg *)); +#endif + void _rl_vi_initialize_line () { register int i; - for (i = 0; i < (int) (sizeof (vi_mark_chars) / sizeof (int)); i++) + for (i = 0; i < sizeof (vi_mark_chars) / sizeof (int); i++) vi_mark_chars[i] = -1; + + RL_UNSETSTATE(RL_STATE_VICMDONCE); } void @@ -166,7 +189,8 @@ _rl_vi_stuff_insert (count) redo a text modification command. The default for _rl_vi_last_command puts you back into insert mode. */ int -rl_vi_redo (int count, int c __attribute__((unused))) +rl_vi_redo (count, c) + int count, c; { int r; @@ -185,7 +209,16 @@ rl_vi_redo (int count, int c __attribute__((unused))) _rl_vi_stuff_insert (count); /* And back up point over the last character inserted. */ if (rl_point > 0) - rl_point--; + _rl_vi_backup (); + } + /* Ditto for redoing an insert with `a', but move forward a character first + like the `a' command does. */ + else if (_rl_vi_last_command == 'a' && vi_insert_buffer && *vi_insert_buffer) + { + _rl_vi_append_forward ('a'); + _rl_vi_stuff_insert (count); + if (rl_point > 0) + _rl_vi_backup (); } else r = _rl_dispatch (_rl_vi_last_command, _rl_keymap); @@ -204,7 +237,8 @@ rl_vi_undo (count, key) /* Yank the nth arg from the previous line into this line at point. */ int -rl_vi_yank_arg (int count, int key __attribute__((unused))) +rl_vi_yank_arg (count, key) + int count, key; { /* Readline thinks that the first word on a line is the 0th, while vi thinks the first word on a line is the 1st. Compensate. */ @@ -268,10 +302,12 @@ rl_vi_search (count, key) switch (key) { case '?': + _rl_free_saved_history_line (); rl_noninc_forward_search (count, key); break; case '/': + _rl_free_saved_history_line (); rl_noninc_reverse_search (count, key); break; @@ -284,7 +320,8 @@ rl_vi_search (count, key) /* Completion, from vi's point of view. */ int -rl_vi_complete (int ignore __attribute__((unused)), int key) +rl_vi_complete (ignore, key) + int ignore, key; { if ((rl_point < rl_end) && (!whitespace (rl_line_buffer[rl_point]))) { @@ -310,7 +347,8 @@ rl_vi_complete (int ignore __attribute__((unused)), int key) /* Tilde expansion for vi mode. */ int -rl_vi_tilde_expand (int ignore __attribute__((unused)), int key) +rl_vi_tilde_expand (ignore, key) + int ignore, key; { rl_tilde_expand (0, key); rl_vi_start_inserting (key, 1, rl_arg_sign); @@ -380,7 +418,8 @@ rl_vi_end_word (count, key) /* Move forward a word the way that 'W' does. */ int -rl_vi_fWord (int count, int ignore __attribute__((unused))) +rl_vi_fWord (count, ignore) + int count, ignore; { while (count-- && rl_point < (rl_end - 1)) { @@ -396,7 +435,8 @@ rl_vi_fWord (int count, int ignore __attribute__((unused))) } int -rl_vi_bWord (int count, int ignore __attribute__((unused))) +rl_vi_bWord (count, ignore) + int count, ignore; { while (count-- && rl_point > 0) { @@ -419,7 +459,8 @@ rl_vi_bWord (int count, int ignore __attribute__((unused))) } int -rl_vi_eWord(int count, int ignore __attribute__((unused))) +rl_vi_eWord (count, ignore) + int count, ignore; { while (count-- && rl_point < (rl_end - 1)) { @@ -449,7 +490,8 @@ rl_vi_eWord(int count, int ignore __attribute__((unused))) } int -rl_vi_fword (int count, int ignore __attribute__((unused))) +rl_vi_fword (count, ignore) + int count, ignore; { while (count-- && rl_point < (rl_end - 1)) { @@ -474,7 +516,8 @@ rl_vi_fword (int count, int ignore __attribute__((unused))) } int -rl_vi_bword (int count, int ignore __attribute__((unused))) +rl_vi_bword (count, ignore) + int count, ignore; { while (count-- && rl_point > 0) { @@ -512,7 +555,8 @@ rl_vi_bword (int count, int ignore __attribute__((unused))) } int -rl_vi_eword (int count, int ignore __attribute__((unused))) +rl_vi_eword (count, ignore) + int count, ignore; { while (count-- && rl_point < rl_end - 1) { @@ -536,34 +580,46 @@ rl_vi_eword (int count, int ignore __attribute__((unused))) } int -rl_vi_insert_beg (int count __attribute__((unused)), int key) +rl_vi_insert_beg (count, key) + int count, key; { rl_beg_of_line (1, key); rl_vi_insertion_mode (1, key); return (0); } -int -rl_vi_append_mode (int count __attribute__((unused)), int key) +static void +_rl_vi_append_forward (key) + int key; { + int point; + if (rl_point < rl_end) { if (MB_CUR_MAX == 1 || rl_byte_oriented) rl_point++; else { - int point = rl_point; + point = rl_point; rl_forward_char (1, key); if (point == rl_point) rl_point = rl_end; } } - rl_vi_insertion_mode (1, key); +} + +int +rl_vi_append_mode (count, key) + int count, key; +{ + _rl_vi_append_forward (key); + rl_vi_start_inserting (key, 1, rl_arg_sign); return (0); } int -rl_vi_append_eol (int count __attribute__((unused)), int key) +rl_vi_append_eol (count, key) + int count, key; { rl_end_of_line (1, key); rl_vi_append_mode (1, key); @@ -572,7 +628,8 @@ rl_vi_append_eol (int count __attribute__((unused)), int key) /* What to do in the case of C-d. */ int -rl_vi_eof_maybe (int count __attribute__((unused)), int c __attribute__((unused))) +rl_vi_eof_maybe (count, c) + int count, c; { return (rl_newline (1, '\n')); } @@ -582,7 +639,8 @@ rl_vi_eof_maybe (int count __attribute__((unused)), int c __attribute__((unused) /* Switching from one mode to the other really just involves switching keymaps. */ int -rl_vi_insertion_mode (int count __attribute__((unused)), int key) +rl_vi_insertion_mode (count, key) + int count, key; { _rl_keymap = vi_insertion_keymap; _rl_vi_last_key_before_insert = key; @@ -595,7 +653,7 @@ _rl_vi_save_insert (up) { int len, start, end; - if (up == 0) + if (up == 0 || up->what != UNDO_INSERT) { if (vi_insert_buffer_size >= 1) vi_insert_buffer[0] = '\0'; @@ -644,13 +702,21 @@ _rl_vi_done_inserting () } int -rl_vi_movement_mode (int count __attribute__((unused)), int key) +rl_vi_movement_mode (count, key) + int count, key; { if (rl_point > 0) rl_backward_char (1, key); _rl_keymap = vi_movement_keymap; _rl_vi_done_inserting (); + + /* This is how POSIX.2 says `U' should behave -- everything up until the + first time you go into command mode should not be undone. */ + if (RL_ISSTATE (RL_STATE_VICMDONCE) == 0) + rl_free_undo_list (); + + RL_SETSTATE (RL_STATE_VICMDONCE); return (0); } @@ -672,7 +738,7 @@ _rl_vi_change_mbchar_case (count) { wchar_t wc; char mb[MB_LEN_MAX+1]; - int local_mblen; + int mlen, p; mbstate_t ps; memset (&ps, 0, sizeof (mbstate_t)); @@ -695,11 +761,14 @@ _rl_vi_change_mbchar_case (count) /* Vi is kind of strange here. */ if (wc) { - local_mblen = wcrtomb (mb, wc, &ps); - if (local_mblen >= 0) - mb[local_mblen] = '\0'; + p = rl_point; + mlen = wcrtomb (mb, wc, &ps); + if (mlen >= 0) + mb[mlen] = '\0'; rl_begin_undo_group (); - rl_delete (1, 0); + rl_vi_delete (1, 0); + if (rl_point < p) /* Did we retreat at EOL? */ + rl_point++; /* XXX - should we advance more than 1 for mbchar? */ rl_insert_text (mb); rl_end_undo_group (); rl_vi_check (); @@ -713,7 +782,8 @@ _rl_vi_change_mbchar_case (count) #endif int -rl_vi_change_case (int count, int ignore __attribute__((unused))) +rl_vi_change_case (count, ignore) + int count, ignore; { int c, p; @@ -772,6 +842,15 @@ rl_vi_put (count, key) return (0); } +static void +_rl_vi_backup () +{ + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO); + else + rl_point--; +} + int rl_vi_check () { @@ -816,7 +895,9 @@ rl_vi_domove (key, nextkey) save = rl_numeric_arg; rl_numeric_arg = _rl_digit_value (c); rl_explicit_arg = 1; + RL_SETSTATE (RL_STATE_NUMERICARG|RL_STATE_VIMOTION); rl_digit_loop1 (); + RL_UNSETSTATE (RL_STATE_VIMOTION); rl_numeric_arg *= save; RL_SETSTATE(RL_STATE_MOREINPUT); c = rl_read_key (); /* real command */ @@ -889,52 +970,59 @@ rl_vi_domove (key, nextkey) return (0); } +/* Process C as part of the current numeric argument. Return -1 if the + argument should be aborted, 0 if we should not read any more chars, and + 1 if we should continue to read chars. */ +static int +_rl_vi_arg_dispatch (c) + int c; +{ + int key; + + key = c; + if (c >= 0 && _rl_keymap[c].type == ISFUNC && _rl_keymap[c].function == rl_universal_argument) + { + rl_numeric_arg *= 4; + return 1; + } + + c = UNMETA (c); + + if (_rl_digit_p (c)) + { + if (rl_explicit_arg) + rl_numeric_arg = (rl_numeric_arg * 10) + _rl_digit_value (c); + else + rl_numeric_arg = _rl_digit_value (c); + rl_explicit_arg = 1; + return 1; + } + else + { + rl_clear_message (); + rl_stuff_char (key); + return 0; + } +} + /* A simplified loop for vi. Don't dispatch key at end. Don't recognize minus sign? Should this do rl_save_prompt/rl_restore_prompt? */ static int rl_digit_loop1 () { - int key, c; + int c, r; - RL_SETSTATE(RL_STATE_NUMERICARG); while (1) { - if (rl_numeric_arg > 1000000) - { - rl_explicit_arg = rl_numeric_arg = 0; - rl_ding (); - rl_clear_message (); - RL_UNSETSTATE(RL_STATE_NUMERICARG); - return 1; - } - rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg); - RL_SETSTATE(RL_STATE_MOREINPUT); - key = c = rl_read_key (); - RL_UNSETSTATE(RL_STATE_MOREINPUT); + if (_rl_arg_overflow ()) + return 1; - if (c >= 0 && _rl_keymap[c].type == ISFUNC && - _rl_keymap[c].function == rl_universal_argument) - { - rl_numeric_arg *= 4; - continue; - } + c = _rl_arg_getchar (); - c = UNMETA (c); - if (_rl_digit_p (c)) - { - if (rl_explicit_arg) - rl_numeric_arg = (rl_numeric_arg * 10) + _rl_digit_value (c); - else - rl_numeric_arg = _rl_digit_value (c); - rl_explicit_arg = 1; - } - else - { - rl_clear_message (); - rl_stuff_char (key); - break; - } + r = _rl_vi_arg_dispatch (c); + if (r <= 0) + break; } RL_UNSETSTATE(RL_STATE_NUMERICARG); @@ -942,7 +1030,8 @@ rl_digit_loop1 () } int -rl_vi_delete_to (int count __attribute__((unused)), int key) +rl_vi_delete_to (count, key) + int count, key; { int c; @@ -967,7 +1056,8 @@ rl_vi_delete_to (int count __attribute__((unused)), int key) } int -rl_vi_change_to (int count __attribute__((unused)), int key) +rl_vi_change_to (count, key) + int count, key; { int c, start_pos; @@ -1019,10 +1109,12 @@ rl_vi_change_to (int count __attribute__((unused)), int key) } int -rl_vi_yank_to (int count __attribute__((unused)), int key) +rl_vi_yank_to (count, key) + int count, key; { - int c, save = rl_point; + int c, save; + save = rl_point; if (_rl_uppercase_p (key)) rl_stuff_char ('$'); @@ -1046,12 +1138,46 @@ rl_vi_yank_to (int count __attribute__((unused)), int key) return (0); } +int +rl_vi_rubout (count, key) + int count, key; +{ + int opoint; + + if (count < 0) + return (rl_vi_delete (-count, key)); + + if (rl_point == 0) + { + rl_ding (); + return -1; + } + + opoint = rl_point; + if (count > 1 && MB_CUR_MAX > 1 && rl_byte_oriented == 0) + rl_backward_char (count, key); + else if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO); + else + rl_point -= count; + + if (rl_point < 0) + rl_point = 0; + + rl_kill_text (rl_point, opoint); + + return (0); +} + int rl_vi_delete (count, key) int count, key; { int end; + if (count < 0) + return (rl_vi_rubout (-count, key)); + if (rl_end == 0) { rl_ding (); @@ -1070,11 +1196,13 @@ rl_vi_delete (count, key) if (rl_point > 0 && rl_point == rl_end) rl_backward_char (1, key); + return (0); } int -rl_vi_back_to_indent (int count __attribute__((unused)), int key) +rl_vi_back_to_indent (count, key) + int count, key; { rl_beg_of_line (1, key); while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point])) @@ -1083,75 +1211,115 @@ rl_vi_back_to_indent (int count __attribute__((unused)), int key) } int -rl_vi_first_print (int count __attribute__((unused)), int key) +rl_vi_first_print (count, key) + int count, key; { return (rl_vi_back_to_indent (1, key)); } +static int _rl_cs_dir, _rl_cs_orig_dir; + +#if defined (READLINE_CALLBACKS) +static int +_rl_vi_callback_char_search (data) + _rl_callback_generic_arg *data; +{ +#if defined (HANDLE_MULTIBYTE) + _rl_vi_last_search_mblen = _rl_read_mbchar (_rl_vi_last_search_mbchar, MB_LEN_MAX); +#else + RL_SETSTATE(RL_STATE_MOREINPUT); + _rl_vi_last_search_char = rl_read_key (); + RL_UNSETSTATE(RL_STATE_MOREINPUT); +#endif + + _rl_callback_func = 0; + _rl_want_redisplay = 1; + +#if defined (HANDLE_MULTIBYTE) + return (_rl_char_search_internal (data->count, _rl_cs_dir, _rl_vi_last_search_mbchar, _rl_vi_last_search_mblen)); +#else + return (_rl_char_search_internal (data->count, _rl_cs_dir, _rl_vi_last_search_char)); +#endif +} +#endif + int rl_vi_char_search (count, key) int count, key; { #if defined (HANDLE_MULTIBYTE) static char *target; - static int mb_len; + static int tlen; #else static char target; #endif - static int orig_dir, dir; if (key == ';' || key == ',') - dir = key == ';' ? orig_dir : -orig_dir; + _rl_cs_dir = (key == ';') ? _rl_cs_orig_dir : -_rl_cs_orig_dir; else { + switch (key) + { + case 't': + _rl_cs_orig_dir = _rl_cs_dir = FTO; + break; + + case 'T': + _rl_cs_orig_dir = _rl_cs_dir = BTO; + break; + + case 'f': + _rl_cs_orig_dir = _rl_cs_dir = FFIND; + break; + + case 'F': + _rl_cs_orig_dir = _rl_cs_dir = BFIND; + break; + } + if (vi_redoing) -#if defined (HANDLE_MULTIBYTE) - target = _rl_vi_last_search_mbchar; -#else - target = _rl_vi_last_search_char; + { + /* set target and tlen below */ + } +#if defined (READLINE_CALLBACKS) + else if (RL_ISSTATE (RL_STATE_CALLBACK)) + { + _rl_callback_data = _rl_callback_data_alloc (count); + _rl_callback_data->i1 = _rl_cs_dir; + _rl_callback_func = _rl_vi_callback_char_search; + return (0); + } #endif else { #if defined (HANDLE_MULTIBYTE) - mb_len = _rl_read_mbchar (_rl_vi_last_search_mbchar, MB_LEN_MAX); - target = _rl_vi_last_search_mbchar; + _rl_vi_last_search_mblen = _rl_read_mbchar (_rl_vi_last_search_mbchar, MB_LEN_MAX); #else RL_SETSTATE(RL_STATE_MOREINPUT); - _rl_vi_last_search_char = target = rl_read_key (); + _rl_vi_last_search_char = rl_read_key (); RL_UNSETSTATE(RL_STATE_MOREINPUT); #endif } - - switch (key) - { - case 't': - orig_dir = dir = FTO; - break; - - case 'T': - orig_dir = dir = BTO; - break; - - case 'f': - orig_dir = dir = FFIND; - break; - - case 'F': - orig_dir = dir = BFIND; - break; - } } #if defined (HANDLE_MULTIBYTE) - return (_rl_char_search_internal (count, dir, target, mb_len)); + target = _rl_vi_last_search_mbchar; + tlen = _rl_vi_last_search_mblen; #else - return (_rl_char_search_internal (count, dir, target)); + target = _rl_vi_last_search_char; +#endif + +#if defined (HANDLE_MULTIBYTE) + return (_rl_char_search_internal (count, _rl_cs_dir, target, tlen)); +#else + return (_rl_char_search_internal (count, _rl_cs_dir, target)); #endif } /* Match brackets */ int -rl_vi_match (int ignore __attribute__((unused)), int key) +rl_vi_match (ignore, key) + int ignore, key; { int count = 1, brack, pos, tmp, pre; @@ -1255,24 +1423,12 @@ rl_vi_bracktype (c) } } -/* XXX - think about reading an entire mbchar with _rl_read_mbchar and - inserting it in one bunch instead of the loop below (like in - rl_vi_char_search or _rl_vi_change_mbchar_case). Set c to mbchar[0] - for test against 033 or ^C. Make sure that _rl_read_mbchar does - this right. */ -int -rl_vi_change_char (int count, int key __attribute__((unused))) +static int +_rl_vi_change_char (count, c, mb) + int count, c; + char *mb; { - int c, p; - - if (vi_redoing) - c = _rl_vi_last_replacement; - else - { - RL_SETSTATE(RL_STATE_MOREINPUT); - _rl_vi_last_replacement = c = rl_read_key (); - RL_UNSETSTATE(RL_STATE_MOREINPUT); - } + int p; if (c == '\033' || c == CTRL ('C')) return -1; @@ -1282,27 +1438,87 @@ rl_vi_change_char (int count, int key __attribute__((unused))) { p = rl_point; rl_vi_delete (1, c); + if (rl_point < p) /* Did we retreat at EOL? */ + rl_point++; #if defined (HANDLE_MULTIBYTE) if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) - while (_rl_insert_char (1, c)) - { - RL_SETSTATE (RL_STATE_MOREINPUT); - c = rl_read_key (); - RL_UNSETSTATE (RL_STATE_MOREINPUT); - } + rl_insert_text (mb); else #endif - { - if (rl_point < p) /* Did we retreat at EOL? */ - rl_point++; - _rl_insert_char (1, c); - } + _rl_insert_char (1, c); } + + /* The cursor shall be left on the last character changed. */ + rl_backward_char (1, c); + rl_end_undo_group (); return (0); } +static int +_rl_vi_callback_getchar (mb, mlen) + char *mb; + int mlen; +{ + int c; + + RL_SETSTATE(RL_STATE_MOREINPUT); + c = rl_read_key (); + RL_UNSETSTATE(RL_STATE_MOREINPUT); + +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + c = _rl_read_mbstring (c, mb, mlen); +#endif + + return c; +} + +#if defined (READLINE_CALLBACKS) +static int +_rl_vi_callback_change_char (data) + _rl_callback_generic_arg *data; +{ + int c; + char mb[MB_LEN_MAX]; + + _rl_vi_last_replacement = c = _rl_vi_callback_getchar (mb, MB_LEN_MAX); + + _rl_callback_func = 0; + _rl_want_redisplay = 1; + + return (_rl_vi_change_char (data->count, c, mb)); +} +#endif + +int +rl_vi_change_char (count, key) + int count, key; +{ + int c; + char mb[MB_LEN_MAX]; + + if (vi_redoing) + { + c = _rl_vi_last_replacement; + mb[0] = c; + mb[1] = '\0'; + } +#if defined (READLINE_CALLBACKS) + else if (RL_ISSTATE (RL_STATE_CALLBACK)) + { + _rl_callback_data = _rl_callback_data_alloc (count); + _rl_callback_func = _rl_vi_callback_change_char; + return (0); + } +#endif + else + _rl_vi_last_replacement = c = _rl_vi_callback_getchar (mb, MB_LEN_MAX); + + return (_rl_vi_change_char (count, c, mb)); +} + int rl_vi_subst (count, key) int count, key; @@ -1365,7 +1581,8 @@ rl_vi_overstrike_delete (count, key) } int -rl_vi_replace (int count __attribute__((unused)), int key __attribute__((unused))) +rl_vi_replace (count, key) + int count, key; { int i; @@ -1424,8 +1641,8 @@ rl_vi_possible_completions() #endif /* Functions to save and restore marks. */ -int -rl_vi_set_mark (int count __attribute__((unused)), int key __attribute__((unused))) +static int +_rl_vi_set_mark () { int ch; @@ -1443,8 +1660,36 @@ rl_vi_set_mark (int count __attribute__((unused)), int key __attribute__((unused return 0; } +#if defined (READLINE_CALLBACKS) +static int +_rl_vi_callback_set_mark (data) + _rl_callback_generic_arg *data; +{ + _rl_callback_func = 0; + _rl_want_redisplay = 1; + + return (_rl_vi_set_mark ()); +} +#endif + int -rl_vi_goto_mark (int count __attribute__((unused)), int key __attribute__((unused))) +rl_vi_set_mark (count, key) + int count, key; +{ +#if defined (READLINE_CALLBACKS) + if (RL_ISSTATE (RL_STATE_CALLBACK)) + { + _rl_callback_data = 0; + _rl_callback_func = _rl_vi_callback_set_mark; + return (0); + } +#endif + + return (_rl_vi_set_mark ()); +} + +static int +_rl_vi_goto_mark () { int ch; @@ -1473,4 +1718,31 @@ rl_vi_goto_mark (int count __attribute__((unused)), int key __attribute__((unuse return 0; } +#if defined (READLINE_CALLBACKS) +static int +_rl_vi_callback_goto_mark (data) + _rl_callback_generic_arg *data; +{ + _rl_callback_func = 0; + _rl_want_redisplay = 1; + + return (_rl_vi_goto_mark ()); +} +#endif + +int +rl_vi_goto_mark (count, key) + int count, key; +{ +#if defined (READLINE_CALLBACKS) + if (RL_ISSTATE (RL_STATE_CALLBACK)) + { + _rl_callback_data = 0; + _rl_callback_func = _rl_vi_callback_goto_mark; + return (0); + } +#endif + + return (_rl_vi_goto_mark ()); +} #endif /* VI_MODE */ diff --git a/cmd-line-utils/readline/xmalloc.c b/cmd-line-utils/readline/xmalloc.c index 497936d3b43..8985d340d39 100644 --- a/cmd-line-utils/readline/xmalloc.c +++ b/cmd-line-utils/readline/xmalloc.c @@ -20,7 +20,9 @@ Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ #define READLINE_LIBRARY -#include "config_readline.h" +#if defined (HAVE_CONFIG_H) +#include +#endif #include @@ -39,7 +41,8 @@ /* **************************************************************** */ static void -memory_error_and_abort(const char *fname) +memory_error_and_abort (fname) + char *fname; { fprintf (stderr, "%s: out of virtual memory\n", fname); exit (2); @@ -56,7 +59,7 @@ xmalloc (bytes) temp = malloc (bytes); if (temp == 0) - memory_error_and_abort("xmalloc"); + memory_error_and_abort ("xmalloc"); return (temp); } @@ -70,7 +73,7 @@ xrealloc (pointer, bytes) temp = pointer ? realloc (pointer, bytes) : malloc (bytes); if (temp == 0) - memory_error_and_abort("xrealloc"); + memory_error_and_abort ("xrealloc"); return (temp); } diff --git a/config/ac-macros/plugins.m4 b/config/ac-macros/plugins.m4 index 48754563992..8dfb698709f 100644 --- a/config/ac-macros/plugins.m4 +++ b/config/ac-macros/plugins.m4 @@ -360,6 +360,17 @@ AC_DEFUN([__MYSQL_EMIT_CHECK_PLUGIN],[ AC_MSG_ERROR([cannot disable mandatory plugin]) fi [mysql_plugin_]$2=yes + ],[ + case "$with_mysqld_ldflags " in + *"-all-static "*) + # No need to build shared plugins when mysqld is linked with + # -all-static as it won't be able to load them. + if test "X[$mysql_plugin_]$2" != Xyes -a \ + "X[$with_plugin_]$2" != Xyes; then + [with_plugin_]$2=no + fi + ;; + esac ]) if test "X[$with_plugin_]$2" = Xno; then AC_MSG_RESULT([no]) diff --git a/configure.in b/configure.in index 259ac378b6b..cd77cb24f72 100644 --- a/configure.in +++ b/configure.in @@ -1788,7 +1788,18 @@ then LDFLAGS="$LDFLAGS -rdynamic" AC_MSG_RESULT("-rdynamic") else - AC_MSG_RESULT("none") + case "$SYSTEM_TYPE$with_mysqld_ldflags " in + *freebsd*"-all-static "*|*dragonfly*"-all-static "*) + AC_MSG_RESULT("none") + ;; + *freebsd*|*dragonfly*) + MYSQLD_EXTRA_LDFLAGS="$MYSQLD_EXTRA_LDFLAGS -export-dynamic" + AC_MSG_RESULT("-export-dynamic") + ;; + *) + AC_MSG_RESULT("none") + ;; + esac fi dnl Checks for typedefs, structures, and compiler characteristics. diff --git a/include/my_base.h b/include/my_base.h index 339554979a8..947f7695215 100644 --- a/include/my_base.h +++ b/include/my_base.h @@ -187,7 +187,13 @@ enum ha_extra_function { Inform handler that an "INSERT...ON DUPLICATE KEY UPDATE" will be executed. This condition is unset by HA_EXTRA_NO_IGNORE_DUP_KEY. */ - HA_EXTRA_INSERT_WITH_UPDATE + HA_EXTRA_INSERT_WITH_UPDATE, + /* + Orders MERGE handler to attach or detach its child tables. Used at + begin and end of a statement. + */ + HA_EXTRA_ATTACH_CHILDREN, + HA_EXTRA_DETACH_CHILDREN }; /* The following is parameter to ha_panic() */ @@ -244,6 +250,8 @@ enum ha_base_keytype { HA_BINARY_PACK_KEY | HA_FULLTEXT | HA_UNIQUE_CHECK | \ HA_SPATIAL | HA_NULL_ARE_EQUAL | HA_GENERATED_KEY) +#define HA_KEY_HAS_PART_KEY_SEG 65536 /* Key contains partial segments */ + /* Automatic bits in key-flag */ #define HA_SPACE_PACK_USED 4 /* Test for if SPACE_PACK used */ @@ -407,9 +415,11 @@ enum ha_base_keytype { #define HA_ERR_RECORD_IS_THE_SAME 169 /* row not actually updated : new values same as the old values */ -#define HA_ERR_LOGGING_IMPOSSIBLE 170 /* It is not possible to log this - statement */ -#define HA_ERR_LAST 170 /*Copy last error nr.*/ +#define HA_ERR_LOGGING_IMPOSSIBLE 170 /* It is not possible to log this + statement */ +#define HA_ERR_CORRUPT_EVENT 171 /* The event was corrupt, leading to + illegal data being read */ +#define HA_ERR_LAST 171 /*Copy last error nr.*/ /* Add error numbers before HA_ERR_LAST and change it accordingly. */ #define HA_ERR_ERRORS (HA_ERR_LAST - HA_ERR_FIRST + 1) diff --git a/include/my_sys.h b/include/my_sys.h index 2ce36760032..e13c4cde78b 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -691,6 +691,8 @@ extern WF_PACK *wf_comp(char * str); extern int wf_test(struct wild_file_pack *wf_pack,const char *name); extern void wf_end(struct wild_file_pack *buffer); extern size_t strip_sp(char * str); +extern my_bool array_append_string_unique(const char *str, + const char **array, size_t size); extern void get_date(char * to,int timeflag,time_t use_time); extern void soundex(CHARSET_INFO *, char * out_pntr, char * in_pntr, pbool remove_garbage); @@ -710,8 +712,10 @@ extern sig_handler my_set_alarm_variable(int signo); extern void my_string_ptr_sort(uchar *base, uint items, size_t size); extern void radixsort_for_str_ptr(uchar* base[], uint number_of_elements, size_t size_of_element,uchar *buffer[]); -extern qsort_t qsort2(void *base_ptr, size_t total_elems, size_t size, - qsort2_cmp cmp, void *cmp_argument); +extern qsort_t my_qsort(void *base_ptr, size_t total_elems, size_t size, + qsort_cmp cmp); +extern qsort_t my_qsort2(void *base_ptr, size_t total_elems, size_t size, + qsort2_cmp cmp, void *cmp_argument); extern qsort2_cmp get_ptr_compare(size_t); void my_store_ptr(uchar *buff, size_t pack_length, my_off_t pos); my_off_t my_get_ptr(uchar *ptr, size_t pack_length); @@ -782,7 +786,7 @@ extern int get_index_dynamic(DYNAMIC_ARRAY *array, uchar * element); #define dynamic_element(array,array_index,type) ((type)((array)->buffer) +(array_index)) #define push_dynamic(A,B) insert_dynamic((A),(B)) #define reset_dynamic(array) ((array)->elements= 0) -#define sort_dynamic(A,cmp) qsort((A)->buffer, (A)->elements, (A)->size_of_element, (cmp)) +#define sort_dynamic(A,cmp) my_qsort((A)->buffer, (A)->elements, (A)->size_of_element, (cmp)) extern my_bool init_dynamic_string(DYNAMIC_STRING *str, const char *init_str, size_t init_alloc,size_t alloc_increment); diff --git a/include/myisammrg.h b/include/myisammrg.h index eed50bebaee..0cf3aa222b3 100644 --- a/include/myisammrg.h +++ b/include/myisammrg.h @@ -69,6 +69,8 @@ typedef struct st_myrg_info uint merge_insert_method; uint tables,options,reclength,keys; my_bool cache_in_use; + /* If MERGE children attached to parent. See top comment in ha_myisammrg.cc */ + my_bool children_attached; LIST open_list; QUEUE by_key; ulong *rec_per_key_part; /* for sql optimizing */ @@ -80,6 +82,13 @@ typedef struct st_myrg_info extern int myrg_close(MYRG_INFO *file); extern int myrg_delete(MYRG_INFO *file,const uchar *buff); extern MYRG_INFO *myrg_open(const char *name,int mode,int wait_if_locked); +extern MYRG_INFO *myrg_parent_open(const char *parent_name, + int (*callback)(void*, const char*), + void *callback_param); +extern int myrg_attach_children(MYRG_INFO *m_info, int handle_locking, + MI_INFO *(*callback)(void*), + void *callback_param); +extern int myrg_detach_children(MYRG_INFO *m_info); extern int myrg_panic(enum ha_panic_function function); extern int myrg_rfirst(MYRG_INFO *file,uchar *buf,int inx); extern int myrg_rlast(MYRG_INFO *file,uchar *buf,int inx); diff --git a/include/mysql.h b/include/mysql.h index 68cce3196a0..d114afb6c93 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -557,16 +557,6 @@ unsigned long STDCALL mysql_real_escape_string(MYSQL *mysql, char *to,const char *from, unsigned long length); void STDCALL mysql_debug(const char *debug); -char * STDCALL mysql_odbc_escape_string(MYSQL *mysql, - char *to, - unsigned long to_length, - const char *from, - unsigned long from_length, - void *param, - char * - (*extend_buffer) - (void *, char *to, - unsigned long *length)); void STDCALL myodbc_remove_escape(MYSQL *mysql,char *name); unsigned int STDCALL mysql_thread_safe(void); my_bool STDCALL mysql_embedded(void); diff --git a/include/mysql_com.h b/include/mysql_com.h index f76486b9ec2..4ae7f66060f 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -94,6 +94,7 @@ enum enum_server_command #define TIMESTAMP_FLAG 1024 /* Field is a timestamp */ #define SET_FLAG 2048 /* field is a set */ #define NO_DEFAULT_VALUE_FLAG 4096 /* Field doesn't have default value */ +#define ON_UPDATE_NOW_FLAG 8192 /* Field is set to NOW on UPDATE */ #define NUM_FLAG 32768 /* Field is num (for clients) */ #define PART_KEY_FLAG 16384 /* Intern; Part of some key */ #define GROUP_FLAG 32768 /* Intern: Group field */ diff --git a/include/mysql_h.ic b/include/mysql_h.ic index 12e16df878a..4bedb9e8050 100644 --- a/include/mysql_h.ic +++ b/include/mysql_h.ic @@ -54,7 +54,7 @@ typedef struct st_list LIST; typedef struct st_mem_root MEM_ROOT; # 258 "mysql.h" typedef struct st_mysql MYSQL; -# 664 "mysql.h" +# 654 "mysql.h" typedef struct st_mysql_bind MYSQL_BIND; # 95 "mysql.h" typedef struct st_mysql_field MYSQL_FIELD; @@ -72,17 +72,17 @@ typedef struct st_mysql_res MYSQL_RES; typedef char * * MYSQL_ROW; # 145 "mysql.h" typedef MYSQL_ROWS * MYSQL_ROW_OFFSET; -# 693 "mysql.h" +# 683 "mysql.h" typedef struct st_mysql_stmt MYSQL_STMT; # 52 "mysql/plugin.h" typedef struct st_mysql_xid MYSQL_XID; # 243 "mysql.h" typedef struct character_set MY_CHARSET_INFO; -# 187 "mysql_com.h" +# 188 "mysql_com.h" typedef struct st_net NET; # 22 "typelib.h" typedef struct st_typelib TYPELIB; -# 177 "mysql_com.h" +# 178 "mysql_com.h" typedef struct st_vio Vio; # 28 "my_list.h" typedef int (* list_walk_action)(void *, void *); @@ -92,7 +92,7 @@ typedef char my_bool; typedef int my_socket; # 128 "mysql.h" typedef unsigned long long int my_ulonglong; -# 214 "/usr/lib/gcc/i486-linux-gnu/4.1.2/include/stddef.h" +# 214 "/usr/lib/gcc/i486-linux-gnu/4.1.3/include/stddef.h" typedef unsigned int size_t; # 149 "mysql.h" typedef struct embedded_query_result EMBEDDED_QUERY_RESULT; @@ -102,13 +102,13 @@ typedef struct st_mysql_data MYSQL_DATA; typedef struct st_mysql_ftparser_boolean_info MYSQL_FTPARSER_BOOLEAN_INFO; # 557 "mysql/plugin.h" typedef struct st_mysql_ftparser_param MYSQL_FTPARSER_PARAM; -# 763 "mysql.h" +# 753 "mysql.h" typedef struct st_mysql_methods MYSQL_METHODS; # 47 "mysql_time.h" typedef struct st_mysql_time MYSQL_TIME; -# 383 "mysql_com.h" +# 384 "mysql_com.h" typedef struct st_udf_args UDF_ARGS; -# 397 "mysql_com.h" +# 398 "mysql_com.h" typedef struct st_udf_init UDF_INIT; # 26 "my_alloc.h" typedef struct st_used_mem USED_MEM; @@ -130,7 +130,7 @@ struct __attribute__((aligned(__alignof__(unsigned int)), aligned(__alignof__(vo unsigned int mbminlen; unsigned int mbmaxlen; }; -# 369 "mysql_com.h" +# 370 "mysql_com.h" struct __attribute__((aligned(__alignof__(unsigned long int)), aligned(__alignof__(double)))) rand_struct { unsigned long int seed1; @@ -203,7 +203,7 @@ struct __attribute__((aligned(__alignof__(void *)), aligned(__alignof__(unsigned char * info_buffer; void * extension; }; -# 664 "mysql.h" +# 654 "mysql.h" struct __attribute__((aligned(__alignof__(void *)), aligned(__alignof__(unsigned long int)))) st_mysql_bind { unsigned long int * length; @@ -328,7 +328,7 @@ struct __attribute__((aligned(__alignof__(void *)), aligned(__alignof__(unsigned char last_error[256]; void * extension; }; -# 763 "mysql.h" +# 753 "mysql.h" struct __attribute__((aligned(__alignof__(void *)))) st_mysql_methods { my_bool (* read_query_result)(MYSQL * mysql); @@ -448,7 +448,7 @@ struct __attribute__((aligned(__alignof__(void *)))) st_mysql_show_var char * value; enum enum_mysql_show_type type; }; -# 693 "mysql.h" +# 683 "mysql.h" struct __attribute__((aligned(__alignof__(void *)), aligned(__alignof__(unsigned long long int)))) st_mysql_stmt { MEM_ROOT mem_root; @@ -513,7 +513,7 @@ struct __attribute__((aligned(__alignof__(long int)))) st_mysql_xid long int bqual_length; char data[128]; }; -# 187 "mysql_com.h" +# 188 "mysql_com.h" struct __attribute__((aligned(__alignof__(void *)), aligned(__alignof__(unsigned long int)))) st_net { Vio * vio; @@ -558,7 +558,7 @@ struct __attribute__((aligned(__alignof__(unsigned int)), aligned(__alignof__(vo char const * * type_names; unsigned int * type_lengths; }; -# 383 "mysql_com.h" +# 384 "mysql_com.h" struct __attribute__((aligned(__alignof__(unsigned int)), aligned(__alignof__(void *)))) st_udf_args { unsigned int arg_count; @@ -570,7 +570,7 @@ struct __attribute__((aligned(__alignof__(unsigned int)), aligned(__alignof__(vo unsigned long int * attribute_lengths; void * extension; }; -# 397 "mysql_com.h" +# 398 "mysql_com.h" struct __attribute__((aligned(__alignof__(unsigned long int)), aligned(__alignof__(void *)))) st_udf_init { my_bool maybe_null; @@ -587,7 +587,7 @@ struct __attribute__((aligned(__alignof__(void *)), aligned(__alignof__(unsigned unsigned int left; unsigned int size; }; -# 380 "mysql_com.h" +# 381 "mysql_com.h" enum Item_result { STRING_RESULT = 0, @@ -596,7 +596,7 @@ enum Item_result ROW_RESULT = 3, DECIMAL_RESULT = 4, }; -# 321 "mysql_com.h" +# 322 "mysql_com.h" enum enum_cursor_type { CURSOR_TYPE_NO_CURSOR = 0, @@ -604,7 +604,7 @@ enum enum_cursor_type CURSOR_TYPE_FOR_UPDATE = 2, CURSOR_TYPE_SCROLLABLE = 4, }; -# 234 "mysql_com.h" +# 235 "mysql_com.h" enum enum_field_types { MYSQL_TYPE_DECIMAL = 0, @@ -651,7 +651,7 @@ enum enum_ftparser_mode MYSQL_FTPARSER_WITH_STOPWORDS = 1, MYSQL_FTPARSER_FULL_BOOLEAN_INFO = 2, }; -# 331 "mysql_com.h" +# 332 "mysql_com.h" enum enum_mysql_set_option { MYSQL_OPTION_MULTI_STATEMENTS_ON = 0, @@ -671,7 +671,7 @@ enum enum_mysql_show_type SHOW_FUNC = 8, SHOW_DOUBLE = 9, }; -# 594 "mysql.h" +# 584 "mysql.h" enum enum_mysql_stmt_state { MYSQL_STMT_INIT_DONE = 1, @@ -723,14 +723,14 @@ enum enum_server_command COM_DAEMON = 29, COM_END = 30, }; -# 740 "mysql.h" +# 730 "mysql.h" enum enum_stmt_attr_type { STMT_ATTR_UPDATE_MAX_LENGTH = 0, STMT_ATTR_CURSOR_TYPE = 1, STMT_ATTR_PREFETCH_ROWS = 2, }; -# 296 "mysql_com.h" +# 297 "mysql_com.h" enum mysql_enum_shutdown_level { SHUTDOWN_DEFAULT = 0, @@ -790,13 +790,13 @@ enum mysql_status MYSQL_STATUS_GET_RESULT = 1, MYSQL_STATUS_USE_RESULT = 2, }; -# 438 "mysql_com.h" +# 439 "mysql_com.h" extern my_bool check_scramble(char const * reply, char const * message, unsigned char const * hash_stage2); -# 431 "mysql_com.h" +# 432 "mysql_com.h" extern my_bool check_scramble_323(char const *, char const * message, unsigned long int * salt); # 35 "typelib.h" extern TYPELIB * copy_typelib(MEM_ROOT * root, TYPELIB * from); -# 426 "mysql_com.h" +# 427 "mysql_com.h" extern void create_random_string(char * to, unsigned int, struct rand_struct * rand_st); # 32 "typelib.h" extern int find_type(char * x, TYPELIB const * typelib, unsigned int); @@ -804,15 +804,15 @@ extern int find_type(char * x, TYPELIB const * typelib, unsigned int); extern int find_type_or_exit(char const * x, TYPELIB * typelib, char const * option); # 29 "typelib.h" extern my_ulonglong find_typeset(char * x, TYPELIB * typelib, int * error_position); -# 440 "mysql_com.h" +# 441 "mysql_com.h" extern void get_salt_from_password(unsigned char * res, char const * password); -# 433 "mysql_com.h" +# 434 "mysql_com.h" extern void get_salt_from_password_323(unsigned long int * res, char const * password); -# 446 "mysql_com.h" +# 447 "mysql_com.h" extern char * get_tty_password(char const * opt_message); # 34 "typelib.h" extern char const * get_type(TYPELIB * typelib, unsigned int); -# 428 "mysql_com.h" +# 429 "mysql_com.h" extern void hash_password(unsigned long int * to, char const * password, unsigned int); # 30 "my_list.h" extern LIST * list_add(LIST * root, LIST * element); @@ -828,47 +828,47 @@ extern unsigned int list_length(LIST *); extern LIST * list_reverse(LIST * root); # 36 "my_list.h" extern int list_walk(LIST *, list_walk_action, unsigned char * argument); -# 441 "mysql_com.h" +# 442 "mysql_com.h" extern void make_password_from_salt(char * to, unsigned char const * hash_stage2); -# 434 "mysql_com.h" +# 435 "mysql_com.h" extern void make_password_from_salt_323(char * to, unsigned long int const * salt); -# 436 "mysql_com.h" +# 437 "mysql_com.h" extern void make_scrambled_password(char * to, char const * password); -# 429 "mysql_com.h" +# 430 "mysql_com.h" extern void make_scrambled_password_323(char * to, char const * password); # 33 "typelib.h" extern void make_type(char * to, unsigned int, TYPELIB * typelib); -# 366 "mysql_com.h" +# 367 "mysql_com.h" extern int my_connect(my_socket, struct sockaddr const * name, unsigned int, unsigned int); -# 343 "mysql_com.h" -extern my_bool my_net_init(NET * net, Vio * vio); # 344 "mysql_com.h" +extern my_bool my_net_init(NET * net, Vio * vio); +# 345 "mysql_com.h" extern void my_net_local_init(NET * net); -# 354 "mysql_com.h" +# 355 "mysql_com.h" extern unsigned long int my_net_read(NET * net); -# 349 "mysql_com.h" +# 350 "mysql_com.h" extern my_bool my_net_write(NET * net, unsigned char const * packet, size_t); -# 425 "mysql_com.h" +# 426 "mysql_com.h" extern double my_rnd(struct rand_struct *); -# 452 "mysql_com.h" +# 453 "mysql_com.h" extern void my_thread_end(void); -# 451 "mysql_com.h" +# 452 "mysql_com.h" extern my_bool my_thread_init(void); -# 570 "mysql.h" +# 560 "mysql.h" extern void myodbc_remove_escape(MYSQL * mysql, char * name); # 512 "mysql.h" extern int mysql_add_slave(MYSQL * mysql, char const * host, unsigned int, char const * user, char const * passwd); # 421 "mysql.h" extern my_ulonglong mysql_affected_rows(MYSQL * mysql); -# 836 "mysql.h" +# 826 "mysql.h" extern my_bool mysql_autocommit(MYSQL * mysql, my_bool); # 437 "mysql.h" extern my_bool mysql_change_user(MYSQL * mysql, char const * user, char const * passwd, char const * db); # 429 "mysql.h" extern char const * mysql_character_set_name(MYSQL * mysql); -# 839 "mysql.h" +# 829 "mysql.h" extern void mysql_close(MYSQL * sock); -# 834 "mysql.h" +# 824 "mysql.h" extern my_bool mysql_commit(MYSQL * mysql); # 541 "mysql.h" extern void mysql_data_seek(MYSQL_RES * result, my_ulonglong); @@ -880,7 +880,7 @@ extern void mysql_disable_reads_from_master(MYSQL * mysql); extern void mysql_disable_rpl_parse(MYSQL * mysql); # 520 "mysql.h" extern int mysql_dump_debug_info(MYSQL * mysql); -# 572 "mysql.h" +# 562 "mysql.h" extern my_bool mysql_embedded(void); # 497 "mysql.h" extern void mysql_enable_reads_from_master(MYSQL * mysql); @@ -890,7 +890,7 @@ extern void mysql_enable_rpl_parse(MYSQL * mysql); extern my_bool mysql_eof(MYSQL_RES * res); # 423 "mysql.h" extern unsigned int mysql_errno(MYSQL * mysql); -# 447 "mysql_com.h" +# 448 "mysql_com.h" extern char const * mysql_errno_to_sqlstate(unsigned int); # 424 "mysql.h" extern char const * mysql_error(MYSQL * mysql); @@ -950,30 +950,28 @@ extern MYSQL_RES * mysql_list_fields(MYSQL * mysql, char const * table, char con extern MYSQL_RES * mysql_list_processes(MYSQL * mysql); # 536 "mysql.h" extern MYSQL_RES * mysql_list_tables(MYSQL * mysql, char const * wild); -# 579 "mysql.h" +# 569 "mysql.h" extern void mysql_manager_close(MYSQL_MANAGER * con); -# 580 "mysql.h" +# 570 "mysql.h" extern int mysql_manager_command(MYSQL_MANAGER * con, char const * cmd, int); -# 574 "mysql.h" +# 564 "mysql.h" extern MYSQL_MANAGER * mysql_manager_connect(MYSQL_MANAGER * con, char const * host, char const * user, char const * passwd, unsigned int); -# 582 "mysql.h" +# 572 "mysql.h" extern int mysql_manager_fetch_line(MYSQL_MANAGER * con, char * res_buf, int); -# 573 "mysql.h" +# 563 "mysql.h" extern MYSQL_MANAGER * mysql_manager_init(MYSQL_MANAGER * con); # 456 "mysql.h" extern my_bool mysql_master_query(MYSQL * mysql, char const * q, unsigned long int); # 458 "mysql.h" extern my_bool mysql_master_send_query(MYSQL * mysql, char const * q, unsigned long int); -# 837 "mysql.h" +# 827 "mysql.h" extern my_bool mysql_more_results(MYSQL * mysql); -# 838 "mysql.h" +# 828 "mysql.h" extern int mysql_next_result(MYSQL * mysql); # 412 "mysql.h" extern unsigned int mysql_num_fields(MYSQL_RES * res); # 411 "mysql.h" extern my_ulonglong mysql_num_rows(MYSQL_RES * res); -# 560 "mysql.h" -extern char * mysql_odbc_escape_string(MYSQL * mysql, char * to, unsigned long int, char const * from, unsigned long int, void * param, char * (* extend_buffer)(void *, char * to, unsigned long int * length)); # 538 "mysql.h" extern int mysql_options(MYSQL * mysql, enum mysql_option, void const * arg); # 527 "mysql.h" @@ -984,7 +982,7 @@ extern unsigned int mysql_port; extern int mysql_query(MYSQL * mysql, char const * q); # 780 "mysql/plugin.h" extern void mysql_query_cache_invalidate4(void * thd, char const * key, unsigned int, int); -# 585 "mysql.h" +# 575 "mysql.h" extern my_bool mysql_read_query_result(MYSQL * mysql); # 500 "mysql.h" extern my_bool mysql_reads_from_master_enabled(MYSQL * mysql); @@ -996,7 +994,7 @@ extern unsigned long int mysql_real_escape_string(MYSQL * mysql, char * to, char extern int mysql_real_query(MYSQL * mysql, char const * q, unsigned long int); # 521 "mysql.h" extern int mysql_refresh(MYSQL * mysql, unsigned int); -# 835 "mysql.h" +# 825 "mysql.h" extern my_bool mysql_rollback(MYSQL * mysql); # 543 "mysql.h" extern MYSQL_ROW_OFFSET mysql_row_seek(MYSQL_RES * result, MYSQL_ROW_OFFSET); @@ -1038,59 +1036,59 @@ extern char const * mysql_sqlstate(MYSQL * mysql); extern my_bool mysql_ssl_set(MYSQL * mysql, char const * key, char const * cert, char const * ca, char const * capath, char const * cipher); # 528 "mysql.h" extern char const * mysql_stat(MYSQL * mysql); -# 830 "mysql.h" -extern my_ulonglong mysql_stmt_affected_rows(MYSQL_STMT * stmt); -# 808 "mysql.h" -extern my_bool mysql_stmt_attr_get(MYSQL_STMT * stmt, enum enum_stmt_attr_type, void * attr); -# 805 "mysql.h" -extern my_bool mysql_stmt_attr_set(MYSQL_STMT * stmt, enum enum_stmt_attr_type, void const * attr); -# 811 "mysql.h" -extern my_bool mysql_stmt_bind_param(MYSQL_STMT * stmt, MYSQL_BIND * bnd); -# 812 "mysql.h" -extern my_bool mysql_stmt_bind_result(MYSQL_STMT * stmt, MYSQL_BIND * bnd); -# 813 "mysql.h" -extern my_bool mysql_stmt_close(MYSQL_STMT * stmt); -# 828 "mysql.h" -extern void mysql_stmt_data_seek(MYSQL_STMT * stmt, my_ulonglong); -# 822 "mysql.h" -extern unsigned int mysql_stmt_errno(MYSQL_STMT * stmt); -# 823 "mysql.h" -extern char const * mysql_stmt_error(MYSQL_STMT * stmt); -# 798 "mysql.h" -extern int mysql_stmt_execute(MYSQL_STMT * stmt); -# 799 "mysql.h" -extern int mysql_stmt_fetch(MYSQL_STMT * stmt); -# 800 "mysql.h" -extern int mysql_stmt_fetch_column(MYSQL_STMT * stmt, MYSQL_BIND * bind_arg, unsigned int, unsigned long int); -# 832 "mysql.h" -extern unsigned int mysql_stmt_field_count(MYSQL_STMT * stmt); -# 815 "mysql.h" -extern my_bool mysql_stmt_free_result(MYSQL_STMT * stmt); -# 795 "mysql.h" -extern MYSQL_STMT * mysql_stmt_init(MYSQL * mysql); -# 831 "mysql.h" -extern my_ulonglong mysql_stmt_insert_id(MYSQL_STMT * stmt); -# 829 "mysql.h" -extern my_ulonglong mysql_stmt_num_rows(MYSQL_STMT * stmt); -# 804 "mysql.h" -extern unsigned long int mysql_stmt_param_count(MYSQL_STMT * stmt); -# 821 "mysql.h" -extern MYSQL_RES * mysql_stmt_param_metadata(MYSQL_STMT * stmt); -# 796 "mysql.h" -extern int mysql_stmt_prepare(MYSQL_STMT * stmt, char const * query, unsigned long int); -# 814 "mysql.h" -extern my_bool mysql_stmt_reset(MYSQL_STMT * stmt); # 820 "mysql.h" -extern MYSQL_RES * mysql_stmt_result_metadata(MYSQL_STMT * stmt); -# 825 "mysql.h" -extern MYSQL_ROW_OFFSET mysql_stmt_row_seek(MYSQL_STMT * stmt, MYSQL_ROW_OFFSET); -# 827 "mysql.h" -extern MYSQL_ROW_OFFSET mysql_stmt_row_tell(MYSQL_STMT * stmt); -# 816 "mysql.h" -extern my_bool mysql_stmt_send_long_data(MYSQL_STMT * stmt, unsigned int, char const * data, unsigned long int); -# 824 "mysql.h" -extern char const * mysql_stmt_sqlstate(MYSQL_STMT * stmt); +extern my_ulonglong mysql_stmt_affected_rows(MYSQL_STMT * stmt); +# 798 "mysql.h" +extern my_bool mysql_stmt_attr_get(MYSQL_STMT * stmt, enum enum_stmt_attr_type, void * attr); +# 795 "mysql.h" +extern my_bool mysql_stmt_attr_set(MYSQL_STMT * stmt, enum enum_stmt_attr_type, void const * attr); +# 801 "mysql.h" +extern my_bool mysql_stmt_bind_param(MYSQL_STMT * stmt, MYSQL_BIND * bnd); +# 802 "mysql.h" +extern my_bool mysql_stmt_bind_result(MYSQL_STMT * stmt, MYSQL_BIND * bnd); # 803 "mysql.h" +extern my_bool mysql_stmt_close(MYSQL_STMT * stmt); +# 818 "mysql.h" +extern void mysql_stmt_data_seek(MYSQL_STMT * stmt, my_ulonglong); +# 812 "mysql.h" +extern unsigned int mysql_stmt_errno(MYSQL_STMT * stmt); +# 813 "mysql.h" +extern char const * mysql_stmt_error(MYSQL_STMT * stmt); +# 788 "mysql.h" +extern int mysql_stmt_execute(MYSQL_STMT * stmt); +# 789 "mysql.h" +extern int mysql_stmt_fetch(MYSQL_STMT * stmt); +# 790 "mysql.h" +extern int mysql_stmt_fetch_column(MYSQL_STMT * stmt, MYSQL_BIND * bind_arg, unsigned int, unsigned long int); +# 822 "mysql.h" +extern unsigned int mysql_stmt_field_count(MYSQL_STMT * stmt); +# 805 "mysql.h" +extern my_bool mysql_stmt_free_result(MYSQL_STMT * stmt); +# 785 "mysql.h" +extern MYSQL_STMT * mysql_stmt_init(MYSQL * mysql); +# 821 "mysql.h" +extern my_ulonglong mysql_stmt_insert_id(MYSQL_STMT * stmt); +# 819 "mysql.h" +extern my_ulonglong mysql_stmt_num_rows(MYSQL_STMT * stmt); +# 794 "mysql.h" +extern unsigned long int mysql_stmt_param_count(MYSQL_STMT * stmt); +# 811 "mysql.h" +extern MYSQL_RES * mysql_stmt_param_metadata(MYSQL_STMT * stmt); +# 786 "mysql.h" +extern int mysql_stmt_prepare(MYSQL_STMT * stmt, char const * query, unsigned long int); +# 804 "mysql.h" +extern my_bool mysql_stmt_reset(MYSQL_STMT * stmt); +# 810 "mysql.h" +extern MYSQL_RES * mysql_stmt_result_metadata(MYSQL_STMT * stmt); +# 815 "mysql.h" +extern MYSQL_ROW_OFFSET mysql_stmt_row_seek(MYSQL_STMT * stmt, MYSQL_ROW_OFFSET); +# 817 "mysql.h" +extern MYSQL_ROW_OFFSET mysql_stmt_row_tell(MYSQL_STMT * stmt); +# 806 "mysql.h" +extern my_bool mysql_stmt_send_long_data(MYSQL_STMT * stmt, unsigned int, char const * data, unsigned long int); +# 814 "mysql.h" +extern char const * mysql_stmt_sqlstate(MYSQL_STMT * stmt); +# 793 "mysql.h" extern int mysql_stmt_store_result(MYSQL_STMT * stmt); # 452 "mysql.h" extern MYSQL_RES * mysql_store_result(MYSQL * mysql); @@ -1100,7 +1098,7 @@ extern void mysql_thread_end(void); extern unsigned long int mysql_thread_id(MYSQL * mysql); # 403 "mysql.h" extern my_bool mysql_thread_init(void); -# 571 "mysql.h" +# 561 "mysql.h" extern unsigned int mysql_thread_safe(void); # 699 "mysql/plugin.h" extern int mysql_tmpfile(char const * prefix); @@ -1110,25 +1108,25 @@ extern char * mysql_unix_port; extern MYSQL_RES * mysql_use_result(MYSQL * mysql); # 426 "mysql.h" extern unsigned int mysql_warning_count(MYSQL * mysql); -# 346 "mysql_com.h" -extern void net_clear(NET * net, my_bool); -# 345 "mysql_com.h" -extern void net_end(NET * net); -# 348 "mysql_com.h" -extern my_bool net_flush(NET * net); -# 353 "mysql_com.h" -extern int net_real_write(NET * net, unsigned char const * packet, size_t); # 347 "mysql_com.h" +extern void net_clear(NET * net, my_bool); +# 346 "mysql_com.h" +extern void net_end(NET * net); +# 349 "mysql_com.h" +extern my_bool net_flush(NET * net); +# 354 "mysql_com.h" +extern int net_real_write(NET * net, unsigned char const * packet, size_t); +# 348 "mysql_com.h" extern my_bool net_realloc(NET * net, size_t); -# 350 "mysql_com.h" +# 351 "mysql_com.h" extern my_bool net_write_command(NET * net, unsigned char, unsigned char const * header, size_t, unsigned char const * packet, size_t); -# 442 "mysql_com.h" +# 443 "mysql_com.h" extern char * octet2hex(char * to, char const * str, unsigned int); -# 423 "mysql_com.h" +# 424 "mysql_com.h" extern void randominit(struct rand_struct *, unsigned long int, unsigned long int); -# 437 "mysql_com.h" +# 438 "mysql_com.h" extern void scramble(char * to, char const * message, char const * password); -# 430 "mysql_com.h" +# 431 "mysql_com.h" extern void scramble_323(char * to, char const * message, char const * password); # 37 "typelib.h" extern TYPELIB sql_protocol_typelib; diff --git a/libmysql/CMakeLists.txt b/libmysql/CMakeLists.txt index 8471bbbd76c..249e6294c22 100755 --- a/libmysql/CMakeLists.txt +++ b/libmysql/CMakeLists.txt @@ -75,7 +75,7 @@ SET(CLIENT_SOURCES ../mysys/array.c ../strings/bchange.c ../strings/bmove.c ../mysys/hash.c ../mysys/my_sleep.c ../mysys/default_modify.c get_password.c ../strings/int2str.c ../strings/is_prefix.c libmysql.c ../mysys/list.c ../strings/llstr.c - ../strings/longlong2str.c manager.c ../mysys/mf_cache.c + ../strings/longlong2str.c manager.c ../mysys/mf_arr_appstr.c ../mysys/mf_cache.c ../mysys/mf_dirname.c ../mysys/mf_fn_ext.c ../mysys/mf_format.c ../mysys/mf_iocache.c ../mysys/mf_iocache2.c ../mysys/mf_loadpath.c ../mysys/mf_pack.c ../mysys/mf_path.c ../mysys/mf_tempfile.c ../mysys/mf_unixpath.c @@ -97,7 +97,7 @@ SET(CLIENT_SOURCES ../mysys/array.c ../strings/bchange.c ../strings/bmove.c ../strings/strmov.c ../strings/strnlen.c ../strings/strnmov.c ../strings/strtod.c ../strings/strtoll.c ../strings/strtoull.c ../strings/strxmov.c ../strings/strxnmov.c ../mysys/thr_mutex.c ../mysys/typelib.c ../vio/vio.c ../vio/viosocket.c - ../vio/viossl.c ../vio/viosslfactories.c ../strings/xml.c + ../vio/viossl.c ../vio/viosslfactories.c ../strings/xml.c ../mysys/mf_qsort.c ../mysys/my_getsystime.c ${LIB_SOURCES}) # Need to set USE_TLS for building the DLL, since __declspec(thread) diff --git a/libmysql/Makefile.shared b/libmysql/Makefile.shared index 3a2559921f9..53b24c4fb42 100644 --- a/libmysql/Makefile.shared +++ b/libmysql/Makefile.shared @@ -59,7 +59,7 @@ mysysobjects1 = my_init.lo my_static.lo my_malloc.lo my_realloc.lo \ mf_pack.lo my_messnc.lo mf_dirname.lo mf_fn_ext.lo\ mf_wcomp.lo typelib.lo safemalloc.lo my_alloc.lo \ mf_format.lo mf_path.lo mf_unixpath.lo my_fopen.lo \ - my_symlink.lo my_fstream.lo \ + my_symlink.lo my_fstream.lo mf_arr_appstr.lo \ mf_loadpath.lo my_pthread.lo my_thr_init.lo \ thr_mutex.lo mulalloc.lo string.lo \ default.lo default_modify.lo \ @@ -73,7 +73,7 @@ sqlobjects = net.lo sql_cmn_objects = pack.lo client.lo my_time.lo # Not needed in the minimum library -mysysobjects2 = my_lib.lo +mysysobjects2 = my_lib.lo mf_qsort.lo mysysobjects = $(mysysobjects1) $(mysysobjects2) target_libadd = $(mysysobjects) $(mystringsobjects) $(dbugobjects) \ $(sql_cmn_objects) $(vio_objects) $(sqlobjects) diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index cb326fa4685..bf5dd7d63eb 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -1629,78 +1629,6 @@ mysql_real_escape_string(MYSQL *mysql, char *to,const char *from, return escape_string_for_mysql(mysql->charset, to, 0, from, length); } - -char * STDCALL -mysql_odbc_escape_string(MYSQL *mysql, - char *to, ulong to_length, - const char *from, ulong from_length, - void *param, - char * (*extend_buffer) - (void *, char *, ulong *)) -{ - char *to_end=to+to_length-5; - const char *end; -#ifdef USE_MB - my_bool use_mb_flag=use_mb(mysql->charset); -#endif - - for (end=from+from_length; from != end ; from++) - { - if (to >= to_end) - { - to_length = (ulong) (end-from)+512; /* We want this much more */ - if (!(to=(*extend_buffer)(param, to, &to_length))) - return to; - to_end=to+to_length-5; - } -#ifdef USE_MB - { - int l; - if (use_mb_flag && (l = my_ismbchar(mysql->charset, from, end))) - { - while (l--) - *to++ = *from++; - from--; - continue; - } - } -#endif - switch (*from) { - case 0: /* Must be escaped for 'mysql' */ - *to++= '\\'; - *to++= '0'; - break; - case '\n': /* Must be escaped for logs */ - *to++= '\\'; - *to++= 'n'; - break; - case '\r': - *to++= '\\'; - *to++= 'r'; - break; - case '\\': - *to++= '\\'; - *to++= '\\'; - break; - case '\'': - *to++= '\\'; - *to++= '\''; - break; - case '"': /* Better safe than sorry */ - *to++= '\\'; - *to++= '"'; - break; - case '\032': /* This gives problems on Win32 */ - *to++= '\\'; - *to++= 'Z'; - break; - default: - *to++= *from; - } - } - return to; -} - void STDCALL myodbc_remove_escape(MYSQL *mysql,char *name) { diff --git a/libmysql/libmysql.def b/libmysql/libmysql.def index 8c6b71d9553..81f86dc8726 100644 --- a/libmysql/libmysql.def +++ b/libmysql/libmysql.def @@ -78,7 +78,6 @@ EXPORTS mysql_next_result mysql_num_fields mysql_num_rows - mysql_odbc_escape_string mysql_options mysql_stmt_param_count mysql_stmt_param_metadata diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc index 5eda45ee5d7..cf6013f2ffb 100644 --- a/libmysqld/lib_sql.cc +++ b/libmysqld/lib_sql.cc @@ -97,6 +97,7 @@ emb_advanced_command(MYSQL *mysql, enum enum_server_command command, thd->current_stmt= stmt; thd->store_globals(); // Fix if more than one connect + lex_start(thd); /* We have to call free_old_query before we start to fill mysql->fields for new query. In the case of embedded server we collect field data @@ -587,6 +588,7 @@ void *create_embedded_thd(int client_flag) fprintf(stderr,"store_globals failed.\n"); goto err; } + lex_start(thd); /* TODO - add init_connect command execution */ diff --git a/libmysqld/libmysqld.def b/libmysqld/libmysqld.def index 78ff08e510a..2aa75c0b23c 100644 --- a/libmysqld/libmysqld.def +++ b/libmysqld/libmysqld.def @@ -78,7 +78,6 @@ EXPORTS mysql_next_result mysql_num_fields mysql_num_rows - mysql_odbc_escape_string mysql_options mysql_ping mysql_query diff --git a/mysql-test/extra/binlog_tests/blackhole.test b/mysql-test/extra/binlog_tests/blackhole.test index 1ca59955d76..df2295af4ff 100644 --- a/mysql-test/extra/binlog_tests/blackhole.test +++ b/mysql-test/extra/binlog_tests/blackhole.test @@ -134,6 +134,15 @@ drop table t1,t2,t3; # table # CREATE TABLE t1(a INT) ENGINE=BLACKHOLE; +# NOTE: After exchanging open_ltable() by open_and_lock_tables() in +# handle_delayed_insert() to fix problems with MERGE tables (Bug#26379), +# problems with INSERT DELAYED and BLACKHOLE popped up. open_ltable() +# does not check if the binlogging capabilities of the statement and the +# table match. So the below used to succeed. But since INSERT DELAYED +# switches to row-based logging in mixed-mode and BLACKHOLE cannot do +# row-based logging, it could not really work. Until this problem is +# correctly fixed, we have that error here. +--error ER_BINLOG_LOGGING_IMPOSSIBLE INSERT DELAYED INTO t1 VALUES(1); DROP TABLE t1; diff --git a/mysql-test/extra/binlog_tests/database.test b/mysql-test/extra/binlog_tests/database.test new file mode 100644 index 00000000000..11a8f53a6d7 --- /dev/null +++ b/mysql-test/extra/binlog_tests/database.test @@ -0,0 +1,15 @@ +source include/have_log_bin.inc; +source include/not_embedded.inc; + +# Checking that the drop of a database does not replicate anything in +# addition to the drop of the database + +reset master; +create database testing_1; +use testing_1; +create table t1 (a int); +create function sf1 (a int) returns int return a+1; +create trigger tr1 before insert on t1 for each row insert into t2 values (2*new.a); +create procedure sp1 (a int) insert into t1 values(a); +drop database testing_1; +source include/show_binlog_events.inc; diff --git a/mysql-test/extra/binlog_tests/mix_innodb_myisam_side_effects.test b/mysql-test/extra/binlog_tests/mix_innodb_myisam_side_effects.test new file mode 100644 index 00000000000..03514bfdb55 --- /dev/null +++ b/mysql-test/extra/binlog_tests/mix_innodb_myisam_side_effects.test @@ -0,0 +1,298 @@ +# the file to be sourced from binlog.binlog_mix_innodb_myisam + +# +# Bug #27417 thd->no_trans_update.stmt lost value inside of SF-exec-stack +# bug #28960 non-trans temp table changes with insert .. select +# not binlogged after rollback +# +# testing appearence of insert into temp_table in binlog. +# There are two branches of execution that require different setup. + +# checking binlog content filled with row-based events due to +# a used stored function modifies non-transactional table + +## send_eof() branch + +# prepare + +create temporary table tt (a int unique); +create table ti (a int) engine=innodb; +reset master; +show master status; + +# action + +begin; +insert into ti values (1); +insert into ti values (2) ; +insert into tt select * from ti; +rollback; + +# check + +select count(*) from tt /* 2 */; +show master status; +source include/show_binlog_events.inc; +select count(*) from ti /* zero */; +insert into ti select * from tt; +select * from ti /* that is what slave would miss - bug#28960 */; + + +## send_error() branch +delete from ti; +delete from tt where a=1; +reset master; +show master status; + +# action + +begin; +insert into ti values (1); +insert into ti values (2) /* to make the dup error in the following */; +--error ER_DUP_ENTRY +insert into tt select * from ti /* one affected and error */; +rollback; + +# check + +show master status; +source include/show_binlog_events.inc; # nothing in binlog with row bilog format +select count(*) from ti /* zero */; +insert into ti select * from tt; +select * from tt /* that is what otherwise slave missed - the bug */; + +drop table ti; + + +# +# Bug #27417 thd->no_trans_update.stmt lost value inside of SF-exec-stack +# +# Testing asserts: if there is a side effect of modifying non-transactional +# table thd->no_trans_update.stmt must be TRUE; +# the assert is active with debug build +# + +--disable_warnings +drop function if exists bug27417; +drop table if exists t1,t2; +--enable_warnings +# side effect table +CREATE TABLE t1 (a int NOT NULL auto_increment primary key) ENGINE=MyISAM; +# target tables +CREATE TABLE t2 (a int NOT NULL auto_increment, PRIMARY KEY (a)); + +delimiter |; +create function bug27417(n int) +RETURNS int(11) +begin + insert into t1 values (null); + return n; +end| +delimiter ;| + +reset master; + +# execute + +insert into t2 values (bug27417(1)); +insert into t2 select bug27417(2); +reset master; + +--error ER_DUP_ENTRY +insert into t2 values (bug27417(2)); +source include/show_binlog_events.inc; #only (!) with fixes for #23333 will show there is the query +select count(*) from t1 /* must be 3 */; + +reset master; +select count(*) from t2; +delete from t2 where a=bug27417(3); +select count(*) from t2 /* nothing got deleted */; +source include/show_binlog_events.inc; # the query must be in regardless of #23333 +select count(*) from t1 /* must be 5 */; + +--enable_info +delete t2 from t2 where t2.a=bug27417(100) /* must not affect t2 */; +--disable_info +select count(*) from t1 /* must be 7 */; + +# function bug27417 remains for the following testing of bug#23333 +drop table t1,t2; + +# +# Bug#23333 using the patch (and the test) for bug#27471 +# throughout the bug tests +# t1 - non-trans side effects gatherer; +# t2 - transactional table; +# +CREATE TABLE t1 (a int NOT NULL auto_increment primary key) ENGINE=MyISAM; +CREATE TABLE t2 (a int, PRIMARY KEY (a)) ENGINE=InnoDB; +CREATE TABLE t3 (a int, PRIMARY KEY (a), b int unique) ENGINE=MyISAM; +CREATE TABLE t4 (a int, PRIMARY KEY (a), b int unique) ENGINE=Innodb; +CREATE TABLE t5 (a int, PRIMARY KEY (a)) ENGINE=InnoDB; + + +# +# INSERT +# + +# prepare + + insert into t2 values (1); + reset master; + +# execute + + --error ER_DUP_ENTRY + insert into t2 values (bug27417(1)); + +# check + + source include/show_binlog_events.inc; # must be event of the query + select count(*) from t1 /* must be 1 */; + +# +# INSERT SELECT +# + +# prepare + delete from t1; + delete from t2; + insert into t2 values (2); + reset master; + +# execute + + --error ER_DUP_ENTRY + insert into t2 select bug27417(1) union select bug27417(2); + +# check + + source include/show_binlog_events.inc; # must be events of the query + select count(*) from t1 /* must be 2 */; + +# +# UPDATE inc multi-update +# + +# prepare + delete from t1; + insert into t3 values (1,1),(2,3),(3,4); + reset master; + +# execute + --error ER_DUP_ENTRY + update t3 set b=b+bug27417(1); + +# check + source include/show_binlog_events.inc; # must be events of the query + select count(*) from t1 /* must be 2 */; + +## multi_update::send_eof() branch + +# prepare + delete from t3; + delete from t4; + insert into t3 values (1,1); + insert into t4 values (1,1),(2,2); + + reset master; + +# execute + --error ER_DUP_ENTRY + UPDATE t4,t3 SET t4.a=t3.a + bug27417(1) /* top level non-ta table */; + +# check + source include/show_binlog_events.inc; # the offset must denote there is the query + select count(*) from t1 /* must be 4 */; + +## send_error() branch of multi_update + +# prepare + delete from t1; + delete from t3; + delete from t4; + insert into t3 values (1,1),(2,2); + insert into t4 values (1,1),(2,2); + + reset master; + +# execute + --error ER_DUP_ENTRY + UPDATE t3,t4 SET t3.a=t4.a + bug27417(1); + +# check + select count(*) from t1 /* must be 1 */; + +# cleanup + drop table t4; + + +# +# DELETE incl multi-delete +# + +# prepare + delete from t1; + delete from t2; + delete from t3; + insert into t2 values (1); + insert into t3 values (1,1); + create trigger trg_del before delete on t2 for each row + insert into t3 values (bug27417(1), 2); + reset master; + +# execute + --error ER_DUP_ENTRY + delete from t2; +# check + source include/show_binlog_events.inc; # the offset must denote there is the query + select count(*) from t1 /* must be 1 */; + +# cleanup + drop trigger trg_del; + +# prepare + delete from t1; + delete from t2; + delete from t5; + create trigger trg_del_t2 after delete on t2 for each row + insert into t1 values (1); + insert into t2 values (2),(3); + insert into t5 values (1),(2); + reset master; + +# execute + --error ER_DUP_ENTRY + delete t2.* from t2,t5 where t2.a=t5.a + 1; + +# check + source include/show_binlog_events.inc; # must be events of the query + select count(*) from t1 /* must be 1 */; + + +# +# LOAD DATA +# + +# prepare + delete from t1; + create table t4 (a int default 0, b int primary key) engine=innodb; + insert into t4 values (0, 17); + reset master; + +# execute + --error ER_DUP_ENTRY + load data infile '../std_data_ln/rpl_loaddata.dat' into table t4 (a, @b) set b= @b + bug27417(2); +# check + select * from t4; + select count(*) from t1 /* must be 2 */; + source include/show_binlog_events.inc; # must be events of the query + +# +# bug#23333 cleanup +# + + +drop trigger trg_del_t2; +drop table t1,t2,t3,t4,t5; +drop function bug27417; diff --git a/mysql-test/extra/rpl_tests/rpl_extraMaster_Col.test b/mysql-test/extra/rpl_tests/rpl_extraMaster_Col.test index d3959d10306..cdd828305dc 100644 --- a/mysql-test/extra/rpl_tests/rpl_extraMaster_Col.test +++ b/mysql-test/extra/rpl_tests/rpl_extraMaster_Col.test @@ -410,7 +410,7 @@ binary data'; select * from t2 order by f1; select * from t3 order by f1; select * from t4 order by f1; - select * from t31 order by f1; + select * from t31 order by f3; connection master; --echo diff --git a/mysql-test/extra/rpl_tests/rpl_extraSlave_Col.test b/mysql-test/extra/rpl_tests/rpl_extraSlave_Col.test index a4ac55cc2e8..6fa2c9ac1b5 100644 --- a/mysql-test/extra/rpl_tests/rpl_extraSlave_Col.test +++ b/mysql-test/extra/rpl_tests/rpl_extraSlave_Col.test @@ -10,7 +10,7 @@ ########### Clean up ################ --disable_warnings --disable_query_log -DROP TABLE IF EXISTS t1, t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17; +DROP TABLE IF EXISTS t1, t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t14a,t15,t16,t17; --enable_query_log --enable_warnings @@ -662,6 +662,68 @@ sync_slave_with_master; --replace_column 7 CURRENT_TIMESTAMP SELECT * FROM t14 ORDER BY c1; +#################################################### +# - Alter Master drop column at end of table # +# Expect: column dropped # +#################################################### + +--echo *** Create t14a on slave *** +STOP SLAVE; +RESET SLAVE; +eval CREATE TABLE t14a (c1 INT KEY, c4 BLOB, c5 CHAR(5), + c6 INT DEFAULT '1', + c7 TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP + )ENGINE=$engine_type; + +--echo *** Create t14a on Master *** +connection master; +eval CREATE TABLE t14a (c1 INT PRIMARY KEY, c4 BLOB, c5 CHAR(5) + ) ENGINE=$engine_type; +RESET MASTER; + +--echo *** Start Slave *** +connection slave; +START SLAVE; + +--echo *** Master Data Insert *** +connection master; +set @b1 = 'b1b1b1b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t14a () VALUES(1,@b1,'Kyle'), + (2,@b1,'JOE'), + (3,@b1,'QA'); + +SELECT * FROM t14a ORDER BY c1; +--echo *** Select on Slave **** +sync_slave_with_master; +--replace_column 5 CURRENT_TIMESTAMP +SELECT * FROM t14a ORDER BY c1; +STOP SLAVE; +RESET SLAVE; + +--echo *** Master Drop c5 *** +connection master; +ALTER TABLE t14a DROP COLUMN c5; +RESET MASTER; + +--echo *** Start Slave *** +connection slave; +START SLAVE; + +--echo *** Master Data Insert *** +connection master; +set @b1 = 'b1b1b1b1'; +set @b1 = concat(@b1,@b1); + +INSERT INTO t14a () VALUES(4,@b1), + (5,@b1), + (6,@b1); +SELECT * FROM t14a ORDER BY c1; + +--echo *** Select on Slave **** +sync_slave_with_master; +--replace_column 5 CURRENT_TIMESTAMP +SELECT * FROM t14a ORDER BY c1; #################################################### # - Alter Master Dropping columns from the middle. # @@ -736,7 +798,7 @@ connection slave; --replace_result $MASTER_MYPORT MASTER_PORT --replace_column 1 # 4 # 7 # 8 # 9 # 16 # 22 # 23 # 33 # 35 # 36 # --query_vertical SHOW SLAVE STATUS -SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; START SLAVE; --echo *** Try to insert in master **** @@ -744,6 +806,8 @@ connection master; INSERT INTO t15 () VALUES(5,2.00,'Replication Testing',@b1,'Buda',2); SELECT * FROM t15 ORDER BY c1; +#SHOW BINLOG EVENTS; + --echo *** Try to select from slave **** sync_slave_with_master; --replace_column 7 CURRENT_TIMESTAMP @@ -856,7 +920,10 @@ sync_slave_with_master; #### Clean Up #### --disable_warnings --disable_query_log -DROP TABLE IF EXISTS t1, t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17; +connection master; +DROP TABLE IF EXISTS t1, t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t14a,t15,t16,t17; +sync_slave_with_master; +connection master; --enable_query_log --enable_warnings diff --git a/mysql-test/extra/rpl_tests/rpl_row_basic.test b/mysql-test/extra/rpl_tests/rpl_row_basic.test index 6de254d9931..c35a53f15bc 100644 --- a/mysql-test/extra/rpl_tests/rpl_row_basic.test +++ b/mysql-test/extra/rpl_tests/rpl_row_basic.test @@ -215,11 +215,36 @@ sync_slave_with_master; --echo --- on slave --- SELECT * FROM t8 ORDER BY a; -# -# Test conflicting operations when changing in a table referenced by a -# foreign key. We'll reuse the above table and just add a table that -# references it. -# +# BUG#31552: Replication breaks when deleting rows from out-of-sync +# table without PK + +--echo **** Test for BUG#31552 **** + +--echo **** On Master **** +# Clean up t1 so that we can use it. +connection master; +DELETE FROM t1; +sync_slave_with_master; + +# Just to get a clean binary log +source include/reset_master_and_slave.inc; + +--echo **** On Master **** +connection master; +INSERT INTO t1 VALUES ('K','K'), ('L','L'), ('M','M'); +--echo **** On Master **** +sync_slave_with_master; +DELETE FROM t1 WHERE C1 = 'L'; + +connection master; +DELETE FROM t1; +query_vertical SELECT COUNT(*) FROM t1 ORDER BY c1,c2; +sync_slave_with_master; +let $last_error = query_get_value("SHOW SLAVE STATUS", Last_SQL_Errno, 1); +disable_query_log; +eval SELECT "$last_error" AS Last_SQL_Error; +enable_query_log; +query_vertical SELECT COUNT(*) FROM t1 ORDER BY c1,c2; # # cleanup @@ -227,3 +252,4 @@ SELECT * FROM t8 ORDER BY a; connection master; DROP TABLE IF EXISTS t1,t2,t3,t4,t5,t6,t7,t8; +sync_slave_with_master; diff --git a/mysql-test/extra/rpl_tests/rpl_truncate_helper.test b/mysql-test/extra/rpl_tests/rpl_truncate_helper.test index 64a8de7c6a0..76db74acfa1 100644 --- a/mysql-test/extra/rpl_tests/rpl_truncate_helper.test +++ b/mysql-test/extra/rpl_tests/rpl_truncate_helper.test @@ -1,17 +1,16 @@ - ---disable_query_log ---disable_warnings connection slave; STOP SLAVE; +source include/wait_for_slave_to_stop.inc; connection master; +--disable_warnings DROP TABLE IF EXISTS t1; -RESET MASTER; +--enable_warnings connection slave; +--disable_warnings DROP TABLE IF EXISTS t1; +--enable_warnings RESET SLAVE; START SLAVE; ---enable_warnings ---enable_query_log --echo **** On Master **** connection master; @@ -38,3 +37,6 @@ connection master; DROP TABLE t1; let $SERVER_VERSION=`select version()`; source include/show_binlog_events.inc; + +connection master; +RESET MASTER; diff --git a/mysql-test/include/ctype_regex.inc b/mysql-test/include/ctype_regex.inc new file mode 100644 index 00000000000..0e6b4c41607 --- /dev/null +++ b/mysql-test/include/ctype_regex.inc @@ -0,0 +1,42 @@ +# +# To test a desired collation, set session.collation_connection to +# this collation before including this file +# + +--disable_warnings +drop table if exists t1; +--enable_warnings + +# +# Create a table with two varchar(64) null-able column, +# using current values of +# @@character_set_connection and @@collation_connection. +# + +create table t1 as +select repeat(' ', 64) as s1, repeat(' ',64) as s2 +union +select null, null; +show create table t1; +delete from t1; + +insert into t1 values('aaa','aaa'); +insert into t1 values('aaa|qqq','qqq'); +insert into t1 values('gheis','^[^a-dXYZ]+$'); +insert into t1 values('aab','^aa?b'); +insert into t1 values('Baaan','^Ba*n'); +insert into t1 values('aaa','qqq|aaa'); +insert into t1 values('qqq','qqq|aaa'); + +insert into t1 values('bbb','qqq|aaa'); +insert into t1 values('bbb','qqq'); +insert into t1 values('aaa','aba'); + +insert into t1 values(null,'abc'); +insert into t1 values('def',null); +insert into t1 values(null,null); +insert into t1 values('ghi','ghi['); + +select HIGH_PRIORITY s1 regexp s2 from t1; + +drop table t1; diff --git a/mysql-test/include/gis_keys.inc b/mysql-test/include/gis_keys.inc index 295e0c48234..c75311f062a 100644 --- a/mysql-test/include/gis_keys.inc +++ b/mysql-test/include/gis_keys.inc @@ -13,20 +13,20 @@ CREATE TABLE t2 (p POINT, INDEX(p)); INSERT INTO t1 VALUES (POINTFROMTEXT('POINT(1 2)')); INSERT INTO t2 VALUES (POINTFROMTEXT('POINT(1 2)')); --- no index, returns 1 as expected +# no index, returns 1 as expected SELECT COUNT(*) FROM t1 WHERE p=POINTFROMTEXT('POINT(1 2)'); --- with index, returns 1 as expected --- EXPLAIN shows that the index is not used though --- due to the "most rows covered anyway, so a scan is more effective" rule +# with index, returns 1 as expected +# EXPLAIN shows that the index is not used though +# due to the "most rows covered anyway, so a scan is more effective" rule EXPLAIN SELECT COUNT(*) FROM t2 WHERE p=POINTFROMTEXT('POINT(1 2)'); SELECT COUNT(*) FROM t2 WHERE p=POINTFROMTEXT('POINT(1 2)'); --- adding another row to the table so that --- the "most rows covered" rule doesn't kick in anymore --- now EXPLAIN shows the index used on the table --- and we're getting the wrong result again +# adding another row to the table so that +# the "most rows covered" rule doesn't kick in anymore +# now EXPLAIN shows the index used on the table +# and we're getting the wrong result again INSERT INTO t1 VALUES (POINTFROMTEXT('POINT(1 2)')); INSERT INTO t2 VALUES (POINTFROMTEXT('POINT(1 2)')); EXPLAIN diff --git a/mysql-test/include/handler.inc b/mysql-test/include/handler.inc index 79e21382d4c..485b2e881d3 100644 --- a/mysql-test/include/handler.inc +++ b/mysql-test/include/handler.inc @@ -598,3 +598,97 @@ handler a2 read a last; handler a2 read a prev; handler a2 close; drop table t1; + +# +# Bug#31397 Inconsistent drop table behavior of handler tables. +# + +--disable_warnings +drop table if exists t1,t2; +--enable_warnings +create table t1 (a int); +handler t1 open as t1_alias; +drop table t1; +create table t1 (a int); +handler t1 open as t1_alias; +flush tables; +drop table t1; +create table t1 (a int); +handler t1 open as t1_alias; +handler t1_alias close; +drop table t1; +create table t1 (a int); +handler t1 open as t1_alias; +handler t1_alias read first; +drop table t1; +--error ER_UNKNOWN_TABLE +handler t1_alias read next; + +# Test that temporary tables associated with handlers are properly dropped. + +create table t1 (a int); +create temporary table t2 (a int, key(a)); +handler t1 open as a1; +handler t2 open as a2; +handler a2 read a first; +drop table t1, t2; +--error ER_UNKNOWN_TABLE +handler a2 read a next; +--error ER_UNKNOWN_TABLE +handler a1 close; + +# Alter table drop handlers + +create table t1 (a int, key(a)); +create table t2 like t1; +handler t1 open as a1; +handler t2 open as a2; +handler a1 read a first; +handler a2 read a first; +alter table t1 add b int; +--error ER_UNKNOWN_TABLE +handler a1 close; +handler a2 close; +drop table t1, t2; + +# Rename table drop handlers + +create table t1 (a int, key(a)); +handler t1 open as a1; +handler a1 read a first; +rename table t1 to t2; +--error ER_UNKNOWN_TABLE +handler a1 read a first; +drop table t2; + +# Optimize table drop handlers + +create table t1 (a int, key(a)); +create table t2 like t1; +handler t1 open as a1; +handler t2 open as a2; +handler a1 read a first; +handler a2 read a first; +optimize table t1; +--error ER_UNKNOWN_TABLE +handler a1 close; +handler a2 close; +drop table t1, t2; + +# Flush tables causes handlers reopen + +create table t1 (a int, b char(1), key a(a), key b(a,b)); +insert into t1 values (0,"a"),(1,"b"),(2,"c"),(3,"d"),(4,"e"), + (5,"f"),(6,"g"),(7,"h"),(8,"i"),(9,"j"); +handler t1 open; +handler t1 read a first; +handler t1 read a next; +flush tables; +handler t1 read a next; +handler t1 read a next; +flush tables with read lock; +handler t1 read a next; +unlock tables; +drop table t1; +--error ER_UNKNOWN_TABLE +handler t1 read a next; diff --git a/mysql-test/include/innodb_rollback_on_timeout.inc b/mysql-test/include/innodb_rollback_on_timeout.inc index 73c7374c79e..6be47397e4b 100644 --- a/mysql-test/include/innodb_rollback_on_timeout.inc +++ b/mysql-test/include/innodb_rollback_on_timeout.inc @@ -2,6 +2,10 @@ # Bug #24200: Provide backwards compatibility mode for 4.x "rollback on # transaction timeout" # +--disable_warnings +drop table if exists t1; +--enable_warnings + show variables like 'innodb_rollback_on_timeout'; create table t1 (a int unsigned not null primary key) engine = innodb; insert into t1 values (1); diff --git a/mysql-test/include/mix1.inc b/mysql-test/include/mix1.inc index d55b404621d..e695e7d5570 100644 --- a/mysql-test/include/mix1.inc +++ b/mysql-test/include/mix1.inc @@ -1069,6 +1069,15 @@ DROP TABLE t1; ########################################################################### +# +# Bug #31137: Assertion failed: primary_key_no == -1 || primary_key_no == 0 +# +create table t1(a char(10) not null, unique key aa(a(1)), + b char(4) not null, unique key bb(b(4))) engine=innodb; +desc t1; +show create table t1; +drop table t1; + --echo End of 5.0 tests # Fix for BUG#19243 "wrong LAST_INSERT_ID() after ON DUPLICATE KEY @@ -1212,7 +1221,7 @@ CREATE TABLE t1 (a INT PRIMARY KEY, b VARCHAR(256)) ENGINE = $engine_type; INSERT INTO t1 VALUES (1,2); ---#echo 1. test for locking: +--echo # 1. test for locking: BEGIN; --enable_info @@ -1353,4 +1362,12 @@ if ($test_foreign_keys) DROP TABLE t1; } +# +# Bug #26447: "ALTER TABLE .. ORDER" does not work with InnoDB and +# auto_increment keys +# +create table t1 (a int auto_increment primary key) engine=innodb; +alter table t1 order by a; +drop table t1; + --echo End of 5.1 tests diff --git a/mysql-test/include/partition_1.inc b/mysql-test/include/partition_1.inc deleted file mode 100644 index b0094db2efe..00000000000 --- a/mysql-test/include/partition_1.inc +++ /dev/null @@ -1,750 +0,0 @@ --- source include/have_partition.inc - -# include/partition_1.inc -# -# Partitionong tests -# -# Attention: The variable -# $engine -- Storage engine to be tested. -# must be set within the script sourcing this file. -# ---disable_abort_on_error -SET AUTOCOMMIT= 1; - -##### Disabled testcases, because of open bugs ##### ---echo ---echo #------------------------------------------------------------------------ ---echo # There are several testcases disabled because ouf the open bugs ---echo # #15407 , #15408 , #15890 , #15961 , #13447 , #15966 , #15968, #16370 ---echo #------------------------------------------------------------------------ -# Bug#15407 Partitions: crash if subpartition -let $fixed_bug15407= 0; -# Bug#15408 Partitions: subpartition names are not unique -let $fixed_bug15408= 0; -# Bug#15890 Partitions: Strange interpretation of partition number -let $fixed_bug15890= 0; -# Bug#15961 Partitions: Creation of subpart. table without subpart. rule not rejected -let $fixed_bug15961= 0; -# Bug#13447 Partitions: crash with alter table -let $fixed_bug13447= 0; -# Bug#15966 Partitions: crash if session default engine <> engine used in create table -let $fixed_bug15966= 0; -# Bug#15968 Partitions: crash when INSERT with f1 = -1 into PARTITION BY HASH(f1) -let $fixed_bug15968= 0; -# Bug #16370 Partitions: subpartitions names not mentioned in SHOW CREATE TABLE output -let $fixed_bug16370= 0; - -##### Option, for displaying files ##### -# -# Attention: Displaying the directory content via "ls $MYSQLTEST_VARDIR/master-data/test/t*" -# is probably not portable. -# let $ls= 0; disables the execution of "ls ....." -let $ls= 0; - -################################################################################ -# Partitioning syntax -# -# CREATE TABLE .... (column-list ..) -# PARTITION BY -# KEY '(' ( column-list ) ')' -# | RANGE '(' ( expr ) ')' -# | LIST '(' ( expr ) ')' -# | HASH '(' ( expr ) ')' -# [PARTITIONS num ] -# [SUBPARTITION BY -# KEY '(' ( column-list ) ')' -# | HASH '(' ( expr ) ')' -# [SUBPARTITIONS num ] -# ] -# [ '(' -# ( PARTITION logical-name -# [ VALUES LESS THAN '(' ( expr | MAX_VALUE ) ')' ] -# [ VALUES IN '(' (expr)+ ')' ] -# [ TABLESPACE tablespace-name ] -# [ [ STORAGE ] ENGINE [ '=' ] storage-engine-name ] -# [ NODEGROUP nodegroup-id ] -# [ '(' -# ( SUBPARTITION logical-name -# [ TABLESPACE tablespace-name ] -# [ STORAGE ENGINE = storage-engine-name ] -# [ NODEGROUP nodegroup-id ] -# )+ -# ')' -# )+ -# ')' -# ] -################################################################################ - ---echo ---echo #------------------------------------------------------------------------ ---echo # 0. Setting of auxiliary variables + Creation of an auxiliary table ---echo # needed in all testcases ---echo #------------------------------------------------------------------------ -let $max_row= `SELECT @max_row`; -let $max_row_div2= `SELECT @max_row DIV 2`; -let $max_row_div3= `SELECT @max_row DIV 3`; -let $max_row_div4= `SELECT @max_row DIV 4`; -let $max_int_4= 2147483647; ---disable_warnings -DROP TABLE IF EXISTS t0_template; ---enable_warnings -CREATE TABLE t0_template ( f1 INTEGER, f2 char(20), PRIMARY KEY(f1)) -ENGINE = MEMORY; ---echo # Logging of INSERTs into t0_template suppressed ---disable_query_log -let $num= $max_row; -while ($num) -{ - eval INSERT INTO t0_template SET f1 = $num, f2 = '---$num---'; - - dec $num; -} ---enable_query_log - ---echo ---echo #------------------------------------------------------------------------ ---echo # 1. Some syntax checks ---echo #------------------------------------------------------------------------ ---echo # 1.1 Subpartioned table without subpartitioning rule must be rejected ---disable_warnings -DROP TABLE IF EXISTS t1; ---enable_warnings -if ($fixed_bug15961) -{ -# Bug#15961 Partitions: Creation of subpart. table without subpart. rule not rejected ---error 9999 -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY RANGE(f1) -( PARTITION part1 VALUES LESS THAN (1000) (SUBPARTITION subpart11)); -} ---echo # FIXME Implement testcases, where it is checked that all create and ---echo # alter table statements ---echo # - with missing mandatory parameters are rejected ---echo # - with optional parameters are accepted ---echo # - with wrong combinations of optional parameters are rejected ---echo # - ............ - ---echo ---echo #------------------------------------------------------------------------ ---echo # 2. Checks where the engine is assigned on all supported (CREATE TABLE ---echo # statement) positions + basic operations on the tables ---echo # Storage engine mixups are currently (2005-12-23) not supported ---echo #------------------------------------------------------------------------ ---disable_warnings -DROP TABLE IF EXISTS t1; ---enable_warnings - ---echo # 2.1 non partitioned table (for comparison) -eval CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) ENGINE = $engine; -# MLML Full size (as check of check routine) ---source include/partition_10.inc -DROP TABLE t1; -# ---echo # 2.2 Assignment of storage engine just after column list only -eval CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) ENGINE = $engine - PARTITION BY HASH(f1) PARTITIONS 2; ---source include/partition_10.inc -DROP TABLE t1; -# ---echo # 2.3 Assignment of storage engine just after partition or subpartition ---echo # name only -eval CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) - PARTITION BY HASH(f1) - ( PARTITION part1 STORAGE ENGINE = $engine, - PARTITION part2 STORAGE ENGINE = $engine - ); ---source include/partition_10.inc -DROP TABLE t1; -eval CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) - PARTITION BY RANGE(f1) - SUBPARTITION BY HASH(f1) - ( PARTITION part1 VALUES LESS THAN ($max_row_div2) - (SUBPARTITION subpart11 STORAGE ENGINE = $engine, - SUBPARTITION subpart12 STORAGE ENGINE = $engine), - PARTITION part2 VALUES LESS THAN ($max_int_4) - (SUBPARTITION subpart21 STORAGE ENGINE = $engine, - SUBPARTITION subpart22 STORAGE ENGINE = $engine) - ); ---source include/partition_10.inc -DROP TABLE t1; -# ---echo # 2.4 Some but not all named partitions or subpartitions get a storage ---echo # engine assigned -eval CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) - PARTITION BY HASH(f1) - ( PARTITION part1 STORAGE ENGINE = $engine, - PARTITION part2 - ); ---source include/partition_10.inc -DROP TABLE t1; -eval CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) - PARTITION BY HASH(f1) - ( PARTITION part1 , - PARTITION part2 STORAGE ENGINE = $engine - ); ---source include/partition_10.inc -DROP TABLE t1; -eval CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) - PARTITION BY RANGE(f1) - SUBPARTITION BY HASH(f1) - ( PARTITION part1 VALUES LESS THAN ($max_row_div2) - (SUBPARTITION subpart11, - SUBPARTITION subpart12 STORAGE ENGINE = $engine), - PARTITION part2 VALUES LESS THAN ($max_int_4) - (SUBPARTITION subpart21 STORAGE ENGINE = $engine, - SUBPARTITION subpart22 STORAGE ENGINE = $engine) - ); ---source include/partition_10.inc -DROP TABLE t1; -eval CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) - PARTITION BY RANGE(f1) - SUBPARTITION BY HASH(f1) - ( PARTITION part1 VALUES LESS THAN ($max_row_div2) - (SUBPARTITION subpart11 STORAGE ENGINE = $engine, - SUBPARTITION subpart12 STORAGE ENGINE = $engine), - PARTITION part2 VALUES LESS THAN ($max_int_4) - (SUBPARTITION subpart21, - SUBPARTITION subpart22 ) - ); ---source include/partition_10.inc -DROP TABLE t1; -# ---echo # 2.5 Storage engine assignment after partition name + after name of ---echo # subpartitions belonging to another partition -eval CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) - PARTITION BY RANGE(f1) - SUBPARTITION BY HASH(f1) - ( PARTITION part1 VALUES LESS THAN ($max_row_div2) ENGINE = $engine - (SUBPARTITION subpart11, - SUBPARTITION subpart12), - PARTITION part2 VALUES LESS THAN ($max_int_4) - (SUBPARTITION subpart21 STORAGE ENGINE = $engine, - SUBPARTITION subpart22 STORAGE ENGINE = $engine) - ); ---source include/partition_10.inc -DROP TABLE t1; -eval CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) - PARTITION BY RANGE(f1) - SUBPARTITION BY HASH(f1) - ( PARTITION part1 VALUES LESS THAN ($max_row_div2) - (SUBPARTITION subpart11 STORAGE ENGINE = $engine, - SUBPARTITION subpart12 STORAGE ENGINE = $engine), - PARTITION part2 VALUES LESS THAN ($max_int_4) ENGINE = $engine - (SUBPARTITION subpart21, - SUBPARTITION subpart22) - ); ---source include/partition_10.inc -DROP TABLE t1; -# ---echo # 2.6 Precedence of storage engine assignments ---echo # 2.6.1 Storage engine assignment after column list + after partition ---echo # or subpartition name -eval CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) ENGINE = $engine - PARTITION BY HASH(f1) - ( PARTITION part1 STORAGE ENGINE = $engine, - PARTITION part2 STORAGE ENGINE = $engine - ); ---source include/partition_10.inc -DROP TABLE t1; -eval CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) ENGINE = $engine - PARTITION BY RANGE(f1) - SUBPARTITION BY HASH(f1) - ( PARTITION part1 VALUES LESS THAN ($max_row_div2) - (SUBPARTITION subpart11 STORAGE ENGINE = $engine, - SUBPARTITION subpart12 STORAGE ENGINE = $engine), - PARTITION part2 VALUES LESS THAN ($max_int_4) - (SUBPARTITION subpart21 STORAGE ENGINE = $engine, - SUBPARTITION subpart22 STORAGE ENGINE = $engine) - ); ---source include/partition_10.inc -DROP TABLE t1; ---echo # 2.6.2 Storage engine assignment after partition name + after ---echo # subpartition name -# in partition part + in sub partition part -eval CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) - PARTITION BY RANGE(f1) - SUBPARTITION BY HASH(f1) - ( PARTITION part1 VALUES LESS THAN ($max_row_div2) STORAGE ENGINE = $engine - (SUBPARTITION subpart11 STORAGE ENGINE = $engine, - SUBPARTITION subpart12 STORAGE ENGINE = $engine), - PARTITION part2 VALUES LESS THAN ($max_int_4) - (SUBPARTITION subpart21 STORAGE ENGINE = $engine, - SUBPARTITION subpart22 STORAGE ENGINE = $engine) - ); ---source include/partition_10.inc -DROP TABLE t1; - ---echo # 2.7 Session default engine differs from engine used within create table -eval SET SESSION storage_engine=$engine_other; -if ($fixed_bug15966) -{ -# Bug#15966 Partitions: crash if session default engine <> engine used in create table -eval CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY HASH(f1) ( PARTITION part1 ENGINE = $engine); ---source include/partition_10.inc -DROP TABLE t1; -# Bug#15966 Partitions: crash if session default engine <> engine used in create table -eval CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) - PARTITION BY RANGE(f1) - SUBPARTITION BY HASH(f1) - ( PARTITION part1 VALUES LESS THAN (1000) - (SUBPARTITION subpart11 STORAGE ENGINE = $engine, - SUBPARTITION subpart12 STORAGE ENGINE = $engine)); ---source include/partition_10.inc -DROP TABLE t1; -} -eval SET SESSION storage_engine=$engine; - - ---echo ---echo #------------------------------------------------------------------------ ---echo # 3. Check assigning the number of partitions and subpartitions ---echo # with and without named partitions/subpartitions ---echo #------------------------------------------------------------------------ ---disable_warnings -DROP TABLE IF EXISTS t1; ---enable_warnings ---echo # 3.1 (positive) without partition/subpartition number assignment ---echo # 3.1.1 no partition number, no named partitions -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY HASH(f1); ---source include/partition_10.inc -DROP TABLE t1; ---echo # 3.1.2 no partition number, named partitions -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY HASH(f1) (PARTITION part1, PARTITION part2); ---source include/partition_10.inc -DROP TABLE t1; -# Attention: Several combinations are impossible -# If subpartitioning exists -# - partitioning algorithm must be RANGE or LIST -# This implies the assignment of named partitions. -# - subpartitioning algorithm must be HASH or KEY ---echo # 3.1.3 variations on no partition/subpartition number, named partitions, ---echo # different subpartitions are/are not named -# -# Partition name -- "properties" -# part1 -- first/non last -# part2 -- non first/non last -# part3 -- non first/ last -# -# Testpattern: -# named subpartitions in -# Partition part1 part2 part3 -# N N N -# N N Y -# N Y N -# N Y Y -# Y N N -# Y N Y -# Y Y N -# Y Y Y ---disable_query_log -let $part0= CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY RANGE(f1) SUBPARTITION BY HASH(f1); -# -eval SET @aux = '(PARTITION part1 VALUES LESS THAN ($max_row_div2),'; -let $part1_N= `SELECT @AUX`; -eval SET @aux = '(PARTITION part1 VALUES LESS THAN ($max_row_div2) -(SUBPARTITION subpart11 , SUBPARTITION subpart12 ),'; -let $part1_Y= `SELECT @AUX`; -# -eval SET @aux = 'PARTITION part2 VALUES LESS THAN ($max_row),'; -let $part2_N= `SELECT @AUX`; -eval SET @aux = 'PARTITION part2 VALUES LESS THAN ($max_row) -(SUBPARTITION subpart21 , SUBPARTITION subpart22 ),'; -let $part2_Y= `SELECT @AUX`; -# -eval SET @aux = 'PARTITION part3 VALUES LESS THAN ($max_int_4))'; -let $part3_N= `SELECT @AUX`; -eval SET @aux = 'PARTITION part3 VALUES LESS THAN ($max_int_4) -(SUBPARTITION subpart31 , SUBPARTITION subpart32 ))'; -let $part3_Y= `SELECT @AUX`; ---enable_query_log - -eval $part0 $part1_N $part2_N $part3_N ; -DROP TABLE t1; -# Bug#15407 Partitions: crash if subpartition -if ($fixed_bug15407) -{ -eval $part0 $part1_N $part2_N $part3_Y ; ---source include/partition_10.inc -DROP TABLE t1; -eval $part0 $part1_N $part2_Y $part3_N ; ---source include/partition_10.inc -DROP TABLE t1; -eval $part0 $part1_N $part2_Y $part3_Y ; ---source include/partition_10.inc -DROP TABLE t1; -eval $part0 $part1_Y $part2_N $part3_N ; ---source include/partition_10.inc -DROP TABLE t1; -eval $part0 $part1_Y $part2_N $part3_Y ; ---source include/partition_10.inc -DROP TABLE t1; -eval $part0 $part1_Y $part2_Y $part3_N ; ---source include/partition_10.inc -DROP TABLE t1; -} -eval $part0 $part1_Y $part2_Y $part3_Y ; ---source include/partition_10.inc -DROP TABLE t1; - ---echo # 3.2 partition/subpartition numbers good and bad values and notations ---disable_warnings -DROP TABLE IF EXISTS t1; ---enable_warnings ---echo # 3.2.1 partition/subpartition numbers INTEGER notation -# ML: "positive/negative" is my private judgement. It need no to correspond -# with the server response. -# (positive) number = 2 -let $part_number= 2; ---source include/partition_11.inc -# (positive) special case number = 1 -let $part_number= 1; ---source include/partition_11.inc -# (negative) 0 is non sense -let $part_number= 0; ---source include/partition_11.inc -# (negative) -1 is non sense -let $part_number= -1; ---source include/partition_11.inc -# (negative) 1000000 is too huge -let $part_number= 1000000; ---source include/partition_11.inc - -if ($fixed_bug15890) -{ ---echo # 3.2.2 partition/subpartition numbers DECIMAL notation -# (positive) number = 2.0 -let $part_number= 2.0; ---source include/partition_11.inc -# (negative) -2.0 is non sense -let $part_number= -2.0; ---source include/partition_11.inc -# (negative) case number = 0.0 is non sense -let $part_number= 0.0; ---source include/partition_11.inc -# Bug#15890 Partitions: Strange interpretation of partition number -# (negative) number = 1.5 is non sense -let $part_number= 1.5; ---source include/partition_11.inc -# (negative) number is too huge -let $part_number= 999999999999999999999999999999.999999999999999999999999999999; ---source include/partition_11.inc -# (negative) number is nearly zero -let $part_number= 0.000000000000000000000000000001; ---source include/partition_11.inc - ---echo # 3.2.3 partition/subpartition numbers FLOAT notation -##### FLOAT notation -# (positive) number = 2.0E+0 -let $part_number= 2.0E+0; ---source include/partition_11.inc -# Bug#15890 Partitions: Strange interpretation of partition number -# (positive) number = 0.2E+1 -let $part_number= 0.2E+1; ---source include/partition_11.inc -# (negative) -2.0E+0 is non sense -let $part_number= -2.0E+0; ---source include/partition_11.inc -# (negative) 0.15E+1 is non sense -let $part_number= 0.15E+1; ---source include/partition_11.inc -# (negative) 0.0E+300 is zero -let $part_number= 0.0E+300; ---source include/partition_11.inc -# Bug#15890 Partitions: Strange interpretation of partition number -# (negative) 1E+300 is too huge -let $part_number= 1E+300; ---source include/partition_11.inc -# (negative) 1E-300 is nearly zero -let $part_number= 1E-300; ---source include/partition_11.inc -} - ---echo # 3.2.4 partition/subpartition numbers STRING notation -##### STRING notation -# (negative?) case number = '2' -let $part_number= '2'; ---source include/partition_11.inc -# (negative?) case number = '2.0' -let $part_number= '2.0'; ---source include/partition_11.inc -# (negative?) case number = '0.2E+1' -let $part_number= '0.2E+1'; ---source include/partition_11.inc -# (negative) Strings starts with digit, but 'A' follows -let $part_number= '2A'; ---source include/partition_11.inc -# (negative) Strings starts with 'A', but digit follows -let $part_number= 'A2'; ---source include/partition_11.inc -# (negative) empty string -let $part_number= ''; ---source include/partition_11.inc -# (negative) string without any digits -let $part_number= 'GARBAGE'; ---source include/partition_11.inc - ---echo # 3.2.5 partition/subpartition numbers other notations -# (negative) Strings starts with digit, but 'A' follows -let $part_number= 2A; ---source include/partition_11.inc -# (negative) Strings starts with 'A', but digit follows -let $part_number= A2; ---source include/partition_11.inc -# (negative) string without any digits -let $part_number= GARBAGE; ---source include/partition_11.inc - -# (negative?) double quotes -let $part_number= "2"; ---source include/partition_11.inc -# (negative) Strings starts with digit, but 'A' follows -let $part_number= "2A"; ---source include/partition_11.inc -# (negative) Strings starts with 'A', but digit follows -let $part_number= "A2"; ---source include/partition_11.inc -# (negative) string without any digits -let $part_number= "GARBAGE"; ---source include/partition_11.inc - ---echo # 3.3 Mixups of assigned partition/subpartition numbers and names ---echo # 3.3.1 (positive) number of partition/subpartition ---echo # = number of named partition/subpartition -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY HASH(f1) PARTITIONS 2 ( PARTITION part1, PARTITION part2 ) ; -SHOW CREATE TABLE t1; -DROP TABLE t1; -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY RANGE(f1) PARTITIONS 2 -SUBPARTITION BY HASH(f1) SUBPARTITIONS 2 -( PARTITION part1 VALUES LESS THAN (1000) - (SUBPARTITION subpart11, SUBPARTITION subpart12), - PARTITION part2 VALUES LESS THAN (2147483647) - (SUBPARTITION subpart21, SUBPARTITION subpart22) -); ---source include/partition_layout.inc -DROP TABLE t1; ---echo # 3.3.2 (positive) number of partition/subpartition , ---echo # 0 (= no) named partition/subpartition ---echo # already checked above ---echo # 3.3.3 (negative) number of partitions/subpartitions ---echo # > number of named partitions/subpartitions ---error 1064 -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY HASH(f1) PARTITIONS 2 ( PARTITION part1 ) ; -# Wrong number of named subpartitions in first partition ---error 1064 -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY RANGE(f1) -SUBPARTITION BY HASH(f1) SUBPARTITIONS 2 -( PARTITION part1 VALUES LESS THAN (1000) - (SUBPARTITION subpart11 ), - PARTITION part2 VALUES LESS THAN (2147483647) - (SUBPARTITION subpart21, SUBPARTITION subpart22) -); -# Wrong number of named subpartitions in non first/non last partition ---error 1064 -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY RANGE(f1) -SUBPARTITION BY HASH(f1) SUBPARTITIONS 2 -( PARTITION part1 VALUES LESS THAN (1000) - (SUBPARTITION subpart11, SUBPARTITION subpart12), - PARTITION part2 VALUES LESS THAN (2000) - (SUBPARTITION subpart21 ), - PARTITION part3 VALUES LESS THAN (2147483647) - (SUBPARTITION subpart31, SUBPARTITION subpart32) -); -# Wrong number of named subpartitions in last partition ---error 1064 -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY RANGE(f1) PARTITIONS 2 -SUBPARTITION BY HASH(f1) SUBPARTITIONS 2 -( PARTITION part1 VALUES LESS THAN (1000) - (SUBPARTITION subpart11, SUBPARTITION subpart12), - PARTITION part2 VALUES LESS THAN (2147483647) - (SUBPARTITION subpart21 ) -); ---echo # 3.3.4 (negative) number of partitions < number of named partitions ---error 1064 -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY HASH(f1) PARTITIONS 1 ( PARTITION part1, PARTITION part2 ) ; -# Wrong number of named subpartitions in first partition ---error 1064 -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY RANGE(f1) -SUBPARTITION BY HASH(f1) SUBPARTITIONS 1 -( PARTITION part1 VALUES LESS THAN (1000) - (SUBPARTITION subpart11, SUBPARTITION subpart12), - PARTITION part2 VALUES LESS THAN (2147483647) - (SUBPARTITION subpart21, SUBPARTITION subpart22) -); -# Wrong number of named subpartitions in non first/non last partition ---error 1064 -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY RANGE(f1) -SUBPARTITION BY HASH(f1) SUBPARTITIONS 1 -( PARTITION part1 VALUES LESS THAN (1000) - (SUBPARTITION subpart11, SUBPARTITION subpart12), - PARTITION part2 VALUES LESS THAN (2000) - (SUBPARTITION subpart21 ), - PARTITION part3 VALUES LESS THAN (2147483647) - (SUBPARTITION subpart31, SUBPARTITION subpart32) -); -# Wrong number of named subpartitions in last partition ---error 1064 -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY RANGE(f1) -SUBPARTITION BY HASH(f1) SUBPARTITIONS 1 -( PARTITION part1 VALUES LESS THAN (1000) - (SUBPARTITION subpart11, SUBPARTITION subpart12), - PARTITION part2 VALUES LESS THAN (2147483647) - (SUBPARTITION subpart21, SUBPARTITION subpart22) -); - - ---echo ---echo #------------------------------------------------------------------------ ---echo # 4. Checks of logical partition/subpartition name ---echo # file name clashes during CREATE TABLE ---echo #------------------------------------------------------------------------ ---disable_warnings -DROP TABLE IF EXISTS t1; ---enable_warnings - ---echo # 4.1 (negative) A partition name used more than once ---error ER_SAME_NAME_PARTITION -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY HASH(f1) (PARTITION part1, PARTITION part1); -# -if ($fixed_bug15408) -{ -# Bug#15408 Partitions: subpartition names are not unique ---error ER_SAME_NAME_PARTITION -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY RANGE(f1) -SUBPARTITION BY HASH(f1) -( PARTITION part1 VALUES LESS THAN (1000) - (SUBPARTITION subpart11, SUBPARTITION subpart11) -); -} ---echo # FIXME Implement testcases with filename problems ---echo # existing file of other table --- partition/subpartition file name ---echo # partition/subpartition file name --- file of the same table - ---echo ---echo #------------------------------------------------------------------------ ---echo # 5. Alter table experiments ---echo #------------------------------------------------------------------------ ---disable_warnings -DROP TABLE IF EXISTS t1; ---enable_warnings ---echo # 5.1 alter table add partition ---echo # 5.1.1 (negative) add partition to non partitioned table -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)); ---source include/partition_layout.inc -# MyISAM gets ER_PARTITION_MGMT_ON_NONPARTITIONED and NDB 1005 -# The error code of NDB differs, because all NDB tables are partitioned even -# if the CREATE TABLE does not contain a partitioning clause. ---error ER_PARTITION_MGMT_ON_NONPARTITIONED,1005 -ALTER TABLE t1 ADD PARTITION (PARTITION part1); ---source include/partition_layout.inc -DROP TABLE t1; - ---echo # 5.1.2 Add one partition to a table with one partition -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY HASH(f1); ---source include/partition_layout.inc -eval INSERT INTO t1 SELECT * FROM t0_template WHERE f1 BETWEEN 1 AND $max_row_div2 - 1; ---disable_query_log -eval SELECT $engine = 'NDB' INTO @aux; -let $my_exit= `SELECT @aux`; -if ($my_exit) -{ - exit; -} ---enable_query_log -ALTER TABLE t1 ADD PARTITION (PARTITION part1); ---source include/partition_12.inc -DROP TABLE t1; - ---echo # 5.1.3 Several times add one partition to a table with some partitions -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY HASH(f1) (PARTITION part1, PARTITION part3); ---source include/partition_layout.inc -eval INSERT INTO t1 SELECT * FROM t0_template WHERE f1 BETWEEN 1 AND $max_row_div2 - 1; -# Partition name before first existing partition name -ALTER TABLE t1 ADD PARTITION (PARTITION part0); ---source include/partition_12.inc -DELETE FROM t1; -eval INSERT INTO t1 SELECT * FROM t0_template WHERE f1 BETWEEN 1 AND $max_row_div2 - 1; -# Partition name between existing partition names -ALTER TABLE t1 ADD PARTITION (PARTITION part2); ---source include/partition_12.inc -DELETE FROM t1; -eval INSERT INTO t1 SELECT * FROM t0_template WHERE f1 BETWEEN 1 AND $max_row_div2 - 1; -if ($fixed_bug13447) -{ -# Partition name after all existing partition names -# Bug#13447 Partitions: crash with alter table -ALTER TABLE t1 ADD PARTITION (PARTITION part4); -} ---source include/partition_12.inc -DROP TABLE t1; - ---echo # 5.1.4 Add several partitions to a table with some partitions -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY HASH(f1) (PARTITION part1, PARTITION part3); ---source include/partition_layout.inc -eval INSERT INTO t1 SELECT * FROM t0_template WHERE f1 BETWEEN 1 AND $max_row_div2 - 1; -if ($fixed_bug13447) -{ -# Bug#13447 Partitions: crash with alter table -ALTER TABLE t1 ADD PARTITION (PARTITION part0, PARTITION part2, PARTITION part4); -} ---source include/partition_12.inc -DROP TABLE t1; - ---echo # 5.1.5 (negative) Add partitions to a table with some partitions ---echo # clash on new and already existing partition names -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY HASH(f1) (PARTITION part1, PARTITION part2, PARTITION part3); -# Clash on first/non last partition name ---error ER_SAME_NAME_PARTITION -ALTER TABLE t1 ADD PARTITION (PARTITION part1); -# Clash on non first/non last partition name ---error ER_SAME_NAME_PARTITION -ALTER TABLE t1 ADD PARTITION (PARTITION part2); -# Clash on non first/last partition name ---error ER_SAME_NAME_PARTITION -ALTER TABLE t1 ADD PARTITION (PARTITION part3); -# Clash on all partition names ---error ER_SAME_NAME_PARTITION -ALTER TABLE t1 ADD PARTITION (PARTITION part1, PARTITION part2, PARTITION part3); -DROP TABLE t1; - -# FIXME Is there any way to add a subpartition to an already existing partition - ---echo # 5.2 alter table add subpartition ---echo # 5.2.1 Add one subpartition to a table with subpartitioning rule and ---echo # no explicit defined subpartitions -eval CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY RANGE(f1) -SUBPARTITION BY HASH(f1) -(PARTITION part1 VALUES LESS THAN ($max_row_div2)); -if ($fixed_bug16370) -{ ---source include/partition_layout.inc -} -eval INSERT INTO t1 SELECT * FROM t0_template WHERE f1 BETWEEN 1 AND $max_row_div2 - 1; -eval ALTER TABLE t1 ADD PARTITION (PARTITION part2 VALUES LESS THAN ($max_int_4) - (SUBPARTITION subpart21)); -if ($fixed_bug16370) -{ ---source include/partition_12.inc -} -DROP TABLE t1; -DROP TABLE if exists t0_template; diff --git a/mysql-test/include/reset_master_and_slave.inc b/mysql-test/include/reset_master_and_slave.inc new file mode 100644 index 00000000000..c2d4120ddc9 --- /dev/null +++ b/mysql-test/include/reset_master_and_slave.inc @@ -0,0 +1,10 @@ +--echo **** Resetting master and slave **** +connection slave; +STOP SLAVE; +source include/wait_for_slave_to_stop.inc; +RESET SLAVE; +connection master; +RESET MASTER; +connection slave; +START SLAVE; +source include/wait_for_slave_to_start.inc; diff --git a/mysql-test/include/wait_for_slave_sql_error.inc b/mysql-test/include/wait_for_slave_sql_error.inc new file mode 100644 index 00000000000..6780edbe2f0 --- /dev/null +++ b/mysql-test/include/wait_for_slave_sql_error.inc @@ -0,0 +1,33 @@ +################################################### +#Author: Sven +#Date: 2007-10-09 +#Purpose: Wait until the slave has an error in the +# sql thread, as indicated by +# "SHOW SLAVE STATUS", or at most 30 +# seconds. +#Details: +# 1) Fill in and setup variables +# 2) loop, looking for sql error on slave +# 3) If it loops too long, die. +#################################################### +connection slave; +let $row_number= 1; +let $run= 1; +let $counter= 300; + +while ($run) +{ + let $sql_result= query_get_value("SHOW SLAVE STATUS", Last_SQL_Errno, $row_number); + let $run= `SELECT '$sql_result' = '0'`; + if ($run) { + real_sleep 0.1; + if (!$counter){ + --echo "Failed while waiting for slave to produce an error in its sql thread" + --replace_result $MASTER_MYPORT MASTER_PORT + --replace_column 1 # 7 # 8 # 9 # 22 # 23 # 33 # + query_vertical SHOW SLAVE STATUS; + exit; + } + dec $counter; + } +} diff --git a/mysql-test/lib/mtr_cases.pl b/mysql-test/lib/mtr_cases.pl index 3d5752b4ec8..0d705104303 100644 --- a/mysql-test/lib/mtr_cases.pl +++ b/mysql-test/lib/mtr_cases.pl @@ -33,16 +33,14 @@ my $skip_test; sub init_pattern { my ($from, $what)= @_; - if ( $from =~ /[a-z0-9]/ ) { + if ( $from =~ /^[a-z0-9]$/ ) { # Does not contain any regex, make the pattern match # beginning of string $from= "^$from"; } - else { - # Check that pattern is a valid regex - eval { "" =~/$from/; 1 } or - mtr_error("Invalid regex '$from' passed to $what\nPerl says: $@"); - } + # Check that pattern is a valid regex + eval { "" =~/$from/; 1 } or + mtr_error("Invalid regex '$from' passed to $what\nPerl says: $@"); return $from; } @@ -214,17 +212,44 @@ sub collect_one_suite($$) mtr_verbose("Collecting: $suite"); + my $combination_file= "combinations"; + my $combinations = []; + my $suitedir= "$::glob_mysql_test_dir"; # Default + my $combination_file= "$::glob_mysql_test_dir/$combination_file"; if ( $suite ne "main" ) { $suitedir= mtr_path_exists("$suitedir/suite/$suite", "$suitedir/$suite"); mtr_verbose("suitedir: $suitedir"); + $combination_file= "$suitedir/$combination_file"; } my $testdir= "$suitedir/t"; my $resdir= "$suitedir/r"; + if (!@::opt_combination) + { + # Read combinations file + if ( open(COMB,$combination_file) ) + { + while () + { + chomp; + s/\ +/ /g; + push (@$combinations, $_) unless ($_ eq ''); + } + close COMB; + } + } + else + { + # take the combination from command-line + @$combinations = @::opt_combination; + } + # Remember last element position + my $begin_index = $#{@$cases} + 1; + # ---------------------------------------------------------------------- # Build a hash of disabled testcases for this suite # ---------------------------------------------------------------------- @@ -335,6 +360,78 @@ sub collect_one_suite($$) closedir TESTDIR; } + # ---------------------------------------------------------------------- + # Proccess combinations only if new tests were added + # ---------------------------------------------------------------------- + if (0 and $combinations && $begin_index <= $#{@$cases}) + { + my $end_index = $#{@$cases}; + my $is_copy; + # Keep original master/slave options + my @orig_opts; + for (my $idx = $begin_index; $idx <= $end_index; $idx++) + { + foreach my $param (('master_opt','slave_opt','slave_mi')) + { + @{$orig_opts[$idx]{$param}} = @{$cases->[$idx]->{$param}}; + } + } + my $comb_index = 1; + # Copy original test cases + foreach my $comb_set (@$combinations) + { + for (my $idx = $begin_index; $idx <= $end_index; $idx++) + { + my $test = $cases->[$idx]; + my $copied_test = {}; + foreach my $param (keys %{$test}) + { + # Scalar. Copy as is. + $copied_test->{$param} = $test->{$param}; + # Array. Copy reference instead itself + if ($param =~ /(master_opt|slave_opt|slave_mi)/) + { + my $new_arr = []; + @$new_arr = @{$orig_opts[$idx]{$param}}; + $copied_test->{$param} = $new_arr; + } + elsif ($param =~ /(comment|combinations)/) + { + $copied_test->{$param} = ''; + } + } + if ($is_copy) + { + push(@$cases, $copied_test); + $test = $cases->[$#{@$cases}]; + } + foreach my $comb_opt (split(/ /,$comb_set)) + { + push(@{$test->{'master_opt'}},$comb_opt); + push(@{$test->{'slave_opt'}},$comb_opt); + # Enable rpl if added option is --binlog-format and test case supports that + if ($comb_opt =~ /^--binlog-format=.+$/) + { + my @opt_pairs = split(/=/, $comb_opt); + if ($test->{'binlog_format'} =~ /^$opt_pairs[1]$/ || $test->{'binlog_format'} eq '') + { + $test->{'skip'} = 0; + $test->{'comment'} = ''; + } + else + { + $test->{'skip'} = 1; + $test->{'comment'} = "Requiring binlog format '$test->{'binlog_format'}'";; + } + } + } + $test->{'combination'} = $comb_set; + } + $is_copy = 1; + $comb_index++; + } + } + return $cases; } diff --git a/mysql-test/lib/mtr_report.pl b/mysql-test/lib/mtr_report.pl index 7cd6c1362b3..8b004a0c6c8 100644 --- a/mysql-test/lib/mtr_report.pl +++ b/mysql-test/lib/mtr_report.pl @@ -342,11 +342,19 @@ sub mtr_report_stats ($) { # BUG#29807 - innodb_mysql.test: Cannot find table test/t2 # from the internal data dictionary - /Cannot find table test\/bug29807 from the internal data dictionary/ or + /Cannot find or open table test\/bug29807 from/ or # BUG#29839 - lowercase_table3.test: Cannot find table test/T1 # from the internal data dictiona - /Cannot find table test\/BUG29839 from the internal data dictionary/ + /Cannot find table test\/BUG29839 from the internal data dictionary/ or + + # rpl_extrColmaster_*.test, the slave thread produces warnings + # when it get updates to a table that has more columns on the + # master + /Slave: Unknown column 'c7' in 't15' Error_code: 1054/ or + /Slave: Can't DROP 'c7'.* 1091/ or + /Slave: Key column 'c6'.* 1072/ + ) { next; # Skip these lines diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index c3312dce3ac..1a8c18f7d27 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -164,6 +164,8 @@ our $opt_bench= 0; our $opt_small_bench= 0; our $opt_big_test= 0; +our @opt_combination; + our @opt_extra_mysqld_opt; our $opt_compress; @@ -255,13 +257,13 @@ our $opt_timer= 1; our $opt_user; -our $opt_valgrind= 0; -our $opt_valgrind_mysqld= 0; -our $opt_valgrind_mysqltest= 0; -our $default_valgrind_options= "--show-reachable=yes"; -our $opt_valgrind_options; -our $opt_valgrind_path; -our $opt_callgrind; +my $opt_valgrind= 0; +my $opt_valgrind_mysqld= 0; +my $opt_valgrind_mysqltest= 0; +my @default_valgrind_args= ("--show-reachable=yes"); +my @valgrind_args; +my $opt_valgrind_path; +my $opt_callgrind; our $opt_stress= ""; our $opt_stress_suite= "main"; @@ -461,6 +463,19 @@ sub main () { # ############################################################################## +# +# When an option is no longer used by this program, it must be explicitly +# ignored or else it will be passed through to mysqld. GetOptions will call +# this subroutine once for each such option on the command line. See +# Getopt::Long documentation. +# + +sub warn_about_removed_option { + my ($option, $value, $hash_value) = @_; + + warn "WARNING: This option is no longer used, and is ignored: --$option\n"; +} + sub command_line_setup () { # These are defaults for things that are set on the command line @@ -497,6 +512,15 @@ sub command_line_setup () { # Read the command line # Note: Keep list, and the order, in sync with usage at end of this file + # Options that are no longer used must still be processed, because all + # unprocessed options are passed directly to mysqld. The user will be + # warned that the option is being ignored. + # + # Put the complete option string here. For example, to remove the --suite + # option, remove it from GetOptions() below and put 'suite|suites=s' here. + my @removed_options = ( + ); + Getopt::Long::Configure("pass_through"); GetOptions( # Control what engine/variation to run @@ -529,6 +553,7 @@ sub command_line_setup () { 'skip-im' => \$opt_skip_im, 'skip-test=s' => \$opt_skip_test, 'big-test' => \$opt_big_test, + 'combination=s' => \@opt_combination, # Specify ports 'master_port=i' => \$opt_master_myport, @@ -574,7 +599,18 @@ sub command_line_setup () { 'valgrind|valgrind-all' => \$opt_valgrind, 'valgrind-mysqltest' => \$opt_valgrind_mysqltest, 'valgrind-mysqld' => \$opt_valgrind_mysqld, - 'valgrind-options=s' => \$opt_valgrind_options, + 'valgrind-options=s' => sub { + my ($opt, $value)= @_; + # Deprecated option unless it's what we know pushbuild uses + if ($value eq "--gen-suppressions=all --show-reachable=yes") { + push(@valgrind_args, $_) for (split(' ', $value)); + return; + } + die("--valgrind-options=s is deprecated. Use ", + "--valgrind-option=s, to be specified several", + " times if necessary"); + }, + 'valgrind-option=s' => \@valgrind_args, 'valgrind-path=s' => \$opt_valgrind_path, 'callgrind' => \$opt_callgrind, @@ -614,6 +650,9 @@ sub command_line_setup () { 'suite-timeout=i' => \$opt_suite_timeout, 'warnings|log-warnings' => \$opt_warnings, + # Options which are no longer used + (map { $_ => \&warn_about_removed_option } @removed_options), + 'help|h' => \$opt_usage, ) or usage("Can't read options"); @@ -977,7 +1016,7 @@ sub command_line_setup () { # -------------------------------------------------------------------------- # Check valgrind arguments # -------------------------------------------------------------------------- - if ( $opt_valgrind or $opt_valgrind_path or defined $opt_valgrind_options) + if ( $opt_valgrind or $opt_valgrind_path or @valgrind_args) { mtr_report("Turning on valgrind for all executables"); $opt_valgrind= 1; @@ -1002,17 +1041,18 @@ sub command_line_setup () { $opt_valgrind_mysqld= 1; # Set special valgrind options unless options passed on command line - $opt_valgrind_options="--trace-children=yes" - unless defined $opt_valgrind_options; + push(@valgrind_args, "--trace-children=yes") + unless @valgrind_args; } if ( $opt_valgrind ) { # Set valgrind_options to default unless already defined - $opt_valgrind_options=$default_valgrind_options - unless defined $opt_valgrind_options; + push(@valgrind_args, @default_valgrind_args) + unless @valgrind_args; - mtr_report("Running valgrind with options \"$opt_valgrind_options\""); + mtr_report("Running valgrind with options \"", + join(" ", @valgrind_args), "\""); } if ( ! $opt_testcase_timeout ) @@ -2092,6 +2132,22 @@ sub environment_setup () { $ENV{'EXAMPLE_PLUGIN_OPT'}= ($lib_example_plugin ? "--plugin_dir=" . dirname($lib_example_plugin) : ""); + # ---------------------------------------------------- + # Setup env so childs can execute myisampack and myisamchk + # ---------------------------------------------------- + $ENV{'MYISAMCHK'}= mtr_native_path(mtr_exe_exists( + vs_config_dirs('storage/myisam', 'myisamchk'), + vs_config_dirs('myisam', 'myisamchk'), + "$path_client_bindir/myisamchk", + "$glob_basedir/storage/myisam/myisamchk", + "$glob_basedir/myisam/myisamchk")); + $ENV{'MYISAMPACK'}= mtr_native_path(mtr_exe_exists( + vs_config_dirs('storage/myisam', 'myisampack'), + vs_config_dirs('myisam', 'myisampack'), + "$path_client_bindir/myisampack", + "$glob_basedir/storage/myisam/myisampack", + "$glob_basedir/myisam/myisampack")); + # ---------------------------------------------------- # We are nice and report a bit about our settings # ---------------------------------------------------- @@ -3751,10 +3807,13 @@ sub mysqld_arguments ($$$$) { # see BUG#28359 mtr_add_arg($args, "%s--connect-timeout=60", $prefix); + # When mysqld is run by a root user(euid is 0), it will fail # to start unless we specify what user to run as. If not running # as root it will be ignored, see BUG#30630 - if (!(grep(/^--user/, @$extra_opt, @opt_extra_mysqld_opt))) { + my $euid= $>; + if (!$glob_win32 and $euid == 0 and + grep(/^--user/, @$extra_opt, @opt_extra_mysqld_opt) == 0) { mtr_add_arg($args, "%s--user=root"); } @@ -5054,7 +5113,7 @@ sub valgrind_arguments { } # Add valgrind options, can be overriden by user - mtr_add_arg($args, '%s', $opt_valgrind_options); + mtr_add_arg($args, '%s', $_) for (@valgrind_args); mtr_add_arg($args, $$exe); @@ -5141,6 +5200,8 @@ Options to control what test suites or cases to run skip-im Don't start IM, and skip the IM test cases big-test Set the environment variable BIG_TEST, which can be checked from test cases. + combination="ARG1 .. ARG2" Specify a set of "mysqld" arguments for one + combination. Options that specify ports @@ -5196,12 +5257,14 @@ Options for coverage, profiling etc gcov FIXME gprof FIXME valgrind Run the "mysqltest" and "mysqld" executables using - valgrind with options($default_valgrind_options) + valgrind with default options valgrind-all Synonym for --valgrind valgrind-mysqltest Run the "mysqltest" and "mysql_client_test" executable with valgrind valgrind-mysqld Run the "mysqld" executable with valgrind - valgrind-options=ARGS Options to give valgrind, replaces default options + valgrind-options=ARGS Deprecated, use --valgrind-option + valgrind-option=ARGS Option to give valgrind, replaces default option(s), + can be specified more then once valgrind-path=[EXE] Path to the valgrind executable callgrind Instruct valgrind to use callgrind diff --git a/mysql-test/r/almost_full.result b/mysql-test/r/almost_full.result new file mode 100644 index 00000000000..eb28f12fa51 --- /dev/null +++ b/mysql-test/r/almost_full.result @@ -0,0 +1,29 @@ +drop table if exists t1; +set global myisam_data_pointer_size=2; +CREATE TABLE t1 (a int auto_increment primary key not null, b longtext) ENGINE=MyISAM; +DELETE FROM t1 WHERE a=1 or a=5; +INSERT INTO t1 SET b=repeat('a',600); +ERROR HY000: The table 't1' is full +CHECK TABLE t1 EXTENDED; +Table Op Msg_type Msg_text +test.t1 check warning Datafile is almost full, 65448 of 65534 used +test.t1 check status OK +UPDATE t1 SET b=repeat('a', 800) where a=10; +ERROR HY000: The table 't1' is full +CHECK TABLE t1 EXTENDED; +Table Op Msg_type Msg_text +test.t1 check warning Datafile is almost full, 65448 of 65534 used +test.t1 check status OK +INSERT INTO t1 SET b=repeat('a',400); +CHECK TABLE t1 EXTENDED; +Table Op Msg_type Msg_text +test.t1 check warning Datafile is almost full, 65448 of 65534 used +test.t1 check status OK +DELETE FROM t1 WHERE a=2 or a=6; +UPDATE t1 SET b=repeat('a', 600) where a=11; +CHECK TABLE t1 EXTENDED; +Table Op Msg_type Msg_text +test.t1 check warning Datafile is almost full, 65448 of 65534 used +test.t1 check status OK +drop table t1; +set global myisam_data_pointer_size=default; diff --git a/mysql-test/r/analyze.result b/mysql-test/r/analyze.result index 7b476c3cca2..c3dbb846402 100644 --- a/mysql-test/r/analyze.result +++ b/mysql-test/r/analyze.result @@ -56,3 +56,11 @@ show index from t1; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment t1 1 a 1 a A 5 NULL NULL YES BTREE drop table t1; +End of 4.1 tests +create table t1(a int); +analyze table t1 extended; +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 'extended' at line 1 +optimize table t1 extended; +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 'extended' at line 1 +drop table t1; +End of 5.0 tests diff --git a/mysql-test/r/archive.result b/mysql-test/r/archive.result index 0a473a16771..edd49988a5f 100644 --- a/mysql-test/r/archive.result +++ b/mysql-test/r/archive.result @@ -2619,7 +2619,7 @@ auto fld1 companynr fld3 fld4 fld5 fld6 INSERT INTO t2 VALUES (2,011401,37,'breaking','dreaded','Steinberg','W'); INSERT INTO t2 VALUES (3,011402,37,'Romans','scholastics','jarring',''); INSERT INTO t2 VALUES (4,011403,37,'intercepted','audiology','tinily',''); -OPTIMIZE TABLE t2 EXTENDED; +OPTIMIZE TABLE t2; Table Op Msg_type Msg_text test.t2 optimize status OK SELECT * FROM t2; @@ -12683,3 +12683,7 @@ check table t1 extended; Table Op Msg_type Msg_text test.t1 check status OK drop table t1; +CREATE TABLE t1(a VARCHAR(510)) ENGINE = ARCHIVE; +INSERT INTO t1(a) VALUES (''); +SELECT * FROM t1 ORDER BY a; +DROP TABLE t1; diff --git a/mysql-test/r/bigint.result b/mysql-test/r/bigint.result index 0d6cf8e7d30..4a5b8fcf4aa 100644 --- a/mysql-test/r/bigint.result +++ b/mysql-test/r/bigint.result @@ -170,6 +170,12 @@ t2.value64=t1.value64; value64 value32 value64 value32 9223372036854775807 2 9223372036854775807 4 drop table t1, t2; +create table t1 (sint64 bigint not null); +insert into t1 values (-9223372036854775808); +select * from t1; +sint64 +-9223372036854775808 +drop table t1; create table t1 select 1 as 'a'; show create table t1; Table Create Table diff --git a/mysql-test/r/binlog_unsafe.result b/mysql-test/r/binlog_unsafe.result index 281bb475944..47284ed8bc3 100644 --- a/mysql-test/r/binlog_unsafe.result +++ b/mysql-test/r/binlog_unsafe.result @@ -5,9 +5,9 @@ CREATE TABLE t3 (b INT AUTO_INCREMENT PRIMARY KEY); CREATE VIEW v1(a,b) AS SELECT a,b FROM t2,t3; INSERT INTO t1 SELECT UUID(); Warnings: -Warning 1591 Statement is not safe to log in statement format. +Warning 1592 Statement is not safe to log in statement format. SHOW WARNINGS; Level Warning -Code 1591 +Code 1592 Message Statement is not safe to log in statement format. DROP TABLE t1,t2,t3; diff --git a/mysql-test/r/case.result b/mysql-test/r/case.result index 9ee64ee6dbd..d408a0b6153 100644 --- a/mysql-test/r/case.result +++ b/mysql-test/r/case.result @@ -1,4 +1,4 @@ -drop table if exists t1,t2; +drop table if exists t1, t2; select CASE "b" when "a" then 1 when "b" then 2 END; CASE "b" when "a" then 1 when "b" then 2 END 2 @@ -200,3 +200,21 @@ CEMPNUM EMPMUM1 EMPNUM2 0.00 0 0.00 2.00 2 NULL DROP TABLE t1,t2; +End of 4.1 tests +create table t1 (a int, b bigint unsigned); +create table t2 (c int); +insert into t1 (a, b) values (1,4572794622775114594), (2,18196094287899841997), +(3,11120436154190595086); +insert into t2 (c) values (1), (2), (3); +select t1.a, (case t1.a when 0 then 0 else t1.b end) d from t1 +join t2 on t1.a=t2.c order by d; +a d +1 4572794622775114594 +3 11120436154190595086 +2 18196094287899841997 +select t1.a, (case t1.a when 0 then 0 else t1.b end) d from t1 +join t2 on t1.a=t2.c where b=11120436154190595086 order by d; +a d +3 11120436154190595086 +drop table t1, t2; +End of 5.0 tests diff --git a/mysql-test/r/cast.result b/mysql-test/r/cast.result index afd0a5a990e..c1af92c5f8d 100644 --- a/mysql-test/r/cast.result +++ b/mysql-test/r/cast.result @@ -414,4 +414,28 @@ NULL NULL 20070719 drop table t1; +CREATE TABLE t1 (f1 DATE); +INSERT INTO t1 VALUES ('2007-07-19'), (NULL); +SELECT HOUR(f1), +MINUTE(f1), +SECOND(f1) FROM t1; +HOUR(f1) MINUTE(f1) SECOND(f1) +0 0 0 +NULL NULL NULL +SELECT HOUR(CAST('2007-07-19' AS DATE)), +MINUTE(CAST('2007-07-19' AS DATE)), +SECOND(CAST('2007-07-19' AS DATE)); +HOUR(CAST('2007-07-19' AS DATE)) MINUTE(CAST('2007-07-19' AS DATE)) SECOND(CAST('2007-07-19' AS DATE)) +0 0 0 +SELECT HOUR(CAST(NULL AS DATE)), +MINUTE(CAST(NULL AS DATE)), +SECOND(CAST(NULL AS DATE)); +HOUR(CAST(NULL AS DATE)) MINUTE(CAST(NULL AS DATE)) SECOND(CAST(NULL AS DATE)) +NULL NULL NULL +SELECT HOUR(NULL), +MINUTE(NULL), +SECOND(NULL); +HOUR(NULL) MINUTE(NULL) SECOND(NULL) +NULL NULL NULL +DROP TABLE t1; End of 5.0 tests diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result index ca3b344af53..73a9dba4e69 100644 --- a/mysql-test/r/create.result +++ b/mysql-test/r/create.result @@ -594,7 +594,7 @@ create table t1 (a int); create table t1 select * from t1; ERROR HY000: You can't specify target table 't1' for update in FROM clause create table t2 union = (t1) select * from t1; -ERROR HY000: You can't specify target table 't1' for update in FROM clause +ERROR HY000: 'test.t2' is not BASE TABLE flush tables with read lock; unlock tables; drop table t1; diff --git a/mysql-test/r/ctype_euckr.result b/mysql-test/r/ctype_euckr.result index b9619370d4c..ee786202c01 100644 --- a/mysql-test/r/ctype_euckr.result +++ b/mysql-test/r/ctype_euckr.result @@ -178,3 +178,44 @@ hex(a) A2E6 FEF7 DROP TABLE t1; +create table t1 (s1 varchar(5) character set euckr); +insert into t1 values (0xA141); +insert into t1 values (0xA15A); +insert into t1 values (0xA161); +insert into t1 values (0xA17A); +insert into t1 values (0xA181); +insert into t1 values (0xA1FE); +insert into t1 values (0xA140); +Warnings: +Warning 1366 Incorrect string value: '\xA1@' for column 's1' at row 1 +insert into t1 values (0xA15B); +Warnings: +Warning 1366 Incorrect string value: '\xA1[' for column 's1' at row 1 +insert into t1 values (0xA160); +Warnings: +Warning 1366 Incorrect string value: '\xA1`' for column 's1' at row 1 +insert into t1 values (0xA17B); +Warnings: +Warning 1366 Incorrect string value: '\xA1{' for column 's1' at row 1 +insert into t1 values (0xA180); +Warnings: +Warning 1366 Incorrect string value: '\xA1\x80' for column 's1' at row 1 +insert into t1 values (0xA1FF); +Warnings: +Warning 1366 Incorrect string value: '\xA1\xFF' for column 's1' at row 1 +select hex(s1), hex(convert(s1 using utf8)) from t1 order by binary s1; +hex(s1) hex(convert(s1 using utf8)) + + + + + + +A141 ECA2A5 +A15A ECA381 +A161 ECA382 +A17A ECA3A5 +A181 ECA3A6 +A1FE EFBFA2 +drop table t1; +End of 5.0 tests diff --git a/mysql-test/r/ctype_uca.result b/mysql-test/r/ctype_uca.result index e676d5a5ca0..3fff9b9cda8 100644 --- a/mysql-test/r/ctype_uca.result +++ b/mysql-test/r/ctype_uca.result @@ -2767,4 +2767,49 @@ a c ch drop table t1; +set collation_connection=ucs2_unicode_ci; +drop table if exists t1; +create table t1 as +select repeat(' ', 64) as s1, repeat(' ',64) as s2 +union +select null, null; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `s1` varchar(64) CHARACTER SET ucs2 COLLATE ucs2_unicode_ci DEFAULT NULL, + `s2` varchar(64) CHARACTER SET ucs2 COLLATE ucs2_unicode_ci DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +delete from t1; +insert into t1 values('aaa','aaa'); +insert into t1 values('aaa|qqq','qqq'); +insert into t1 values('gheis','^[^a-dXYZ]+$'); +insert into t1 values('aab','^aa?b'); +insert into t1 values('Baaan','^Ba*n'); +insert into t1 values('aaa','qqq|aaa'); +insert into t1 values('qqq','qqq|aaa'); +insert into t1 values('bbb','qqq|aaa'); +insert into t1 values('bbb','qqq'); +insert into t1 values('aaa','aba'); +insert into t1 values(null,'abc'); +insert into t1 values('def',null); +insert into t1 values(null,null); +insert into t1 values('ghi','ghi['); +select HIGH_PRIORITY s1 regexp s2 from t1; +s1 regexp s2 +1 +1 +1 +1 +1 +1 +1 +0 +0 +0 +NULL +NULL +NULL +NULL +drop table t1; +set names utf8; End for 5.0 tests diff --git a/mysql-test/r/ctype_ucs.result b/mysql-test/r/ctype_ucs.result index a0a8455b496..bd76f2a859f 100644 --- a/mysql-test/r/ctype_ucs.result +++ b/mysql-test/r/ctype_ucs.result @@ -811,6 +811,20 @@ quote(name) ???????? ???????????????? drop table bug20536; +set names ucs2; +ERROR 42000: Variable 'character_set_client' can't be set to the value of 'ucs2' +set names ucs2 collate ucs2_bin; +ERROR 42000: Variable 'character_set_client' can't be set to the value of 'ucs2' +set character_set_client= ucs2; +ERROR 42000: Variable 'character_set_client' can't be set to the value of 'ucs2' +set character_set_client= concat('ucs', substr('2', 1)); +ERROR 42000: Variable 'character_set_client' can't be set to the value of 'ucs2' +CREATE TABLE t1(a TEXT CHARSET ucs2 COLLATE ucs2_unicode_ci); +INSERT INTO t1 VALUES('abcd'); +SELECT * FROM t1 WHERE MATCH(a) AGAINST ('+abcd' IN BOOLEAN MODE); +a +abcd +DROP TABLE t1; End of 4.1 tests CREATE TABLE t1 (a varchar(64) character set ucs2, b decimal(10,3)); INSERT INTO t1 VALUES ("1.1", 0), ("2.1", 0); @@ -922,6 +936,51 @@ ERROR HY000: Illegal mix of collations (ascii_general_ci,IMPLICIT) and (ucs2_gen select * from t1 where a=if(b<10,_ucs2 0x0062,_ucs2 0x00C0); ERROR HY000: Illegal mix of collations (ascii_general_ci,IMPLICIT) and (ucs2_general_ci,COERCIBLE) for operation '=' drop table t1; +set collation_connection=ucs2_general_ci; +drop table if exists t1; +create table t1 as +select repeat(' ', 64) as s1, repeat(' ',64) as s2 +union +select null, null; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `s1` varchar(64) CHARACTER SET ucs2 DEFAULT NULL, + `s2` varchar(64) CHARACTER SET ucs2 DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +delete from t1; +insert into t1 values('aaa','aaa'); +insert into t1 values('aaa|qqq','qqq'); +insert into t1 values('gheis','^[^a-dXYZ]+$'); +insert into t1 values('aab','^aa?b'); +insert into t1 values('Baaan','^Ba*n'); +insert into t1 values('aaa','qqq|aaa'); +insert into t1 values('qqq','qqq|aaa'); +insert into t1 values('bbb','qqq|aaa'); +insert into t1 values('bbb','qqq'); +insert into t1 values('aaa','aba'); +insert into t1 values(null,'abc'); +insert into t1 values('def',null); +insert into t1 values(null,null); +insert into t1 values('ghi','ghi['); +select HIGH_PRIORITY s1 regexp s2 from t1; +s1 regexp s2 +1 +1 +1 +1 +1 +1 +1 +0 +0 +0 +NULL +NULL +NULL +NULL +drop table t1; +set names latin1; select hex(char(0x41 using ucs2)); hex(char(0x41 using ucs2)) 0041 diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index 8243b2bc015..5c90c3b5e0b 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -267,6 +267,51 @@ b select * from t1 where a = 'b' and a != 'b'; a drop table t1; +set collation_connection=utf8_general_ci; +drop table if exists t1; +create table t1 as +select repeat(' ', 64) as s1, repeat(' ',64) as s2 +union +select null, null; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `s1` varchar(64) CHARACTER SET utf8 DEFAULT NULL, + `s2` varchar(64) CHARACTER SET utf8 DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +delete from t1; +insert into t1 values('aaa','aaa'); +insert into t1 values('aaa|qqq','qqq'); +insert into t1 values('gheis','^[^a-dXYZ]+$'); +insert into t1 values('aab','^aa?b'); +insert into t1 values('Baaan','^Ba*n'); +insert into t1 values('aaa','qqq|aaa'); +insert into t1 values('qqq','qqq|aaa'); +insert into t1 values('bbb','qqq|aaa'); +insert into t1 values('bbb','qqq'); +insert into t1 values('aaa','aba'); +insert into t1 values(null,'abc'); +insert into t1 values('def',null); +insert into t1 values(null,null); +insert into t1 values('ghi','ghi['); +select HIGH_PRIORITY s1 regexp s2 from t1; +s1 regexp s2 +1 +1 +1 +1 +1 +1 +1 +0 +0 +0 +NULL +NULL +NULL +NULL +drop table t1; +set names utf8; set names utf8; select 'ваÑÑ' rlike '[[:<:]]ваÑÑ[[:>:]]'; 'ваÑÑ' rlike '[[:<:]]ваÑÑ[[:>:]]' diff --git a/mysql-test/r/delayed.result b/mysql-test/r/delayed.result index c520ab52ab3..95f7fe5aa61 100644 --- a/mysql-test/r/delayed.result +++ b/mysql-test/r/delayed.result @@ -73,13 +73,13 @@ a 13 DROP TABLE t1; SET @bug20627_old_auto_increment_offset= -@@auto_increment_offset= 2; +@@auto_increment_offset; SET @bug20627_old_auto_increment_increment= -@@auto_increment_increment= 3; +@@auto_increment_increment; SET @bug20627_old_session_auto_increment_offset= -@@session.auto_increment_offset= 4; +@@session.auto_increment_offset; SET @bug20627_old_session_auto_increment_increment= -@@session.auto_increment_increment= 5; +@@session.auto_increment_increment; SET @@auto_increment_offset= 2; SET @@auto_increment_increment= 3; SET @@session.auto_increment_offset= 4; @@ -116,13 +116,13 @@ SET @@session.auto_increment_offset= SET @@session.auto_increment_increment= @bug20627_old_session_auto_increment_increment; SET @bug20830_old_auto_increment_offset= -@@auto_increment_offset= 2; +@@auto_increment_offset; SET @bug20830_old_auto_increment_increment= -@@auto_increment_increment= 3; +@@auto_increment_increment; SET @bug20830_old_session_auto_increment_offset= -@@session.auto_increment_offset= 4; +@@session.auto_increment_offset; SET @bug20830_old_session_auto_increment_increment= -@@session.auto_increment_increment= 5; +@@session.auto_increment_increment; SET @@auto_increment_offset= 2; SET @@auto_increment_increment= 3; SET @@session.auto_increment_offset= 4; @@ -250,11 +250,6 @@ SELECT HEX(a) FROM t1; HEX(a) 1 DROP TABLE t1; -CREATE TABLE t1(c1 INT) ENGINE=MyISAM; -CREATE TABLE t2(c1 INT) ENGINE=MERGE UNION=(t1); -INSERT DELAYED INTO t2 VALUES(1); -ERROR HY000: Table storage engine for 't2' doesn't have this option -DROP TABLE t1, t2; DROP TABLE IF EXISTS t1,t2; SET SQL_MODE='NO_AUTO_VALUE_ON_ZERO'; CREATE TABLE `t1` ( diff --git a/mysql-test/r/events_bugs.result b/mysql-test/r/events_bugs.result index b6b77101874..b91e7e88d64 100644 --- a/mysql-test/r/events_bugs.result +++ b/mysql-test/r/events_bugs.result @@ -3,6 +3,10 @@ drop database if exists mysqltest_db1; drop database if exists mysqltest_db2; create database events_test; use events_test; +select * from information_schema.global_variables where variable_name like 'event_scheduler'; +VARIABLE_NAME VARIABLE_VALUE +EVENT_SCHEDULER ON +SET GLOBAL event_scheduler = 'OFF'; CREATE EVENT lower_case ON SCHEDULE EVERY 1 MINUTE DO SELECT 1; CREATE EVENT Lower_case ON SCHEDULE EVERY 2 MINUTE DO SELECT 2; ERROR HY000: Event 'Lower_case' already exists @@ -31,7 +35,7 @@ create event e_55 on schedule at 10000101000000 do drop table t; ERROR HY000: Incorrect AT value: '10000101000000' create event e_55 on schedule at 20000101000000 do drop table t; Warnings: -Note 1587 Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. The event was dropped immediately after creation. +Note 1588 Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. The event was dropped immediately after creation. show events; Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator character_set_client collation_connection Database Collation create event e_55 on schedule at 20200101000000 starts 10000101000000 do drop table t; @@ -457,22 +461,22 @@ CREATE EVENT e4 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00' DO SELECT 1; Warnings: -Note 1587 Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. The event was dropped immediately after creation. +Note 1588 Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. The event was dropped immediately after creation. CREATE EVENT e4 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00' ENDS '1999-01-02 00:00:00' DISABLE DO SELECT 1; Warnings: -Note 1587 Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. The event was dropped immediately after creation. +Note 1588 Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. The event was dropped immediately after creation. CREATE EVENT e4 ON SCHEDULE AT '1999-01-01 00:00:00' DO SELECT 1; Warnings: -Note 1587 Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. The event was dropped immediately after creation. +Note 1588 Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. The event was dropped immediately after creation. CREATE EVENT e4 ON SCHEDULE AT '1999-01-01 00:00:00' DISABLE DO SELECT 1; Warnings: -Note 1587 Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. The event was dropped immediately after creation. +Note 1588 Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. The event was dropped immediately after creation. SHOW EVENTS; Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator character_set_client collation_connection Database Collation events_test e1 root@localhost +05:00 RECURRING NULL 1 DAY 2006-01-01 00:00:00 NULL ENABLED 1 latin1 latin1_swedish_ci latin1_swedish_ci @@ -482,19 +486,19 @@ The following should succeed giving a warning. ALTER EVENT e1 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00' ENDS '1999-01-02 00:00:00' ON COMPLETION PRESERVE; Warnings: -Note 1543 Event execution time is in the past. Event has been disabled +Note 1544 Event execution time is in the past. Event has been disabled CREATE EVENT e4 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00' ENDS '1999-01-02 00:00:00' ON COMPLETION PRESERVE DO SELECT 1; Warnings: -Note 1543 Event execution time is in the past. Event has been disabled +Note 1544 Event execution time is in the past. Event has been disabled CREATE EVENT e5 ON SCHEDULE AT '1999-01-01 00:00:00' ON COMPLETION PRESERVE DO SELECT 1; Warnings: -Note 1543 Event execution time is in the past. Event has been disabled +Note 1544 Event execution time is in the past. Event has been disabled The following should succeed without warnings. ALTER EVENT e2 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00'; ALTER EVENT e3 ON SCHEDULE EVERY 1 HOUR STARTS '1999-01-01 00:00:00' diff --git a/mysql-test/r/events_trans.result b/mysql-test/r/events_trans.result index 984e22a2c1a..16ec64b4c50 100644 --- a/mysql-test/r/events_trans.result +++ b/mysql-test/r/events_trans.result @@ -63,7 +63,7 @@ begin work; insert into t1 (a) values ("OK: create event if not exists"); create event if not exists e1 on schedule every 2 day do select 2; Warnings: -Note 1536 Event 'e1' already exists +Note 1537 Event 'e1' already exists rollback work; select * from t1; a diff --git a/mysql-test/r/federated_server.result b/mysql-test/r/federated_server.result index 0905aabb075..32717b4f0e3 100644 --- a/mysql-test/r/federated_server.result +++ b/mysql-test/r/federated_server.result @@ -253,6 +253,14 @@ drop user guest_usage@localhost; drop user guest_select@localhost; drop table federated.t1; drop server 's1'; +create server 's1' foreign data wrapper 'mysql' options (port 3306); +alter server 's1' options +(host 'localhost', database '', user '', +password '', socket '', owner '', port 3306); +alter server 's1' options +(host 'localhost', database 'database1', user '', +password '', socket '', owner '', port 3306); +drop server 's1'; # End of 5.1 tests use test; create procedure p1 () @@ -262,7 +270,7 @@ DECLARE e INT DEFAULT 0; DECLARE i INT; DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET e = e + 1; SET i = sleep(5); -WHILE v < 20000 do +WHILE v < 10000 do CREATE SERVER s FOREIGN DATA WRAPPER mysql OPTIONS (USER 'Remote', HOST '192.168.1.106', DATABASE 'test'); diff --git a/mysql-test/r/flush.result b/mysql-test/r/flush.result index dcbffd6f7c8..f1b6c471943 100644 --- a/mysql-test/r/flush.result +++ b/mysql-test/r/flush.result @@ -55,6 +55,23 @@ flush tables with read lock; insert into t2 values(1); unlock tables; drop table t1, t2; +drop table if exists t1, t2; +set session low_priority_updates=1; +create table t1 (a int); +create table t2 (b int); +lock tables t1 write; +flush tables with read lock; +ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction +unlock tables; +lock tables t1 read, t2 write; +flush tables with read lock; +ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction +unlock tables; +lock tables t1 read; +flush tables with read lock; +unlock tables; +drop table t1, t2; +set session low_priority_updates=default; End of 5.0 tests set @old_general_log= @@general_log; set @old_read_only= @@read_only; diff --git a/mysql-test/r/fulltext.result b/mysql-test/r/fulltext.result index 96ebb9bf254..c3fa427127b 100644 --- a/mysql-test/r/fulltext.result +++ b/mysql-test/r/fulltext.result @@ -476,6 +476,12 @@ ALTER TABLE t1 DISABLE KEYS; SELECT * FROM t1 WHERE MATCH(a) AGAINST('test'); ERROR HY000: Can't find FULLTEXT index matching the column list DROP TABLE t1; +CREATE TABLE t1(a TEXT); +INSERT INTO t1 VALUES(' aaaaa aaaa'); +SELECT * FROM t1 WHERE MATCH(a) AGAINST ('"aaaa"' IN BOOLEAN MODE); +a + aaaaa aaaa +DROP TABLE t1; CREATE TABLE t1(a VARCHAR(20), FULLTEXT(a)); INSERT INTO t1 VALUES('Offside'),('City Of God'); SELECT a FROM t1 WHERE MATCH a AGAINST ('+city of*' IN BOOLEAN MODE); diff --git a/mysql-test/r/func_gconcat.result b/mysql-test/r/func_gconcat.result index 7ae7806baea..d257e526abf 100644 --- a/mysql-test/r/func_gconcat.result +++ b/mysql-test/r/func_gconcat.result @@ -867,4 +867,13 @@ select group_concat(distinct a, c order by a desc, c desc) from t1; group_concat(distinct a, c order by a desc, c desc) 31,11,10,01,00 drop table t1; +create table t1 (f1 char(20)); +insert into t1 values (''),(''); +select group_concat(distinct f1) from t1; +group_concat(distinct f1) + +select group_concat(f1) from t1; +group_concat(f1) +, +drop table t1; End of 5.0 tests diff --git a/mysql-test/r/func_group.result b/mysql-test/r/func_group.result index ce29d25b736..abf717091af 100644 --- a/mysql-test/r/func_group.result +++ b/mysql-test/r/func_group.result @@ -1378,4 +1378,24 @@ SELECT 1 FROM t1 GROUP BY (SELECT SLEEP(0) FROM t1 ORDER BY AVG(DISTINCT a) ); 1 1 DROP TABLE t1; +CREATE TABLE t1 (a int, b date NOT NULL, KEY k1 (a,b)); +SELECT MIN(b) FROM t1 WHERE a=1 AND b>'2007-08-01'; +MIN(b) +NULL +DROP TABLE t1; +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2),(3),(4); +SET SQL_MODE=ONLY_FULL_GROUP_BY; +SELECT a FROM t1 HAVING COUNT(*)>2; +ERROR 42000: Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP columns is illegal if there is no GROUP BY clause +SELECT COUNT(*), a FROM t1; +ERROR 42000: Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP columns is illegal if there is no GROUP BY clause +SET SQL_MODE=DEFAULT; +SELECT a FROM t1 HAVING COUNT(*)>2; +a +1 +SELECT COUNT(*), a FROM t1; +COUNT(*) a +4 1 +DROP TABLE t1; End of 5.0 tests diff --git a/mysql-test/r/func_misc.result b/mysql-test/r/func_misc.result index aa75cde0525..a7119090ec0 100644 --- a/mysql-test/r/func_misc.result +++ b/mysql-test/r/func_misc.result @@ -212,6 +212,12 @@ test SELECT NAME_CONST('test', 'test'); test test +create table t1 (a int not null); +insert into t1 values (-1), (-2); +select min(a) from t1 group by inet_ntoa(a); +min(a) +-2 +drop table t1; End of 5.0 tests select connection_id() > 0; connection_id() > 0 diff --git a/mysql-test/r/func_regexp.result b/mysql-test/r/func_regexp.result index 05e56f05457..9d85b1d3e7f 100644 --- a/mysql-test/r/func_regexp.result +++ b/mysql-test/r/func_regexp.result @@ -1,5 +1,17 @@ drop table if exists t1; -create table t1 (s1 char(64),s2 char(64)); +set names latin1; +drop table if exists t1; +create table t1 as +select repeat(' ', 64) as s1, repeat(' ',64) as s2 +union +select null, null; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `s1` varchar(64) DEFAULT NULL, + `s2` varchar(64) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +delete from t1; insert into t1 values('aaa','aaa'); insert into t1 values('aaa|qqq','qqq'); insert into t1 values('gheis','^[^a-dXYZ]+$'); diff --git a/mysql-test/r/func_set.result b/mysql-test/r/func_set.result index 5f6ddb020f2..4dd11cafdcd 100644 --- a/mysql-test/r/func_set.result +++ b/mysql-test/r/func_set.result @@ -73,3 +73,33 @@ find_in_set(binary 'a', 'A,B,C') select find_in_set('1','3,1,'); find_in_set('1','3,1,') 2 +End of 4.1 tests +SELECT INTERVAL(0.0, NULL); +INTERVAL(0.0, NULL) +1 +SELECT INTERVAL(0.0, CAST(NULL AS DECIMAL)); +INTERVAL(0.0, CAST(NULL AS DECIMAL)) +1 +SELECT INTERVAL(0.0, CAST(DATE(NULL) AS DECIMAL)); +INTERVAL(0.0, CAST(DATE(NULL) AS DECIMAL)) +1 +SELECT INTERVAL(0.0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INTERVAL(0.0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL) +8 +SELECT INTERVAL(0.0, CAST(NULL AS DECIMAL), CAST(NULL AS DECIMAL), +CAST(NULL AS DECIMAL), CAST(NULL AS DECIMAL), CAST(NULL AS DECIMAL), +CAST(NULL AS DECIMAL), CAST(NULL AS DECIMAL), CAST(NULL AS DECIMAL)); +INTERVAL(0.0, CAST(NULL AS DECIMAL), CAST(NULL AS DECIMAL), +CAST(NULL AS DECIMAL), CAST(NULL AS DECIMAL), CAST(NULL AS DECIMAL), +CAST(NULL AS DECIMAL), CAST(NULL AS DECIMAL), CAST(NULL AS DECIMAL)) +8 +SELECT INTERVAL(0.0, CAST(DATE(NULL) AS DECIMAL), CAST(DATE(NULL) AS DECIMAL), +CAST(DATE(NULL) AS DECIMAL), CAST(DATE(NULL) AS DECIMAL), +CAST(DATE(NULL) AS DECIMAL), CAST(DATE(NULL) AS DECIMAL), +CAST(DATE(NULL) AS DECIMAL), CAST(DATE(NULL) AS DECIMAL)); +INTERVAL(0.0, CAST(DATE(NULL) AS DECIMAL), CAST(DATE(NULL) AS DECIMAL), +CAST(DATE(NULL) AS DECIMAL), CAST(DATE(NULL) AS DECIMAL), +CAST(DATE(NULL) AS DECIMAL), CAST(DATE(NULL) AS DECIMAL), +CAST(DATE(NULL) AS DECIMAL), CAST(DATE(NULL) AS DECIMAL)) +8 +End of 5.0 tests diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index 78d86d3f342..6f6edd5112b 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -722,9 +722,9 @@ Warning 1265 Data truncated for column 'format(130,10)' at row 1 show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `bin(130)` varchar(64) NOT NULL DEFAULT '', - `oct(130)` varchar(64) NOT NULL DEFAULT '', - `conv(130,16,10)` varchar(64) NOT NULL DEFAULT '', + `bin(130)` varchar(64) DEFAULT NULL, + `oct(130)` varchar(64) DEFAULT NULL, + `conv(130,16,10)` varchar(64) DEFAULT NULL, `hex(130)` varchar(6) NOT NULL DEFAULT '', `char(130)` varbinary(4) NOT NULL DEFAULT '', `format(130,10)` varchar(4) NOT NULL DEFAULT '', @@ -1315,6 +1315,18 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 system NULL NULL NULL NULL 0 0.00 const row not found Warnings: Note 1003 select decode('',_latin1'zxcv') AS `enc` from `test`.`t1` +drop table t1; +create table t1 (a bigint not null)engine=myisam; +insert into t1 set a = 1024*1024*1024*4; +delete from t1 order by (inet_ntoa(a)) desc limit 10; +drop table t1; +create table t1 (a char(36) not null)engine=myisam; +insert ignore into t1 set a = ' '; +insert ignore into t1 set a = ' '; +select * from t1 order by (oct(a)); +a + + drop table t1; End of 4.1 tests create table t1 (d decimal default null); diff --git a/mysql-test/r/grant.result b/mysql-test/r/grant.result index 4e25ada43a0..c46f29b787f 100644 --- a/mysql-test/r/grant.result +++ b/mysql-test/r/grant.result @@ -529,7 +529,7 @@ Db char(64) NO PRI User char(16) NO PRI Table_name char(64) NO PRI Grantor char(77) NO MUL -Timestamp timestamp NO CURRENT_TIMESTAMP +Timestamp timestamp NO CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP Table_priv set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter','Create View','Show view','Trigger') NO Column_priv set('Select','Insert','Update','References') NO use test; @@ -1194,6 +1194,7 @@ ERROR 42000: SELECT command denied to user 'mysqltest_2'@'localhost' for table ' DROP DATABASE mysqltest1; DROP DATABASE mysqltest2; DROP USER mysqltest_1@localhost; +DROP USER mysqltest_2@localhost; use test; CREATE TABLE t1 (f1 int, f2 int); INSERT INTO t1 VALUES(1,1), (2,2); @@ -1213,6 +1214,7 @@ f1 f2 REVOKE UPDATE (f1) ON `test`.`t1` FROM 'mysqltest_1'@'localhost'; REVOKE SELECT ON `test`.* FROM 'mysqltest_1'@'localhost'; REVOKE ALL ON db27878.* FROM 'mysqltest_1'@'localhost'; +DROP USER mysqltest_1@localhost; DROP DATABASE db27878; use test; DROP TABLE t1; @@ -1226,3 +1228,61 @@ drop user юзер_юзер@localhost; grant select on test.* to очень_длинный_юзер@localhost; ERROR HY000: String 'очень_длинный_юзер' is too long for user name (should be no longer than 16) set names default; +create database mysqltest; +use mysqltest; +grant create on mysqltest.* to mysqltest@localhost; +create table t1 (i INT); +insert into t1 values (1); +ERROR 42000: INSERT command denied to user 'mysqltest'@'localhost' for table 't1' +create table t2 (i INT); +create table t4 (i INT); +grant select, insert on mysqltest.t2 to mysqltest@localhost; +grant insert on mysqltest.t4 to mysqltest@localhost; +grant create, insert on mysqltest.t5 to mysqltest@localhost; +grant create, insert on mysqltest.t6 to mysqltest@localhost; +flush privileges; +insert into t2 values (1); +create table if not exists t1 select * from t2; +ERROR 42000: INSERT command denied to user 'mysqltest'@'localhost' for table 't1' +create table if not exists t3 select * from t2; +ERROR 42000: INSERT command denied to user 'mysqltest'@'localhost' for table 't3' +create table if not exists t4 select * from t2; +Warnings: +Note 1050 Table 't4' already exists +create table if not exists t5 select * from t2; +create table t6 select * from t2; +create table t7 select * from t2; +ERROR 42000: INSERT command denied to user 'mysqltest'@'localhost' for table 't7' +create table t4 select * from t2; +ERROR 42S01: Table 't4' already exists +create table t1 select * from t2; +ERROR 42000: INSERT command denied to user 'mysqltest'@'localhost' for table 't1' +drop table t1,t2,t4,t5,t6; +revoke create on mysqltest.* from mysqltest@localhost; +revoke select, insert on mysqltest.t2 from mysqltest@localhost; +revoke insert on mysqltest.t4 from mysqltest@localhost; +revoke create, insert on mysqltest.t5 from mysqltest@localhost; +revoke create, insert on mysqltest.t6 from mysqltest@localhost; +drop user mysqltest@localhost; +drop database mysqltest; +use test; +FLUSH PRIVILEGES without procs_priv table. +RENAME TABLE mysql.procs_priv TO mysql.procs_gone; +FLUSH PRIVILEGES; +Warnings: +Error 1146 Table 'mysql.procs_priv' doesn't exist +Error 1548 Cannot load from mysql.mysql.procs_priv. The table is probably corrupted +Assigning privileges without procs_priv table. +CREATE DATABASE mysqltest1; +CREATE PROCEDURE mysqltest1.test() SQL SECURITY DEFINER +SELECT 1; +GRANT EXECUTE ON FUNCTION mysqltest1.test TO mysqltest_1@localhost; +ERROR 42S02: Table 'mysql.procs_priv' doesn't exist +GRANT ALL PRIVILEGES ON test.* TO mysqltest_1@localhost; +CALL mysqltest1.test(); +1 +1 +DROP DATABASE mysqltest1; +RENAME TABLE mysql.procs_gone TO mysql.procs_priv; +FLUSH PRIVILEGES; +End of 5.1 tests diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result index 7498267c91d..1472fdfdd7a 100644 --- a/mysql-test/r/group_by.result +++ b/mysql-test/r/group_by.result @@ -1064,6 +1064,71 @@ select t1.f1,t.* from t1, t1 t group by 1; ERROR 42000: 'test.t.f1' isn't in GROUP BY drop table t1; SET SQL_MODE = ''; +CREATE TABLE t1( +id INT AUTO_INCREMENT PRIMARY KEY, +c1 INT NOT NULL, +c2 INT NOT NULL, +UNIQUE KEY (c2,c1)); +INSERT INTO t1(c1,c2) VALUES (5,1), (4,1), (3,5), (2,3), (1,3); +SELECT * FROM t1 ORDER BY c1; +id c1 c2 +5 1 3 +4 2 3 +3 3 5 +2 4 1 +1 5 1 +SELECT * FROM t1 GROUP BY id ORDER BY c1; +id c1 c2 +5 1 3 +4 2 3 +3 3 5 +2 4 1 +1 5 1 +SELECT * FROM t1 GROUP BY id ORDER BY id DESC; +id c1 c2 +5 1 3 +4 2 3 +3 3 5 +2 4 1 +1 5 1 +SELECT * FROM t1 GROUP BY c2 ,c1, id ORDER BY c2, c1; +id c1 c2 +2 4 1 +1 5 1 +5 1 3 +4 2 3 +3 3 5 +SELECT * FROM t1 GROUP BY c2, c1, id ORDER BY c2 DESC, c1; +id c1 c2 +3 3 5 +5 1 3 +4 2 3 +2 4 1 +1 5 1 +SELECT * FROM t1 GROUP BY c2, c1, id ORDER BY c2 DESC, c1 DESC; +id c1 c2 +3 3 5 +4 2 3 +5 1 3 +1 5 1 +2 4 1 +SELECT * FROM t1 GROUP BY c2 ORDER BY c2, c1; +id c1 c2 +1 5 1 +4 2 3 +3 3 5 +SELECT * FROM t1 GROUP BY c2 ORDER BY c2 DESC, c1; +id c1 c2 +3 3 5 +4 2 3 +1 5 1 +SELECT * FROM t1 GROUP BY c2 ORDER BY c2 DESC, c1 DESC; +id c1 c2 +3 3 5 +4 2 3 +1 5 1 +DROP TABLE t1; +End of 5.0 tests CREATE TABLE t1 (a INT, b INT, PRIMARY KEY (a), KEY i2(a,b)); diff --git a/mysql-test/r/handler_innodb.result b/mysql-test/r/handler_innodb.result index d9a1a0aa12b..9d269f78d10 100644 --- a/mysql-test/r/handler_innodb.result +++ b/mysql-test/r/handler_innodb.result @@ -637,3 +637,94 @@ a b 8 i handler a2 close; drop table t1; +drop table if exists t1,t2; +create table t1 (a int); +handler t1 open as t1_alias; +drop table t1; +create table t1 (a int); +handler t1 open as t1_alias; +flush tables; +drop table t1; +create table t1 (a int); +handler t1 open as t1_alias; +handler t1_alias close; +drop table t1; +create table t1 (a int); +handler t1 open as t1_alias; +handler t1_alias read first; +a +drop table t1; +handler t1_alias read next; +ERROR 42S02: Unknown table 't1_alias' in HANDLER +create table t1 (a int); +create temporary table t2 (a int, key(a)); +handler t1 open as a1; +handler t2 open as a2; +handler a2 read a first; +a +drop table t1, t2; +handler a2 read a next; +ERROR 42S02: Unknown table 'a2' in HANDLER +handler a1 close; +ERROR 42S02: Unknown table 'a1' in HANDLER +create table t1 (a int, key(a)); +create table t2 like t1; +handler t1 open as a1; +handler t2 open as a2; +handler a1 read a first; +a +handler a2 read a first; +a +alter table t1 add b int; +handler a1 close; +ERROR 42S02: Unknown table 'a1' in HANDLER +handler a2 close; +drop table t1, t2; +create table t1 (a int, key(a)); +handler t1 open as a1; +handler a1 read a first; +a +rename table t1 to t2; +handler a1 read a first; +ERROR 42S02: Unknown table 'a1' in HANDLER +drop table t2; +create table t1 (a int, key(a)); +create table t2 like t1; +handler t1 open as a1; +handler t2 open as a2; +handler a1 read a first; +a +handler a2 read a first; +a +optimize table t1; +Table Op Msg_type Msg_text +test.t1 optimize status OK +handler a1 close; +ERROR 42S02: Unknown table 'a1' in HANDLER +handler a2 close; +drop table t1, t2; +create table t1 (a int, b char(1), key a(a), key b(a,b)); +insert into t1 values (0,"a"),(1,"b"),(2,"c"),(3,"d"),(4,"e"), +(5,"f"),(6,"g"),(7,"h"),(8,"i"),(9,"j"); +handler t1 open; +handler t1 read a first; +a b +0 a +handler t1 read a next; +a b +1 b +flush tables; +handler t1 read a next; +a b +0 a +handler t1 read a next; +a b +1 b +flush tables with read lock; +handler t1 read a next; +a b +0 a +unlock tables; +drop table t1; +handler t1 read a next; +ERROR 42S02: Unknown table 't1' in HANDLER diff --git a/mysql-test/r/handler_myisam.result b/mysql-test/r/handler_myisam.result index b42fdc864fe..0b27b07c4d2 100644 --- a/mysql-test/r/handler_myisam.result +++ b/mysql-test/r/handler_myisam.result @@ -637,3 +637,94 @@ a b 8 i handler a2 close; drop table t1; +drop table if exists t1,t2; +create table t1 (a int); +handler t1 open as t1_alias; +drop table t1; +create table t1 (a int); +handler t1 open as t1_alias; +flush tables; +drop table t1; +create table t1 (a int); +handler t1 open as t1_alias; +handler t1_alias close; +drop table t1; +create table t1 (a int); +handler t1 open as t1_alias; +handler t1_alias read first; +a +drop table t1; +handler t1_alias read next; +ERROR 42S02: Unknown table 't1_alias' in HANDLER +create table t1 (a int); +create temporary table t2 (a int, key(a)); +handler t1 open as a1; +handler t2 open as a2; +handler a2 read a first; +a +drop table t1, t2; +handler a2 read a next; +ERROR 42S02: Unknown table 'a2' in HANDLER +handler a1 close; +ERROR 42S02: Unknown table 'a1' in HANDLER +create table t1 (a int, key(a)); +create table t2 like t1; +handler t1 open as a1; +handler t2 open as a2; +handler a1 read a first; +a +handler a2 read a first; +a +alter table t1 add b int; +handler a1 close; +ERROR 42S02: Unknown table 'a1' in HANDLER +handler a2 close; +drop table t1, t2; +create table t1 (a int, key(a)); +handler t1 open as a1; +handler a1 read a first; +a +rename table t1 to t2; +handler a1 read a first; +ERROR 42S02: Unknown table 'a1' in HANDLER +drop table t2; +create table t1 (a int, key(a)); +create table t2 like t1; +handler t1 open as a1; +handler t2 open as a2; +handler a1 read a first; +a +handler a2 read a first; +a +optimize table t1; +Table Op Msg_type Msg_text +test.t1 optimize status Table is already up to date +handler a1 close; +ERROR 42S02: Unknown table 'a1' in HANDLER +handler a2 close; +drop table t1, t2; +create table t1 (a int, b char(1), key a(a), key b(a,b)); +insert into t1 values (0,"a"),(1,"b"),(2,"c"),(3,"d"),(4,"e"), +(5,"f"),(6,"g"),(7,"h"),(8,"i"),(9,"j"); +handler t1 open; +handler t1 read a first; +a b +0 a +handler t1 read a next; +a b +1 b +flush tables; +handler t1 read a next; +a b +0 a +handler t1 read a next; +a b +1 b +flush tables with read lock; +handler t1 read a next; +a b +0 a +unlock tables; +drop table t1; +handler t1 read a next; +ERROR 42S02: Unknown table 't1' in HANDLER diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result index 208509da9a7..72889fc6294 100644 --- a/mysql-test/r/information_schema.result +++ b/mysql-test/r/information_schema.result @@ -1142,11 +1142,13 @@ DROP FUNCTION func2; select column_type, group_concat(table_schema, '.', table_name), count(*) as num from information_schema.columns where table_schema='information_schema' and -(column_type = 'varchar(7)' or column_type = 'varchar(20)') +(column_type = 'varchar(7)' or column_type = 'varchar(20)' + or column_type = 'varchar(27)') group by column_type order by num; column_type group_concat(table_schema, '.', table_name) num +varchar(27) information_schema.COLUMNS 1 varchar(7) information_schema.ROUTINES,information_schema.VIEWS 2 -varchar(20) information_schema.COLUMNS,information_schema.FILES,information_schema.FILES,information_schema.PLUGINS,information_schema.PLUGINS,information_schema.PLUGINS,information_schema.PROFILING 7 +varchar(20) information_schema.FILES,information_schema.FILES,information_schema.FILES,information_schema.PLUGINS,information_schema.PLUGINS,information_schema.PLUGINS,information_schema.PROFILING 7 create table t1(f1 char(1) not null, f2 char(9) not null) default character set utf8; select CHARACTER_MAXIMUM_LENGTH, CHARACTER_OCTET_LENGTH from @@ -1608,4 +1610,9 @@ select * from `information_schema`.`VIEWS` where `TABLE_SCHEMA` = NULL; TABLE_CATALOG TABLE_SCHEMA TABLE_NAME VIEW_DEFINITION CHECK_OPTION IS_UPDATABLE DEFINER SECURITY_TYPE CHARACTER_SET_CLIENT COLLATION_CONNECTION select * from `information_schema`.`VIEWS` where `TABLE_NAME` = NULL; TABLE_CATALOG TABLE_SCHEMA TABLE_NAME VIEW_DEFINITION CHECK_OPTION IS_UPDATABLE DEFINER SECURITY_TYPE CHARACTER_SET_CLIENT COLLATION_CONNECTION +explain extended select 1 from information_schema.tables; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE tables ALL NULL NULL NULL NULL NULL NULL Skip_open_table; Scanned all databases +Warnings: +Note 1003 select 1 AS `1` from `information_schema`.`tables` End of 5.1 tests. diff --git a/mysql-test/r/information_schema_db.result b/mysql-test/r/information_schema_db.result index 2be2928001f..cb56fb3d5cc 100644 --- a/mysql-test/r/information_schema_db.result +++ b/mysql-test/r/information_schema_db.result @@ -142,7 +142,7 @@ Warnings: Warning 1356 View 'testdb_1.v7' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them show fields from testdb_1.v7; Field Type Null Key Default Extra -f1 null YES NULL +f1 char(4) YES NULL Warnings: Note 1449 There is no 'no_such_user'@'no_such_host' registered create table t3 (f1 char(4), f2 char(4)); @@ -162,7 +162,7 @@ View Create View character_set_client collation_connection v6 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `testdb_1`.`v6` AS select `testdb_1`.`t1`.`f1` AS `f1` from `testdb_1`.`t1` latin1 latin1_swedish_ci show fields from testdb_1.v7; Field Type Null Key Default Extra -f1 null YES NULL +f1 char(4) YES NULL Warnings: Note 1449 There is no 'no_such_user'@'no_such_host' registered show create view testdb_1.v7; @@ -190,7 +190,7 @@ show create view v4; ERROR HY000: EXPLAIN/SHOW can not be issued; lacking privileges for underlying table show fields from v4; Field Type Null Key Default Extra -f1 null YES NULL +f1 char(4) YES NULL f2 char(4) YES NULL show fields from v2; Field Type Null Key Default Extra diff --git a/mysql-test/r/innodb-semi-consistent.result b/mysql-test/r/innodb-semi-consistent.result new file mode 100644 index 00000000000..f1139390f20 --- /dev/null +++ b/mysql-test/r/innodb-semi-consistent.result @@ -0,0 +1,37 @@ +drop table if exists t1; +set session transaction isolation level read committed; +create table t1(a int not null) engine=innodb DEFAULT CHARSET=latin1; +insert into t1 values (1),(2),(3),(4),(5),(6),(7); +set autocommit=0; +select * from t1 where a=3 lock in share mode; +a +3 +set session transaction isolation level read committed; +set autocommit=0; +update t1 set a=10 where a=5; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +commit; +update t1 set a=10 where a=5; +select * from t1 where a=2 for update; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +select * from t1 where a=2 limit 1 for update; +a +2 +update t1 set a=11 where a=6; +update t1 set a=12 where a=2; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +update t1 set a=13 where a=1; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +commit; +update t1 set a=14 where a=1; +commit; +select * from t1; +a +14 +2 +3 +4 +10 +11 +7 +drop table t1; diff --git a/mysql-test/r/innodb-ucs2.result b/mysql-test/r/innodb-ucs2.result index a1c73c912b2..b6bff7d5f42 100644 --- a/mysql-test/r/innodb-ucs2.result +++ b/mysql-test/r/innodb-ucs2.result @@ -1,3 +1,4 @@ +drop table if exists t1, t2; create table t1 ( a int, b char(10), c char(10), filler char(10), primary key(a, b(2)), unique key (a, c(2)) ) character set utf8 engine = innodb; diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index d0b67e90afb..c04ec77846a 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -472,43 +472,6 @@ a b 3 3 drop table t1,t2; CREATE TABLE t1 ( -id int(11) NOT NULL auto_increment, -ggid varchar(32) binary DEFAULT '' NOT NULL, -email varchar(64) DEFAULT '' NOT NULL, -passwd varchar(32) binary DEFAULT '' NOT NULL, -PRIMARY KEY (id), -UNIQUE ggid (ggid) -) ENGINE=innodb; -insert into t1 (ggid,passwd) values ('test1','xxx'); -insert into t1 (ggid,passwd) values ('test2','yyy'); -insert into t1 (ggid,passwd) values ('test2','this will fail'); -ERROR 23000: Duplicate entry 'test2' for key 'ggid' -insert into t1 (ggid,id) values ('this will fail',1); -ERROR 23000: Duplicate entry '1' for key 'PRIMARY' -select * from t1 where ggid='test1'; -id ggid email passwd -1 test1 xxx -select * from t1 where passwd='xxx'; -id ggid email passwd -1 test1 xxx -select * from t1 where id=2; -id ggid email passwd -2 test2 yyy -replace into t1 (ggid,id) values ('this will work',1); -replace into t1 (ggid,passwd) values ('test2','this will work'); -update t1 set id=100,ggid='test2' where id=1; -ERROR 23000: Duplicate entry 'test2' for key 'ggid' -select * from t1; -id ggid email passwd -1 this will work -4 test2 this will work -select * from t1 where id=1; -id ggid email passwd -1 this will work -select * from t1 where id=999; -id ggid email passwd -drop table t1; -CREATE TABLE t1 ( user_name varchar(12), password text, subscribed char(1), @@ -962,7 +925,7 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 index NULL b 4 NULL # Using index explain select a,b from t1; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index NULL b 4 NULL # Using index +1 SIMPLE t1 index NULL PRIMARY 4 NULL # explain select a,b,c from t1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL # @@ -1086,6 +1049,19 @@ n d 1 30 2 20 drop table t1,t2; +drop table if exists t1, t2; +CREATE TABLE t1 (a int, PRIMARY KEY (a)); +CREATE TABLE t2 (a int, PRIMARY KEY (a)) ENGINE=InnoDB; +create trigger trg_del_t2 after delete on t2 for each row +insert into t1 values (1); +insert into t1 values (1); +insert into t2 values (1),(2); +delete t2 from t2; +ERROR 23000: Duplicate entry '1' for key 'PRIMARY' +select count(*) from t2 /* must be 2 as restored after rollback caused by the error */; +count(*) +2 +drop table t1, t2; create table t1 (a int, b int) engine=innodb; insert into t1 values(20,null); select t2.b, ifnull(t2.b,"this is null") from t1 as t2 left join t1 as t3 on @@ -1177,14 +1153,14 @@ UPDATE t1 set a=a+100 where b between 2 and 3 and a < 1000; SELECT * from t1; a b 1 1 -102 2 -103 3 4 4 5 5 6 6 7 7 8 8 9 9 +102 2 +103 3 drop table t1; CREATE TABLE t1 (a int not null primary key, b int not null, key (b)) engine=innodb; CREATE TABLE t2 (a int not null primary key, b int not null, key (b)) engine=innodb; @@ -1208,7 +1184,6 @@ a b update t1,t2 set t1.a=t1.a+100 where t1.a=101; select * from t1; a b -201 1 102 2 103 3 104 4 @@ -1220,10 +1195,11 @@ a b 110 10 111 11 112 12 +201 1 update t1,t2 set t1.b=t1.b+10 where t1.b=2; select * from t1; a b -201 1 +102 12 103 3 104 4 105 5 @@ -1233,34 +1209,34 @@ a b 109 9 110 10 111 11 -102 12 112 12 +201 1 update t1,t2 set t1.b=t1.b+2,t2.b=t1.b+10 where t1.b between 3 and 5 and t1.a=t2.a+100; select * from t1; a b -201 1 +102 12 103 5 104 6 -106 6 105 7 +106 6 107 7 108 8 109 9 110 10 111 11 -102 12 112 12 +201 1 select * from t2; a b 1 1 2 2 +3 13 +4 14 +5 15 6 6 7 7 8 8 9 9 -3 13 -4 14 -5 15 drop table t1,t2; CREATE TABLE t2 ( NEXT_T BIGINT NOT NULL PRIMARY KEY) ENGINE=MyISAM; CREATE TABLE t1 ( B_ID INTEGER NOT NULL PRIMARY KEY) ENGINE=InnoDB; @@ -1311,11 +1287,11 @@ insert into t1 (id) values (null),(null),(null),(null),(null); update t1 set fk=69 where fk is null order by id limit 1; SELECT * from t1; id fk +1 69 2 NULL 3 NULL 4 NULL 5 NULL -1 69 drop table t1; create table t1 (a int not null, b int not null, key (a)); insert into t1 values (1,1),(1,2),(1,3),(3,1),(3,2),(3,3),(3,1),(3,2),(3,3),(2,1),(2,2),(2,3); @@ -1754,10 +1730,10 @@ Variable_name Value Innodb_rows_deleted 70 show status like "Innodb_rows_inserted"; Variable_name Value -Innodb_rows_inserted 1083 +Innodb_rows_inserted 1082 show status like "Innodb_rows_updated"; Variable_name Value -Innodb_rows_updated 886 +Innodb_rows_updated 885 show status like "Innodb_row_lock_waits"; Variable_name Value Innodb_row_lock_waits 0 @@ -2444,8 +2420,8 @@ insert into t1 (b) values (1); replace into t1 (b) values (2), (1), (3); select * from t1; a b -3 1 2 2 +3 1 4 3 truncate table t1; insert into t1 (b) values (1); @@ -2454,8 +2430,8 @@ replace into t1 (b) values (1); replace into t1 (b) values (3); select * from t1; a b -3 1 2 2 +3 1 4 3 drop table t1; create table t1 (rowid int not null auto_increment, val int not null,primary @@ -3189,3 +3165,52 @@ c25 CHAR(255), c26 CHAR(255), c27 CHAR(255), c28 CHAR(255), c29 CHAR(255), c30 CHAR(255), c31 CHAR(255), c32 CHAR(255) ) ENGINE = InnoDB; ERROR 42000: Row size too large. The maximum row size for the used table type, not counting BLOBs, is 8126. You have to change some columns to TEXT or BLOBs +DROP TABLE IF EXISTS t1; +Warnings: +Note 1051 Unknown table 't1' +CREATE TABLE t1( +id BIGINT(20) NOT NULL AUTO_INCREMENT PRIMARY KEY +) ENGINE=InnoDB; +INSERT INTO t1 VALUES(-10); +SELECT * FROM t1; +id +-10 +INSERT INTO t1 VALUES(NULL); +SELECT * FROM t1; +id +-10 +1 +DROP TABLE t1; +SET TX_ISOLATION='read-committed'; +SET AUTOCOMMIT=0; +DROP TABLE IF EXISTS t1, t2; +Warnings: +Note 1051 Unknown table 't1' +Note 1051 Unknown table 't2' +CREATE TABLE t1 ( a int ) ENGINE=InnoDB; +CREATE TABLE t2 LIKE t1; +SELECT * FROM t2; +a +SET TX_ISOLATION='read-committed'; +SET AUTOCOMMIT=0; +INSERT INTO t1 VALUES (1); +COMMIT; +SELECT * FROM t1 WHERE a=1; +a +1 +SET TX_ISOLATION='read-committed'; +SET AUTOCOMMIT=0; +SELECT * FROM t2; +a +SET TX_ISOLATION='read-committed'; +SET AUTOCOMMIT=0; +INSERT INTO t1 VALUES (2); +COMMIT; +SELECT * FROM t1 WHERE a=2; +a +2 +SELECT * FROM t1 WHERE a=2; +a +2 +DROP TABLE t1; +DROP TABLE t2; diff --git a/mysql-test/r/innodb_autoinc_lock_mode_zero.result b/mysql-test/r/innodb_autoinc_lock_mode_zero.result new file mode 100644 index 00000000000..3d016684338 --- /dev/null +++ b/mysql-test/r/innodb_autoinc_lock_mode_zero.result @@ -0,0 +1,39 @@ +drop table if exists t1; +CREATE TABLE t1 ( +id int(11) NOT NULL auto_increment, +ggid varchar(32) binary DEFAULT '' NOT NULL, +email varchar(64) DEFAULT '' NOT NULL, +passwd varchar(32) binary DEFAULT '' NOT NULL, +PRIMARY KEY (id), +UNIQUE ggid (ggid) +) ENGINE=innodb; +insert into t1 (ggid,passwd) values ('test1','xxx'); +insert into t1 (ggid,passwd) values ('test2','yyy'); +insert into t1 (ggid,passwd) values ('test2','this will fail'); +ERROR 23000: Duplicate entry 'test2' for key 'ggid' +insert into t1 (ggid,id) values ('this will fail',1); +ERROR 23000: Duplicate entry '1' for key 'PRIMARY' +select * from t1 where ggid='test1'; +id ggid email passwd +1 test1 xxx +select * from t1 where passwd='xxx'; +id ggid email passwd +1 test1 xxx +select * from t1 where id=2; +id ggid email passwd +2 test2 yyy +replace into t1 (ggid,id) values ('this will work',1); +replace into t1 (ggid,passwd) values ('test2','this will work'); +update t1 set id=100,ggid='test2' where id=1; +ERROR 23000: Duplicate entry 'test2' for key 'ggid' +select * from t1; +id ggid email passwd +1 this will work +3 test2 this will work +select * from t1 where id=1; +id ggid email passwd +1 this will work +select * from t1 where id=999; +id ggid email passwd +drop table t1; +End of tests diff --git a/mysql-test/r/innodb_mysql.result b/mysql-test/r/innodb_mysql.result index 05db4436a65..c3896e97165 100644 --- a/mysql-test/r/innodb_mysql.result +++ b/mysql-test/r/innodb_mysql.result @@ -353,13 +353,13 @@ EXPLAIN SELECT COUNT(*) FROM t2 LEFT JOIN t1 ON t2.fkey = t1.id WHERE t1.name LIKE 'A%'; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index PRIMARY,name name 23 NULL 3 Using where; Using index +1 SIMPLE t1 index PRIMARY,name PRIMARY 4 NULL 3 Using where 1 SIMPLE t2 ref fkey fkey 5 test.t1.id 1 Using where; Using index EXPLAIN SELECT COUNT(*) FROM t2 LEFT JOIN t1 ON t2.fkey = t1.id WHERE t1.name LIKE 'A%' OR FALSE; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2 index NULL fkey 5 NULL 5 Using index +1 SIMPLE t2 index NULL PRIMARY 4 NULL 5 1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 test.t2.fkey 1 Using where DROP TABLE t1,t2; CREATE TABLE t1 ( @@ -389,6 +389,7 @@ id select_type table type possible_keys key key_len ref rows Extra SELECT DISTINCT t1.name, t1.dept FROM t1 WHERE t1.name='rs5'; name dept DROP TABLE t1; +drop table if exists t1; show variables like 'innodb_rollback_on_timeout'; Variable_name Value innodb_rollback_on_timeout OFF @@ -451,6 +452,7 @@ tes 1234 drop table test; set global query_cache_type=@save_qcache_type; set global query_cache_size=@save_qcache_size; +drop table if exists t1; show variables like 'innodb_rollback_on_timeout'; Variable_name Value innodb_rollback_on_timeout OFF @@ -775,6 +777,7 @@ EXPLAIN SELECT SQL_BIG_RESULT b, SUM(c) FROM t1 GROUP BY b; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 128 Using filesort DROP TABLE t1; +drop table if exists t1; show variables like 'innodb_rollback_on_timeout'; Variable_name Value innodb_rollback_on_timeout OFF @@ -1261,11 +1264,11 @@ select_type SIMPLE table t1 type index possible_keys NULL -key b -key_len 5 +key PRIMARY +key_len 4 ref NULL rows 3 -Extra Using index; Using filesort +Extra Using filesort SELECT * FROM t1 ORDER BY b ASC, a DESC; a b 1 1 @@ -1277,11 +1280,11 @@ select_type SIMPLE table t1 type index possible_keys NULL -key b -key_len 5 +key PRIMARY +key_len 4 ref NULL rows 3 -Extra Using index; Using filesort +Extra Using filesort SELECT * FROM t1 ORDER BY b DESC, a ASC; a b 2 2 @@ -1322,6 +1325,21 @@ test t1 Redundant # - that's it, cleanup. DROP TABLE t1; +create table t1(a char(10) not null, unique key aa(a(1)), +b char(4) not null, unique key bb(b(4))) engine=innodb; +desc t1; +Field Type Null Key Default Extra +a char(10) NO UNI NULL +b char(4) NO PRI NULL +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` char(10) NOT NULL, + `b` char(4) NOT NULL, + UNIQUE KEY `bb` (`b`), + UNIQUE KEY `aa` (`a`(1)) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +drop table t1; End of 5.0 tests CREATE TABLE `t2` ( `k` int(11) NOT NULL auto_increment, @@ -1460,6 +1478,7 @@ SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; CREATE TABLE t1 (a INT PRIMARY KEY, b VARCHAR(256)) ENGINE = InnoDB; INSERT INTO t1 VALUES (1,2); +# 1. test for locking: BEGIN; UPDATE t1 SET b = 12 WHERE a = 1; affected rows: 1 @@ -1569,4 +1588,9 @@ t2 CREATE TABLE `t2` ( ) ENGINE=InnoDB DEFAULT CHARSET=latin1 DROP TABLE t2; DROP TABLE t1; +create table t1 (a int auto_increment primary key) engine=innodb; +alter table t1 order by a; +Warnings: +Warning 1105 ORDER BY ignored as there is a user-defined clustered index in the table 't1' +drop table t1; End of 5.1 tests diff --git a/mysql-test/r/innodb_timeout_rollback.result b/mysql-test/r/innodb_timeout_rollback.result index b25a2bbd815..e2da6ba8af7 100644 --- a/mysql-test/r/innodb_timeout_rollback.result +++ b/mysql-test/r/innodb_timeout_rollback.result @@ -1,3 +1,4 @@ +drop table if exists t1; show variables like 'innodb_rollback_on_timeout'; Variable_name Value innodb_rollback_on_timeout ON diff --git a/mysql-test/r/insert.result b/mysql-test/r/insert.result index 8dbba4d454a..919aff4bfb7 100644 --- a/mysql-test/r/insert.result +++ b/mysql-test/r/insert.result @@ -499,4 +499,138 @@ i 2 2 DROP TABLE t1, t2; +CREATE TABLE t1 ( +a char(20) NOT NULL, +b char(7) DEFAULT NULL, +c char(4) DEFAULT NULL +); +INSERT INTO t1(a,b,c) VALUES (9.999999e+0, 9.999999e+0, 9.999e+0); +INSERT INTO t1(a,b,c) VALUES (1.225e-05, 1.225e-05, 1.225e-05); +Warnings: +Warning 1265 Data truncated for column 'c' at row 1 +INSERT INTO t1(a,b) VALUES (1.225e-04, 1.225e-04); +INSERT INTO t1(a,b) VALUES (1.225e-01, 1.225e-01); +INSERT INTO t1(a,b) VALUES (1.225877e-01, 1.225877e-01); +INSERT INTO t1(a,b) VALUES (1.225e+01, 1.225e+01); +INSERT INTO t1(a,b,c) VALUES (1.225e+01, 1.225e+01, 1.225e+01); +INSERT INTO t1(a,b) VALUES (1.225e+05, 1.225e+05); +INSERT INTO t1(a,b) VALUES (1.225e+10, 1.225e+10); +INSERT INTO t1(a,b) VALUES (1.225e+15, 1.225e+15); +INSERT INTO t1(a,b) VALUES (5000000e+0, 5000000e+0); +INSERT INTO t1(a,b) VALUES (1.25e+78, 1.25e+78); +INSERT INTO t1(a,b) VALUES (1.25e-94, 1.25e-94); +INSERT INTO t1(a,b) VALUES (1.25e+203, 1.25e+203); +INSERT INTO t1(a,b) VALUES (1.25e-175, 1.25e-175); +INSERT INTO t1(a,c) VALUES (1.225e+0, 1.225e+0); +INSERT INTO t1(a,c) VALUES (1.37e+0, 1.37e+0); +INSERT INTO t1(a,c) VALUES (-1.37e+0, -1.37e+0); +Warnings: +Warning 1265 Data truncated for column 'c' at row 1 +INSERT INTO t1(a,c) VALUES (1.87e-3, 1.87e-3); +Warnings: +Warning 1265 Data truncated for column 'c' at row 1 +INSERT INTO t1(a,c) VALUES (-1.87e-2, -1.87e-2); +Warnings: +Warning 1265 Data truncated for column 'c' at row 1 +INSERT INTO t1(a,c) VALUES (5000e+0, 5000e+0); +INSERT INTO t1(a,c) VALUES (-5000e+0, -5000e+0); +Warnings: +Warning 1265 Data truncated for column 'c' at row 1 +SELECT * FROM t1; +a b c +9.999999 10 10 +1.225e-05 1.2e-05 1e-0 +0.0001225 0.00012 NULL +0.1225 0.1225 NULL +0.1225877 0.12259 NULL +12.25 12.25 NULL +12.25 12.25 12.2 +122500 122500 NULL +12250000000 1.2e+10 NULL +1.225e+15 1.2e+15 NULL +5000000 5000000 NULL +1.25e+78 1.2e+78 NULL +1.25e-94 1.2e-94 NULL +1.25e+203 1e+203 NULL +1.25e-175 1e-175 NULL +1.225 NULL 1.23 +1.37 NULL 1.37 +-1.37 NULL -1.3 +0.00187 NULL 0.00 +-0.0187 NULL -0.0 +5000 NULL 5000 +-5000 NULL -500 +DROP TABLE t1; +CREATE TABLE t1 ( +a char(20) NOT NULL, +b char(7) DEFAULT NULL, +c char(5) +); +INSERT INTO t1(a,b,c) VALUES (9.999999e+0, 9.999999e+0, 9.999e+0); +INSERT INTO t1(a,b,c) VALUES (1.225e-05, 1.225e-05, 1.225e-05); +INSERT INTO t1(a,b) VALUES (1.225e-04, 1.225e-04); +INSERT INTO t1(a,b) VALUES (1.225e-01, 1.225e-01); +INSERT INTO t1(a,b) VALUES (1.225877e-01, 1.225877e-01); +INSERT INTO t1(a,b) VALUES (1.225e+01, 1.225e+01); +INSERT INTO t1(a,b,c) VALUES (1.225e+01, 1.225e+01, 1.225e+01); +INSERT INTO t1(a,b) VALUES (1.225e+05, 1.225e+05); +INSERT INTO t1(a,b) VALUES (1.225e+10, 1.225e+10); +INSERT INTO t1(a,b) VALUES (1.225e+15, 1.225e+15); +INSERT INTO t1(a,b) VALUES (5000000e+0, 5000000e+0); +INSERT INTO t1(a,b) VALUES (1.25e+78, 1.25e+78); +INSERT INTO t1(a,b) VALUES (1.25e-94, 1.25e-94); +INSERT INTO t1(a,b) VALUES (1.25e+203, 1.25e+203); +INSERT INTO t1(a,b) VALUES (1.25e-175, 1.25e-175); +INSERT INTO t1(a,c) VALUES (1.225e+0, 1.225e+0); +INSERT INTO t1(a,c) VALUES (1.37e+0, 1.37e+0); +INSERT INTO t1(a,c) VALUES (-1.37e+0, -1.37e+0); +INSERT INTO t1(a,c) VALUES (1.87e-3, 1.87e-3); +INSERT INTO t1(a,c) VALUES (-1.87e-2, -1.87e-2); +Warnings: +Warning 1265 Data truncated for column 'c' at row 1 +INSERT INTO t1(a,c) VALUES (5000e+0, 5000e+0); +INSERT INTO t1(a,c) VALUES (-5000e+0, -5000e+0); +SELECT * FROM t1; +a b c +9.999999 10 9.999 +1.225e-05 1.2e-05 1e-05 +0.0001225 0.00012 NULL +0.1225 0.1225 NULL +0.1225877 0.12259 NULL +12.25 12.25 NULL +12.25 12.25 12.25 +122500 122500 NULL +12250000000 1.2e+10 NULL +1.225e+15 1.2e+15 NULL +5000000 5000000 NULL +1.25e+78 1.2e+78 NULL +1.25e-94 1.2e-94 NULL +1.25e+203 1e+203 NULL +1.25e-175 1e-175 NULL +1.225 NULL 1.225 +1.37 NULL 1.37 +-1.37 NULL -1.37 +0.00187 NULL 0.002 +-0.0187 NULL -0.01 +5000 NULL 5000 +-5000 NULL -5000 +DROP TABLE t1; +CREATE TABLE t (a CHAR(10),b INT); +INSERT INTO t VALUES (),(),(); +INSERT INTO t(a) SELECT rand() FROM t; +DROP TABLE t; +CREATE TABLE t1 (c1 INT NOT NULL); +INSERT INTO t1 VALUES(4188.32999999999992724042385816574096679687500), +('4188.32999999999992724042385816574096679687500'), (4188); +SELECT * FROM t1; +c1 +4188 +4188 +4188 +CREATE TABLE t2 (c1 BIGINT); +INSERT INTO t2 VALUES('15449237462.0000000000'); +SELECT * FROM t2; +c1 +15449237462 +DROP TABLE t1, t2; End of 5.0 tests. diff --git a/mysql-test/r/join_outer_innodb.result b/mysql-test/r/join_outer_innodb.result index e8a2d6f668b..24a11b12b03 100644 --- a/mysql-test/r/join_outer_innodb.result +++ b/mysql-test/r/join_outer_innodb.result @@ -8,12 +8,12 @@ EXPLAIN SELECT COUNT(*) FROM t2 LEFT JOIN t1 ON t2.fkey = t1.id WHERE t1.name LIKE 'A%'; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index PRIMARY,name name 23 NULL 3 Using where; Using index +1 SIMPLE t1 index PRIMARY,name PRIMARY 4 NULL 3 Using where 1 SIMPLE t2 ref fkey fkey 5 test.t1.id 1 Using where; Using index EXPLAIN SELECT COUNT(*) FROM t2 LEFT JOIN t1 ON t2.fkey = t1.id WHERE t1.name LIKE 'A%' OR FALSE; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2 index NULL fkey 5 NULL 5 Using index +1 SIMPLE t2 index NULL PRIMARY 4 NULL 5 1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 test.t2.fkey 1 Using where DROP TABLE t1,t2; diff --git a/mysql-test/r/key.result b/mysql-test/r/key.result index 3db5e926d30..fcc09a0244d 100644 --- a/mysql-test/r/key.result +++ b/mysql-test/r/key.result @@ -530,6 +530,51 @@ ORDER BY c.b, c.d a b c d e f g h i j a b c d 2 2 1 2004-11-30 12:00:00 1 0 0 0 0 0 2 3388000 -553000 NULL DROP TABLE t1, t2; +create table t1(a int not null, key aa(a), +b char(10) not null, unique key bb(b(1)), +c char(4) not null, unique key cc(c)); +desc t1; +Field Type Null Key Default Extra +a int(11) NO MUL NULL +b char(10) NO UNI NULL +c char(4) NO PRI NULL +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) NOT NULL, + `b` char(10) NOT NULL, + `c` char(4) NOT NULL, + UNIQUE KEY `cc` (`c`), + UNIQUE KEY `bb` (`b`(1)), + KEY `aa` (`a`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +drop table t1; +create table t1(a int not null, key aa(a), +b char(10) not null, unique key bb(b(1)), +c char(4) not null); +desc t1; +Field Type Null Key Default Extra +a int(11) NO MUL NULL +b char(10) NO UNI NULL +c char(4) NO NULL +alter table t1 add unique key cc(c); +desc t1; +Field Type Null Key Default Extra +a int(11) NO MUL NULL +b char(10) NO UNI NULL +c char(4) NO PRI NULL +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) NOT NULL, + `b` char(10) NOT NULL, + `c` char(4) NOT NULL, + UNIQUE KEY `cc` (`c`), + UNIQUE KEY `bb` (`b`(1)), + KEY `aa` (`a`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +drop table t1; +End of 5.0 tests DROP TABLE IF EXISTS t1; CREATE TABLE t1 (a INT PRIMARY KEY AUTO_INCREMENT); INSERT INTO t1 VALUES (), (), (); diff --git a/mysql-test/r/kill.result b/mysql-test/r/kill.result index a08be429a83..3ea5bbd20bc 100644 --- a/mysql-test/r/kill.result +++ b/mysql-test/r/kill.result @@ -125,3 +125,14 @@ drop function bug27563; drop procedure proc27563; PREPARE stmt FROM 'EXPLAIN SELECT * FROM t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17,t18,t19,t20,t21,t22,t23,t24,t25,t26,t27,t28,t29,t30,t31,t32,t33,t34,t35,t36,t37,t38,t39,t40 WHERE a1=a2 AND a2=a3 AND a3=a4 AND a4=a5 AND a5=a6 AND a6=a7 AND a7=a8 AND a8=a9 AND a9=a10 AND a10=a11 AND a11=a12 AND a12=a13 AND a13=a14 AND a14=a15 AND a15=a16 AND a16=a17 AND a17=a18 AND a18=a19 AND a19=a20 AND a20=a21 AND a21=a22 AND a22=a23 AND a23=a24 AND a24=a25 AND a25=a26 AND a26=a27 AND a27=a28 AND a28=a29 AND a29=a30 AND a30=a31 AND a31=a32 AND a32=a33 AND a33=a34 AND a34=a35 AND a35=a36 AND a36=a37 AND a37=a38 AND a38=a39 AND a39=a40 '; EXECUTE stmt; +# +# Bug#19723: kill of active connection yields different error code +# depending on platform. +# + +# Connection: con2. +KILL CONNECTION_ID(); +# CR_SERVER_LOST, CR_SERVER_GONE_ERROR, depending on the timing +# of close of the connection socket +SELECT 1; +Got one of the listed errors diff --git a/mysql-test/r/log_state.result b/mysql-test/r/log_state.result index 3a3ef584ce3..8ecfe3b2094 100644 --- a/mysql-test/r/log_state.result +++ b/mysql-test/r/log_state.result @@ -175,3 +175,78 @@ SET GLOBAL slow_query_log = ON; SET GLOBAL READ_ONLY = OFF; SET GLOBAL general_log = @old_general_log_state; SET GLOBAL slow_query_log = @old_slow_log_state; +SET @old_general_log_state = @@global.general_log; +SET @old_slow_log_state = @@global.slow_query_log; +SHOW VARIABLES LIKE 'general_log'; +Variable_name Value +general_log ON +SHOW VARIABLES LIKE 'log'; +Variable_name Value +log ON +SELECT @@general_log, @@log; +@@general_log @@log +1 1 +SET GLOBAL log = 0; +SHOW VARIABLES LIKE 'general_log'; +Variable_name Value +general_log OFF +SHOW VARIABLES LIKE 'log'; +Variable_name Value +log OFF +SELECT @@general_log, @@log; +@@general_log @@log +0 0 +SET GLOBAL general_log = 1; +SHOW VARIABLES LIKE 'general_log'; +Variable_name Value +general_log ON +SHOW VARIABLES LIKE 'log'; +Variable_name Value +log ON +SELECT @@general_log, @@log; +@@general_log @@log +1 1 +SHOW VARIABLES LIKE 'slow_query_log'; +Variable_name Value +slow_query_log OFF +SHOW VARIABLES LIKE 'log_slow_queries'; +Variable_name Value +log_slow_queries OFF +SELECT @@slow_query_log, @@log_slow_queries; +@@slow_query_log @@log_slow_queries +0 0 +SET GLOBAL log_slow_queries = 0; +SHOW VARIABLES LIKE 'slow_query_log'; +Variable_name Value +slow_query_log OFF +SHOW VARIABLES LIKE 'log_slow_queries'; +Variable_name Value +log_slow_queries OFF +SELECT @@slow_query_log, @@log_slow_queries; +@@slow_query_log @@log_slow_queries +0 0 +SET GLOBAL slow_query_log = 1; +SHOW VARIABLES LIKE 'slow_query_log'; +Variable_name Value +slow_query_log ON +SHOW VARIABLES LIKE 'log_slow_queries'; +Variable_name Value +log_slow_queries ON +SELECT @@slow_query_log, @@log_slow_queries; +@@slow_query_log @@log_slow_queries +1 1 +SET GLOBAL general_log = @old_general_log_state; +SET GLOBAL slow_query_log = @old_slow_log_state; +set @old_general_log_file= @@global.general_log_file; +set @old_slow_query_log_file= @@global.slow_query_log_file; +set global general_log_file= concat('/not exiting path/log.maste', 'r'); +ERROR 42000: Variable 'general_log_file' can't be set to the value of '/not exiting path/log.master' +set global general_log_file= NULL; +ERROR 42000: Variable 'general_log_file' can't be set to the value of 'NULL' +set global slow_query_log_file= concat('/not exiting path/log.maste', 'r'); +ERROR 42000: Variable 'slow_query_log_file' can't be set to the value of '/not exiting path/log.master' +set global slow_query_log_file= NULL; +ERROR 42000: Variable 'slow_query_log_file' can't be set to the value of 'NULL' +set global general_log_file= @old_general_log_file; +set global slow_query_log_file= @old_slow_query_log_file; +End of 5.1 tests diff --git a/mysql-test/r/log_tables.result b/mysql-test/r/log_tables.result index 261e3292f4d..0a7634df85a 100644 --- a/mysql-test/r/log_tables.result +++ b/mysql-test/r/log_tables.result @@ -50,7 +50,7 @@ general_log CREATE TABLE `general_log` ( ) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='General log' show fields from mysql.general_log; Field Type Null Key Default Extra -event_time timestamp NO CURRENT_TIMESTAMP +event_time timestamp NO CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP user_host mediumtext NO NULL thread_id int(11) NO NULL server_id int(11) NO NULL @@ -73,7 +73,7 @@ slow_log CREATE TABLE `slow_log` ( ) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='Slow log' show fields from mysql.slow_log; Field Type Null Key Default Extra -start_time timestamp NO CURRENT_TIMESTAMP +start_time timestamp NO CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP user_host mediumtext NO NULL query_time time NO NULL lock_time time NO NULL @@ -605,6 +605,7 @@ DROP PROCEDURE IF EXISTS `db_17876.archiveGeneralLog`; DROP DATABASE IF EXISTS `db_17876`; SET GLOBAL general_log = @old_general_log_state; SET GLOBAL slow_query_log = @old_slow_log_state; +select CONNECTION_ID() into @thread_id; truncate table mysql.general_log; set @old_general_log_state = @@global.general_log; set global general_log = on; @@ -711,7 +712,7 @@ set @lparam = "000 001 002 003 004 005 006 007 008 009" prepare long_query from "select ? as long_query"; execute long_query using @lparam; set global general_log = off; -select command_type, argument from mysql.general_log; +select command_type, argument from mysql.general_log where thread_id = @thread_id; command_type argument Query set @lparam = "000 001 002 003 004 005 006 007 008 009" "010 011 012 013 014 015 016 017 018 019" @@ -820,3 +821,31 @@ Execute select '000 001 002 003 004 005 006 007 008 009010 011 012 013 014 015 0 Query set global general_log = off deallocate prepare long_query; set global general_log = @old_general_log_state; +SET @old_slow_log_state = @@global.slow_query_log; +SET SESSION long_query_time = 0; +SET GLOBAL slow_query_log = ON; +FLUSH LOGS; +TRUNCATE TABLE mysql.slow_log; +CREATE TABLE t1 (f1 SERIAL,f2 INT, f3 INT, PRIMARY KEY(f1), KEY(f2)); +INSERT INTO t1 VALUES (1,1,1); +INSERT INTO t1 VALUES (2,2,2); +INSERT INTO t1 VALUES (3,3,3); +INSERT INTO t1 VALUES (4,4,4); +SELECT SQL_NO_CACHE 'Bug#31700 - SCAN',f1,f2,f3,SLEEP(1.1) FROM t1 WHERE f3=4; +Bug#31700 - SCAN f1 f2 f3 SLEEP(1.1) +Bug#31700 - SCAN 4 4 4 0 +SELECT SQL_NO_CACHE 'Bug#31700 - KEY', f1,f2,f3,SLEEP(1.1) FROM t1 WHERE f2=3; +Bug#31700 - KEY f1 f2 f3 SLEEP(1.1) +Bug#31700 - KEY 3 3 3 0 +SELECT SQL_NO_CACHE 'Bug#31700 - PK', f1,f2,f3,SLEEP(1.1) FROM t1 WHERE f1=2; +Bug#31700 - PK f1 f2 f3 SLEEP(1.1) +Bug#31700 - PK 2 2 2 0 +SELECT start_time, rows_examined, rows_sent, sql_text FROM mysql.slow_log WHERE sql_text LIKE '%Bug#31700%' ORDER BY start_time; +start_time rows_examined rows_sent sql_text +TIMESTAMP 4 1 SELECT SQL_NO_CACHE 'Bug#31700 - SCAN',f1,f2,f3,SLEEP(1.1) FROM t1 WHERE f3=4 +TIMESTAMP 1 1 SELECT SQL_NO_CACHE 'Bug#31700 - KEY', f1,f2,f3,SLEEP(1.1) FROM t1 WHERE f2=3 +TIMESTAMP 1 1 SELECT SQL_NO_CACHE 'Bug#31700 - PK', f1,f2,f3,SLEEP(1.1) FROM t1 WHERE f1=2 +DROP TABLE t1; +TRUNCATE TABLE mysql.slow_log; +SET GLOBAL slow_query_log = @old_slow_log_state; +SET SESSION long_query_time =@old_long_query_time; diff --git a/mysql-test/r/lowercase_view.result b/mysql-test/r/lowercase_view.result index 3653461c6b8..c37dc41c495 100644 --- a/mysql-test/r/lowercase_view.result +++ b/mysql-test/r/lowercase_view.result @@ -119,7 +119,7 @@ create table t1Aa (col1 int); create view v1Aa as select col1 from t1Aa as AaA; show create view v1AA; View Create View character_set_client collation_connection -v1aa CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1aa` AS select `aaa`.`col1` AS `col1` from `t1aa` `AaA` latin1 latin1_swedish_ci +v1aa CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1aa` AS select `aaa`.`col1` AS `col1` from `t1aa` `aaa` latin1 latin1_swedish_ci drop view v1AA; select Aaa.col1 from t1Aa as AaA; col1 @@ -128,6 +128,23 @@ drop view v1AA; create view v1Aa as select AaA.col1 from t1Aa as AaA; show create view v1AA; View Create View character_set_client collation_connection -v1aa CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1aa` AS select `aaa`.`col1` AS `col1` from `t1aa` `AaA` latin1 latin1_swedish_ci +v1aa CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1aa` AS select `aaa`.`col1` AS `col1` from `t1aa` `aaa` latin1 latin1_swedish_ci drop view v1AA; drop table t1Aa; +CREATE TABLE t1 (a int, b int); +select X.a from t1 AS X group by X.b having (X.a = 1); +a +select X.a from t1 AS X group by X.b having (x.a = 1); +a +select X.a from t1 AS X group by X.b having (x.b = 1); +a +CREATE OR REPLACE VIEW v1 AS +select X.a from t1 AS X group by X.b having (X.a = 1); +SHOW CREATE VIEW v1; +View Create View character_set_client collation_connection +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `x`.`a` AS `a` from `t1` `x` group by `x`.`b` having (`x`.`a` = 1) latin1 latin1_swedish_ci +SELECT * FROM v1; +a +DROP VIEW v1; +DROP TABLE t1; +End of 5.0 tests. diff --git a/mysql-test/r/merge-big.result b/mysql-test/r/merge-big.result new file mode 100644 index 00000000000..82fedc1df73 --- /dev/null +++ b/mysql-test/r/merge-big.result @@ -0,0 +1,77 @@ +drop table if exists t1,t2,t3,t4,t5,t6; +# +# Bug#26379 - Combination of FLUSH TABLE and REPAIR TABLE +# corrupts a MERGE table +# Problem #3 +# +CREATE TABLE t1 (c1 INT) ENGINE= MyISAM; +LOCK TABLE t1 WRITE; +# connection con1 +SET SESSION debug="+d,sleep_open_and_lock_after_open"; +INSERT INTO t1 VALUES (1); +# connection default +# Let INSERT go into thr_multi_lock(). +# Kick INSERT out of thr_multi_lock(). +FLUSH TABLES; +# Let INSERT go through open_tables() where it sleeps. +# Unlock and close table and wait for con1 to close too. +FLUSH TABLES; +# This should give no result. +SELECT * FROM t1; +c1 +UNLOCK TABLES; +# connection con1 +SET SESSION debug="-d,sleep_open_and_lock_after_open"; +# connection default +DROP TABLE t1; +# +# Extra tests for Bug#26379 - Combination of FLUSH TABLE and +# REPAIR TABLE corrupts a MERGE table +# +CREATE TABLE t1 (c1 INT); +CREATE TABLE t2 (c1 INT); +CREATE TABLE t3 (c1 INT); +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (2); +INSERT INTO t3 VALUES (3); +# +# CREATE ... SELECT +# try to access parent from another thread. +# +# connection con1 +SET SESSION debug="+d,sleep_create_select_before_lock"; +CREATE TABLE t4 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1,t2) +INSERT_METHOD=FIRST SELECT * FROM t3; +# connection default +# Now try to access the parent. +# If 3 is in table, SELECT had to wait. +SELECT * FROM t4 ORDER BY c1; +c1 +1 +2 +3 +# connection con1 +SET SESSION debug="-d,sleep_create_select_before_lock"; +# connection default +# Cleanup for next test. +DROP TABLE t4; +DELETE FROM t1 WHERE c1 != 1; +# +# CREATE ... SELECT +# try to access child from another thread. +# +# connection con1 +SET SESSION debug="+d,sleep_create_select_before_lock"; +CREATE TABLE t4 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1,t2) +INSERT_METHOD=FIRST SELECT * FROM t3; +# connection default +# Now try to access a child. +# If 3 is in table, SELECT had to wait. +SELECT * FROM t1 ORDER BY c1; +c1 +1 +3 +# connection con1 +SET SESSION debug="-d,sleep_create_select_before_lock"; +# connection default +DROP TABLE t1, t2, t3, t4; diff --git a/mysql-test/r/merge.result b/mysql-test/r/merge.result index d6e19107ec4..ba1680f2cac 100644 --- a/mysql-test/r/merge.result +++ b/mysql-test/r/merge.result @@ -584,9 +584,7 @@ insert into t1 values (1); insert into t2 values (2); create temporary table t3 (a int not null) ENGINE=MERGE UNION=(t1,t2); select * from t3; -a -1 -2 +ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist create temporary table t4 (a int not null); create temporary table t5 (a int not null); insert into t4 values (1); @@ -597,6 +595,54 @@ a 1 2 drop table t6, t3, t1, t2, t4, t5; +create temporary table t1 (a int not null); +create temporary table t2 (a int not null); +insert into t1 values (1); +insert into t2 values (2); +create table t3 (a int not null) ENGINE=MERGE UNION=(t1,t2); +select * from t3; +ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist +drop table t3, t2, t1; +create table t1 (a int not null); +create temporary table t2 (a int not null); +insert into t1 values (1); +insert into t2 values (2); +create table t3 (a int not null) ENGINE=MERGE UNION=(t1,t2); +select * from t3; +ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist +drop table t3; +create temporary table t3 (a int not null) ENGINE=MERGE UNION=(t1,t2); +select * from t3; +ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist +drop table t3, t2, t1; +# CREATE...SELECT is not implemented for MERGE tables. +CREATE TEMPORARY TABLE t1 (c1 INT NOT NULL); +CREATE TEMPORARY TABLE t2 (c1 INT NOT NULL); +CREATE TABLE t3 (c1 INT NOT NULL); +INSERT INTO t3 VALUES (3), (33); +LOCK TABLES t3 READ; +CREATE TEMPORARY TABLE t4 (c1 INT NOT NULL) ENGINE=MERGE UNION=(t1,t2) +INSERT_METHOD=LAST SELECT * FROM t3; +ERROR HY000: 'test.t4' is not BASE TABLE +SELECT * FROM t4; +ERROR HY000: Table 't4' was not locked with LOCK TABLES +UNLOCK TABLES; +CREATE TEMPORARY TABLE t4 (c1 INT NOT NULL) ENGINE=MERGE UNION=(t1,t2) +INSERT_METHOD=LAST; +INSERT INTO t4 SELECT * FROM t3; +# Alter temporary MERGE table. +ALTER TABLE t4 UNION=(t1); +LOCK TABLES t4 WRITE; +# Alter temporary MERGE table under LOCk tables. +ALTER TABLE t4 UNION=(t1,t2); +UNLOCK TABLES; +# MERGE table and function. +CREATE FUNCTION f1 () RETURNS INT RETURN (SELECT max(c1) FROM t3); +SELECT * FROM t4 WHERE c1 < f1(); +c1 +3 +DROP FUNCTION f1; +DROP TABLE t4, t3, t2, t1; CREATE TABLE t1 ( fileset_id tinyint(3) unsigned NOT NULL default '0', file_code varchar(32) NOT NULL default '', @@ -650,11 +696,11 @@ create table t2 (a int); insert into t1 values (0); insert into t2 values (1); create table t3 engine=merge union=(t1, t2) select * from t1; -ERROR HY000: You can't specify target table 't1' for update in FROM clause +ERROR HY000: 'test.t3' is not BASE TABLE create table t3 engine=merge union=(t1, t2) select * from t2; -ERROR HY000: You can't specify target table 't2' for update in FROM clause +ERROR HY000: 'test.t3' is not BASE TABLE create table t3 engine=merge union=(t1, t2) select (select max(a) from t2); -ERROR HY000: You can't specify target table 't2' for update in FROM clause +ERROR HY000: 'test.t3' is not BASE TABLE drop table t1, t2; create table t1 ( a double(14,4), @@ -784,7 +830,7 @@ ERROR HY000: Unable to open underlying table which is differently defined or of DROP TABLE t1, t2; CREATE TABLE t2(a INT) ENGINE=MERGE UNION=(t3); SELECT * FROM t2; -ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist +ERROR 42S02: Table 'test.t3' doesn't exist DROP TABLE t2; CREATE TABLE t1(a INT, b TEXT); CREATE TABLE tm1(a TEXT, b INT) ENGINE=MERGE UNION=(t1); @@ -849,20 +895,17 @@ drop table t2; drop table t1; CREATE TABLE tm1(a INT) ENGINE=MERGE UNION=(t1, t2); SELECT * FROM tm1; -ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist +ERROR 42S02: Table 'test.t1' doesn't exist CHECK TABLE tm1; Table Op Msg_type Msg_text -test.tm1 check Error Table 'test.t1' is differently defined or of non-MyISAM type or doesn't exist -test.tm1 check Error Table 'test.t2' is differently defined or of non-MyISAM type or doesn't exist -test.tm1 check Error Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist +test.tm1 check Error Table 'test.t1' doesn't exist test.tm1 check error Corrupt CREATE TABLE t1(a INT); SELECT * FROM tm1; -ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist +ERROR 42S02: Table 'test.t2' doesn't exist CHECK TABLE tm1; Table Op Msg_type Msg_text -test.tm1 check Error Table 'test.t2' is differently defined or of non-MyISAM type or doesn't exist -test.tm1 check Error Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist +test.tm1 check Error Table 'test.t2' doesn't exist test.tm1 check error Corrupt CREATE TABLE t2(a BLOB); SELECT * FROM tm1; @@ -885,3 +928,1022 @@ CREATE TABLE IF NOT EXISTS t1 SELECT * FROM t2; ERROR HY000: You can't specify target table 't1' for update in FROM clause DROP TABLE t1, t2; End of 5.0 tests +create table t1 (c1 int, index(c1)); +create table t2 (c1 int, index(c1)) engine=merge union=(t1); +insert into t1 values (1); +flush tables; +select * from t2; +c1 +1 +flush tables; +truncate table t1; +insert into t1 values (1); +flush tables; +select * from t2; +c1 +1 +truncate table t1; +insert into t1 values (1); +drop table t1,t2; +# +# Extra tests for TRUNCATE. +# +# Truncate MERGE table. +CREATE TABLE t1 (c1 INT, INDEX(c1)); +CREATE TABLE t2 (c1 INT, INDEX(c1)); +CREATE TABLE t3 (c1 INT, INDEX(c1)) ENGINE=MRG_MYISAM UNION=(t1,t2); +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (2); +SELECT * FROM t3; +c1 +1 +2 +TRUNCATE TABLE t3; +SELECT * FROM t3; +c1 +# +# Truncate child table. +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (2); +TRUNCATE TABLE t1; +SELECT * FROM t3; +c1 +2 +# +# Truncate MERGE table under locked tables. +LOCK TABLE t1 WRITE, t2 WRITE, t3 WRITE; +INSERT INTO t1 VALUES (1); +TRUNCATE TABLE t3; +ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction +SELECT * FROM t3; +c1 +1 +2 +# +# Truncate child table under locked tables. +TRUNCATE TABLE t1; +ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction +SELECT * FROM t3; +c1 +1 +2 +UNLOCK TABLES; +DROP TABLE t1, t2, t3; +# +# Truncate temporary MERGE table. +CREATE TEMPORARY TABLE t1 (c1 INT, INDEX(c1)); +CREATE TEMPORARY TABLE t2 (c1 INT, INDEX(c1)); +CREATE TEMPORARY TABLE t3 (c1 INT, INDEX(c1)) ENGINE=MRG_MYISAM UNION=(t1,t2); +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (2); +SELECT * FROM t3; +c1 +1 +2 +TRUNCATE TABLE t3; +SELECT * FROM t3; +c1 +# +# Truncate temporary child table. +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (2); +TRUNCATE TABLE t1; +SELECT * FROM t3; +c1 +2 +# +# Truncate temporary MERGE table under locked tables. +INSERT INTO t1 VALUES (1); +CREATE TABLE t4 (c1 INT, INDEX(c1)); +LOCK TABLE t4 WRITE; +TRUNCATE TABLE t3; +ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction +SELECT * FROM t3; +c1 +1 +2 +# +# Truncate temporary child table under locked tables. +TRUNCATE TABLE t1; +ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction +SELECT * FROM t3; +c1 +1 +2 +UNLOCK TABLES; +DROP TABLE t1, t2, t3, t4; +CREATE TABLE t1 (c1 INT) ENGINE= MyISAM; +CREATE TABLE t2 (c1 INT) ENGINE= MRG_MYISAM UNION= (t1) INSERT_METHOD= LAST; +REPAIR TABLE t1; +INSERT INTO t2 VALUES (1); +Table Op Msg_type Msg_text +test.t1 repair status OK +DROP TABLE t1, t2; +CREATE TABLE t1 (c1 INT) ENGINE= MyISAM; +CREATE TABLE t2 (c1 INT) ENGINE= MRG_MYISAM UNION= (t1) INSERT_METHOD= LAST; +LOCK TABLE t1 WRITE; +INSERT INTO t2 VALUES (1); +REPAIR TABLE t1; +Table Op Msg_type Msg_text +test.t1 repair status OK +UNLOCK TABLES; +DROP TABLE t1, t2; +CREATE TABLE t1 (c1 INT) ENGINE= MyISAM; +LOCK TABLE t1 WRITE; +INSERT INTO t1 VALUES (1); +FLUSH TABLES; +FLUSH TABLES; +SELECT * FROM t1; +c1 +UNLOCK TABLES; +DROP TABLE t1; +# +# Extra tests for Bug#26379 - Combination of FLUSH TABLE and +# REPAIR TABLE corrupts a MERGE table +# +# CREATE ... SELECT is disabled for MERGE tables. +# +CREATE TABLE t1(c1 INT); +INSERT INTO t1 VALUES (1); +CREATE TABLE t2 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1) INSERT_METHOD=LAST; +CREATE TABLE t3 ENGINE=MRG_MYISAM INSERT_METHOD=LAST SELECT * FROM t2; +ERROR HY000: Table 't3' is read only +SHOW CREATE TABLE t3; +ERROR 42S02: Table 'test.t3' doesn't exist +CREATE TABLE t3 ENGINE=MRG_MYISAM UNION=(t1) INSERT_METHOD=LAST +SELECT * FROM t2; +ERROR HY000: 'test.t3' is not BASE TABLE +SHOW CREATE TABLE t3; +ERROR 42S02: Table 'test.t3' doesn't exist +DROP TABLE t1, t2; +# +# CREATE ... LIKE +# +# 1. Create like. +CREATE TABLE t1 (c1 INT); +CREATE TABLE t2 (c1 INT); +CREATE TABLE t3 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1,t2) +INSERT_METHOD=LAST; +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (2); +INSERT INTO t3 VALUES (3); +CREATE TABLE t4 LIKE t3; +SHOW CREATE TABLE t4; +Table Create Table +t4 CREATE TABLE `t4` ( + `c1` int(11) DEFAULT NULL +) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 UNION=() +INSERT INTO t4 VALUES (4); +ERROR HY000: Table 't4' is read only +DROP TABLE t4; +# +# 1. Create like with locked tables. +LOCK TABLES t3 WRITE, t2 WRITE, t1 WRITE; +CREATE TABLE t4 LIKE t3; +SHOW CREATE TABLE t4; +ERROR HY000: Table 't4' was not locked with LOCK TABLES +INSERT INTO t4 VALUES (4); +ERROR HY000: Table 't4' was not locked with LOCK TABLES +UNLOCK TABLES; +SHOW CREATE TABLE t4; +Table Create Table +t4 CREATE TABLE `t4` ( + `c1` int(11) DEFAULT NULL +) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 UNION=() +INSERT INTO t4 VALUES (4); +ERROR HY000: Table 't4' is read only +DROP TABLE t4; +# +# Rename child. +# +# 1. Normal rename of non-MERGE table. +CREATE TABLE t4 (c1 INT); +INSERT INTO t4 VALUES (4); +SELECT * FROM t4 ORDER BY c1; +c1 +4 +RENAME TABLE t4 TO t5; +SELECT * FROM t5 ORDER BY c1; +c1 +4 +RENAME TABLE t5 TO t4; +SELECT * FROM t4 ORDER BY c1; +c1 +4 +DROP TABLE t4; +# +# 2. Normal rename. +SELECT * FROM t3 ORDER BY c1; +c1 +1 +2 +3 +RENAME TABLE t2 TO t5; +SELECT * FROM t3 ORDER BY c1; +ERROR 42S02: Table 'test.t2' doesn't exist +RENAME TABLE t5 TO t2; +SELECT * FROM t3 ORDER BY c1; +c1 +1 +2 +3 +# +# 3. Normal rename with locked tables. +LOCK TABLES t1 WRITE, t2 WRITE, t3 WRITE; +SELECT * FROM t3 ORDER BY c1; +c1 +1 +2 +3 +RENAME TABLE t2 TO t5; +ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction +SELECT * FROM t3 ORDER BY c1; +c1 +1 +2 +3 +RENAME TABLE t5 TO t2; +ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction +SELECT * FROM t3 ORDER BY c1; +c1 +1 +2 +3 +UNLOCK TABLES; +# +# 4. Alter table rename. +ALTER TABLE t2 RENAME TO t5; +SELECT * FROM t3 ORDER BY c1; +ERROR 42S02: Table 'test.t2' doesn't exist +ALTER TABLE t5 RENAME TO t2; +SELECT * FROM t3 ORDER BY c1; +c1 +1 +2 +3 +# +# 5. Alter table rename with locked tables. +LOCK TABLES t1 WRITE, t2 WRITE, t3 WRITE; +ALTER TABLE t2 RENAME TO t5; +SELECT * FROM t3 ORDER BY c1; +ERROR HY000: Table 't3' was not locked with LOCK TABLES +ALTER TABLE t5 RENAME TO t2; +ERROR HY000: Table 't5' was not locked with LOCK TABLES +UNLOCK TABLES; +ALTER TABLE t5 RENAME TO t2; +SELECT * FROM t3 ORDER BY c1; +c1 +1 +2 +3 +# +# Rename parent. +# +# 1. Normal rename with locked tables. +LOCK TABLES t1 WRITE, t2 WRITE, t3 WRITE; +SELECT * FROM t3 ORDER BY c1; +c1 +1 +2 +3 +RENAME TABLE t3 TO t5; +ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction +SELECT * FROM t3 ORDER BY c1; +c1 +1 +2 +3 +RENAME TABLE t5 TO t3; +ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction +SELECT * FROM t3 ORDER BY c1; +c1 +1 +2 +3 +# +# 5. Alter table rename with locked tables. +ALTER TABLE t3 RENAME TO t5; +SELECT * FROM t5 ORDER BY c1; +ERROR HY000: Table 't5' was not locked with LOCK TABLES +ALTER TABLE t5 RENAME TO t3; +ERROR HY000: Table 't5' was not locked with LOCK TABLES +UNLOCK TABLES; +ALTER TABLE t5 RENAME TO t3; +SELECT * FROM t3 ORDER BY c1; +c1 +1 +2 +3 +DROP TABLE t1, t2, t3; +# +# Drop locked tables. +# +# 1. Drop parent. +CREATE TABLE t1 (c1 INT, INDEX(c1)); +CREATE TABLE t2 (c1 INT, INDEX(c1)) ENGINE=MRG_MYISAM UNION=(t1) +INSERT_METHOD=LAST; +LOCK TABLES t1 WRITE, t2 WRITE; +INSERT INTO t1 VALUES (1); +DROP TABLE t2; +SELECT * FROM t2; +ERROR HY000: Table 't2' was not locked with LOCK TABLES +SELECT * FROM t1; +c1 +1 +UNLOCK TABLES; +# 2. Drop child. +CREATE TABLE t2 (c1 INT, INDEX(c1)) ENGINE=MRG_MYISAM UNION=(t1) +INSERT_METHOD=LAST; +LOCK TABLES t1 WRITE, t2 WRITE; +INSERT INTO t1 VALUES (1); +DROP TABLE t1; +SELECT * FROM t2; +ERROR 42S02: Table 'test.t1' doesn't exist +SELECT * FROM t1; +ERROR 42S02: Table 'test.t1' doesn't exist +UNLOCK TABLES; +DROP TABLE t2; +# +# ALTER TABLE. Change child list. +# +CREATE TABLE t1 (c1 INT, INDEX(c1)); +CREATE TABLE t2 (c1 INT, INDEX(c1)); +CREATE TABLE t3 (c1 INT, INDEX(c1)); +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (2); +INSERT INTO t3 VALUES (3); +CREATE TABLE t4 (c1 INT, INDEX(c1)) ENGINE=MRG_MYISAM UNION=(t3,t2) +INSERT_METHOD=LAST; +# Shrink child list. +ALTER TABLE t4 UNION=(t3); +SHOW CREATE TABLE t4; +Table Create Table +t4 CREATE TABLE `t4` ( + `c1` int(11) DEFAULT NULL, + KEY `c1` (`c1`) +) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 INSERT_METHOD=LAST UNION=(`t3`) +SELECT * FROM t4 ORDER BY c1; +c1 +3 +# Extend child list. +ALTER TABLE t4 UNION=(t3,t2); +SHOW CREATE TABLE t4; +Table Create Table +t4 CREATE TABLE `t4` ( + `c1` int(11) DEFAULT NULL, + KEY `c1` (`c1`) +) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 INSERT_METHOD=LAST UNION=(`t3`,`t2`) +SELECT * FROM t4 ORDER BY c1; +c1 +2 +3 +# +# ALTER TABLE under LOCK TABLES. Change child list. +# +LOCK TABLES t4 WRITE, t3 WRITE, t2 WRITE; +# Shrink child list. +ALTER TABLE t4 UNION=(t3); +ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction +# Extend child list within locked tables. +ALTER TABLE t4 UNION=(t3,t2); +ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction +# Extend child list beyond locked tables. +ALTER TABLE t4 UNION=(t3,t2,t1); +ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction +SHOW CREATE TABLE t4; +Table Create Table +t4 CREATE TABLE `t4` ( + `c1` int(11) DEFAULT NULL, + KEY `c1` (`c1`) +) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 INSERT_METHOD=LAST UNION=(`t3`,`t2`) +SELECT * FROM t4 ORDER BY c1; +c1 +2 +3 +UNLOCK TABLES; +DROP TABLE t4; +# +# ALTER TABLE under LOCK TABLES. Grave change, table re-creation. +# +CREATE TABLE t4 (c1 INT, INDEX(c1)) ENGINE=MRG_MYISAM UNION=(t1,t2,t3) +INSERT_METHOD=LAST; +# Lock parent first and then children. +LOCK TABLES t4 WRITE, t3 WRITE, t2 WRITE, t1 WRITE; +ALTER TABLE t4 DROP INDEX c1, ADD UNIQUE INDEX (c1); +SELECT * FROM t4 ORDER BY c1; +c1 +1 +2 +3 +ALTER TABLE t2 DROP INDEX c1, ADD UNIQUE INDEX (c1); +SELECT * FROM t4 ORDER BY c1; +c1 +1 +2 +3 +UNLOCK TABLES; +# Lock children first and then parent. +LOCK TABLES t1 WRITE, t2 WRITE, t3 WRITE, t4 WRITE; +ALTER TABLE t4 DROP INDEX c1, ADD UNIQUE INDEX (c1); +SELECT * FROM t4 ORDER BY c1; +c1 +1 +2 +3 +ALTER TABLE t2 DROP INDEX c1, ADD UNIQUE INDEX (c1); +SELECT * FROM t4 ORDER BY c1; +c1 +1 +2 +3 +UNLOCK TABLES; +# Lock parent between children. +LOCK TABLES t3 WRITE, t2 WRITE, t4 WRITE, t1 WRITE; +ALTER TABLE t4 DROP INDEX c1, ADD UNIQUE INDEX (c1); +SELECT * FROM t4 ORDER BY c1; +c1 +1 +2 +3 +ALTER TABLE t2 DROP INDEX c1, ADD UNIQUE INDEX (c1); +SELECT * FROM t4 ORDER BY c1; +c1 +1 +2 +3 +UNLOCK TABLES; +DROP TABLE t1, t2, t3, t4; +# +# ALTER TABLE under LOCK TABLES. Simple change, no re-creation. +# +CREATE TABLE t1 (c1 INT); +CREATE TABLE t2 (c1 INT); +CREATE TABLE t3 (c1 INT); +CREATE TABLE t4 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1,t2,t3) +INSERT_METHOD=LAST; +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (2); +INSERT INTO t3 VALUES (3); +# Lock parent first and then children. +LOCK TABLES t4 WRITE, t3 WRITE, t2 WRITE, t1 WRITE; +ALTER TABLE t4 ALTER COLUMN c1 SET DEFAULT 44; +SELECT * FROM t4 ORDER BY c1; +c1 +1 +2 +3 +ALTER TABLE t2 ALTER COLUMN c1 SET DEFAULT 22; +SELECT * FROM t4 ORDER BY c1; +c1 +1 +2 +3 +UNLOCK TABLES; +# Lock children first and then parent. +LOCK TABLES t1 WRITE, t2 WRITE, t3 WRITE, t4 WRITE; +ALTER TABLE t4 ALTER COLUMN c1 SET DEFAULT 44; +SELECT * FROM t4 ORDER BY c1; +c1 +1 +2 +3 +ALTER TABLE t2 ALTER COLUMN c1 SET DEFAULT 22; +SELECT * FROM t4 ORDER BY c1; +c1 +1 +2 +3 +UNLOCK TABLES; +# Lock parent between children. +LOCK TABLES t3 WRITE, t2 WRITE, t4 WRITE, t1 WRITE; +ALTER TABLE t4 ALTER COLUMN c1 SET DEFAULT 44; +SELECT * FROM t4 ORDER BY c1; +c1 +1 +2 +3 +ALTER TABLE t2 ALTER COLUMN c1 SET DEFAULT 22; +SELECT * FROM t4 ORDER BY c1; +c1 +1 +2 +3 +UNLOCK TABLES; +# +# FLUSH TABLE under LOCK TABLES. +# +# Lock parent first and then children. +LOCK TABLES t4 WRITE, t3 WRITE, t2 WRITE, t1 WRITE; +FLUSH TABLE t4; +SELECT * FROM t4 ORDER BY c1; +c1 +1 +2 +3 +FLUSH TABLE t2; +SELECT * FROM t4 ORDER BY c1; +c1 +1 +2 +3 +FLUSH TABLES; +SELECT * FROM t4 ORDER BY c1; +c1 +1 +2 +3 +UNLOCK TABLES; +# Lock children first and then parent. +LOCK TABLES t1 WRITE, t2 WRITE, t3 WRITE, t4 WRITE; +FLUSH TABLE t4; +SELECT * FROM t4 ORDER BY c1; +c1 +1 +2 +3 +FLUSH TABLE t2; +SELECT * FROM t4 ORDER BY c1; +c1 +1 +2 +3 +FLUSH TABLES; +SELECT * FROM t4 ORDER BY c1; +c1 +1 +2 +3 +UNLOCK TABLES; +# Lock parent between children. +LOCK TABLES t3 WRITE, t2 WRITE, t4 WRITE, t1 WRITE; +FLUSH TABLE t4; +SELECT * FROM t4 ORDER BY c1; +c1 +1 +2 +3 +FLUSH TABLE t2; +SELECT * FROM t4 ORDER BY c1; +c1 +1 +2 +3 +FLUSH TABLES; +SELECT * FROM t4 ORDER BY c1; +c1 +1 +2 +3 +UNLOCK TABLES; +# +# Triggers +# +# Trigger on parent +DELETE FROM t4 WHERE c1 = 4; +CREATE TRIGGER t4_ai AFTER INSERT ON t4 FOR EACH ROW SET @a=1; +SET @a=0; +INSERT INTO t4 VALUES (4); +SELECT @a; +@a +1 +SELECT * FROM t4 ORDER BY c1; +c1 +1 +2 +3 +4 +DROP TRIGGER t4_ai; +# Trigger on parent under LOCK TABLES +LOCK TABLES t3 WRITE, t2 WRITE, t4 WRITE, t1 WRITE; +CREATE TRIGGER t4_ai AFTER INSERT ON t4 FOR EACH ROW SET @a=1; +SET @a=0; +INSERT INTO t4 VALUES (4); +SELECT @a; +@a +1 +SELECT * FROM t4 ORDER BY c1; +c1 +1 +2 +3 +4 +4 +DROP TRIGGER t4_ai; +UNLOCK TABLES; +# +# Trigger on child +DELETE FROM t4 WHERE c1 = 4; +CREATE TRIGGER t3_ai AFTER INSERT ON t3 FOR EACH ROW SET @a=1; +SET @a=0; +INSERT INTO t4 VALUES (4); +SELECT @a; +@a +0 +INSERT INTO t3 VALUES (33); +SELECT @a; +@a +1 +SELECT * FROM t4 ORDER BY c1; +c1 +1 +2 +3 +4 +33 +DROP TRIGGER t3_ai; +# Trigger on child under LOCK TABLES +LOCK TABLES t3 WRITE, t2 WRITE, t4 WRITE, t1 WRITE; +CREATE TRIGGER t3_ai AFTER INSERT ON t3 FOR EACH ROW SET @a=1; +SET @a=0; +INSERT INTO t4 VALUES (4); +SELECT @a; +@a +0 +INSERT INTO t3 VALUES (33); +SELECT @a; +@a +1 +SELECT * FROM t4 ORDER BY c1; +c1 +1 +2 +3 +4 +4 +33 +33 +DELETE FROM t4 WHERE c1 = 33; +DROP TRIGGER t3_ai; +# +# Trigger with table use on child +DELETE FROM t4 WHERE c1 = 4; +CREATE TRIGGER t3_ai AFTER INSERT ON t3 FOR EACH ROW INSERT INTO t2 VALUES(22); +INSERT INTO t4 VALUES (4); +SELECT * FROM t4 ORDER BY c1; +c1 +1 +2 +3 +4 +INSERT INTO t3 VALUES (33); +SELECT * FROM t4 ORDER BY c1; +c1 +1 +2 +3 +4 +22 +33 +DELETE FROM t4 WHERE c1 = 22; +DELETE FROM t4 WHERE c1 = 33; +DROP TRIGGER t3_ai; +# Trigger with table use on child under LOCK TABLES +LOCK TABLES t3 WRITE, t2 WRITE, t4 WRITE, t1 WRITE; +CREATE TRIGGER t3_ai AFTER INSERT ON t3 FOR EACH ROW INSERT INTO t2 VALUES(22); +INSERT INTO t4 VALUES (4); +SELECT * FROM t4 ORDER BY c1; +c1 +1 +2 +3 +4 +4 +INSERT INTO t3 VALUES (33); +SELECT * FROM t4 ORDER BY c1; +c1 +1 +2 +3 +4 +4 +22 +33 +DROP TRIGGER t3_ai; +DELETE FROM t4 WHERE c1 = 22; +DELETE FROM t4 WHERE c1 = 33; +UNLOCK TABLES; +# +# Repair +# +REPAIR TABLE t4; +Table Op Msg_type Msg_text +test.t4 repair note The storage engine for the table doesn't support repair +REPAIR TABLE t2; +Table Op Msg_type Msg_text +test.t2 repair status OK +SELECT * FROM t4 ORDER BY c1; +c1 +1 +2 +3 +4 +4 +LOCK TABLES t3 WRITE, t2 WRITE, t4 WRITE, t1 WRITE; +REPAIR TABLE t4; +Table Op Msg_type Msg_text +test.t4 repair note The storage engine for the table doesn't support repair +REPAIR TABLE t2; +Table Op Msg_type Msg_text +test.t2 repair status OK +SELECT * FROM t4 ORDER BY c1; +c1 +1 +2 +3 +4 +4 +UNLOCK TABLES; +# +# Optimize +# +OPTIMIZE TABLE t4; +Table Op Msg_type Msg_text +test.t4 optimize note The storage engine for the table doesn't support optimize +OPTIMIZE TABLE t2; +Table Op Msg_type Msg_text +test.t2 optimize status OK +SELECT * FROM t4 ORDER BY c1; +c1 +1 +2 +3 +4 +4 +LOCK TABLES t3 WRITE, t2 WRITE, t4 WRITE, t1 WRITE; +OPTIMIZE TABLE t4; +Table Op Msg_type Msg_text +test.t4 optimize note The storage engine for the table doesn't support optimize +OPTIMIZE TABLE t2; +Table Op Msg_type Msg_text +test.t2 optimize status Table is already up to date +SELECT * FROM t4 ORDER BY c1; +c1 +1 +2 +3 +4 +4 +UNLOCK TABLES; +# +# Checksum +# +CHECKSUM TABLE t4; +Table Checksum +test.t4 46622073 +CHECKSUM TABLE t2; +Table Checksum +test.t2 3700403066 +SELECT * FROM t4 ORDER BY c1; +c1 +1 +2 +3 +4 +4 +LOCK TABLES t3 WRITE, t2 WRITE, t4 WRITE, t1 WRITE; +CHECKSUM TABLE t4; +Table Checksum +test.t4 46622073 +CHECKSUM TABLE t2; +Table Checksum +test.t2 3700403066 +SELECT * FROM t4 ORDER BY c1; +c1 +1 +2 +3 +4 +4 +UNLOCK TABLES; +# +# Insert delayed +# +INSERT DELAYED INTO t4 VALUES(44); +DELETE FROM t4 WHERE c1 = 44; +INSERT DELAYED INTO t3 VALUES(33); +SELECT * FROM t4 ORDER BY c1; +c1 +1 +2 +3 +4 +4 +33 +LOCK TABLES t3 WRITE, t2 WRITE, t4 WRITE, t1 WRITE; +INSERT DELAYED INTO t4 VALUES(444); +Got one of the listed errors +INSERT DELAYED INTO t3 VALUES(333); +Got one of the listed errors +SELECT * FROM t4 ORDER BY c1; +c1 +1 +2 +3 +4 +4 +33 +UNLOCK TABLES; +DROP TABLE t1, t2, t3, t4; +# +# Recursive inclusion of merge tables in their union clauses. +# +CREATE TABLE t1 (c1 INT, INDEX(c1)); +CREATE TABLE t2 (c1 INT, INDEX(c1)) ENGINE=MRG_MYISAM UNION=(t1) +INSERT_METHOD=LAST; +CREATE TABLE t3 (c1 INT, INDEX(c1)) ENGINE=MRG_MYISAM UNION=(t2,t1) +INSERT_METHOD=LAST; +ALTER TABLE t2 UNION=(t3,t1); +SELECT * FROM t2; +ERROR HY000: Table 't3' is differently defined or of non-MyISAM type or doesn't exist +DROP TABLE t1, t2, t3; +CREATE TABLE t1 (c1 INT) ENGINE= MyISAM; +CREATE TABLE t2 (c1 INT) ENGINE= MyISAM; +CREATE TABLE t3 (c1 INT) ENGINE= MRG_MYISAM UNION= (t1, t2); +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (2); +SELECT * FROM t3; +c1 +1 +2 +TRUNCATE TABLE t1; +SELECT * FROM t3; +c1 +2 +DROP TABLE t1, t2, t3; +CREATE TABLE t1 (id INTEGER, grp TINYINT, id_rev INTEGER); +SET @rnd_max= 2147483647; +SET @rnd= RAND(); +SET @id = CAST(@rnd * @rnd_max AS UNSIGNED); +SET @id_rev= @rnd_max - @id; +SET @grp= CAST(127.0 * @rnd AS UNSIGNED); +INSERT INTO t1 (id, grp, id_rev) VALUES (@id, @grp, @id_rev); +SET @rnd= RAND(); +SET @id = CAST(@rnd * @rnd_max AS UNSIGNED); +SET @id_rev= @rnd_max - @id; +SET @grp= CAST(127.0 * @rnd AS UNSIGNED); +INSERT INTO t1 (id, grp, id_rev) VALUES (@id, @grp, @id_rev); +SET @rnd= RAND(); +SET @id = CAST(@rnd * @rnd_max AS UNSIGNED); +SET @id_rev= @rnd_max - @id; +SET @grp= CAST(127.0 * @rnd AS UNSIGNED); +INSERT INTO t1 (id, grp, id_rev) VALUES (@id, @grp, @id_rev); +SET @rnd= RAND(); +SET @id = CAST(@rnd * @rnd_max AS UNSIGNED); +SET @id_rev= @rnd_max - @id; +SET @grp= CAST(127.0 * @rnd AS UNSIGNED); +INSERT INTO t1 (id, grp, id_rev) VALUES (@id, @grp, @id_rev); +SET @rnd= RAND(); +SET @id = CAST(@rnd * @rnd_max AS UNSIGNED); +SET @id_rev= @rnd_max - @id; +SET @grp= CAST(127.0 * @rnd AS UNSIGNED); +INSERT INTO t1 (id, grp, id_rev) VALUES (@id, @grp, @id_rev); +SET @rnd= RAND(); +SET @id = CAST(@rnd * @rnd_max AS UNSIGNED); +SET @id_rev= @rnd_max - @id; +SET @grp= CAST(127.0 * @rnd AS UNSIGNED); +INSERT INTO t1 (id, grp, id_rev) VALUES (@id, @grp, @id_rev); +SET @rnd= RAND(); +SET @id = CAST(@rnd * @rnd_max AS UNSIGNED); +SET @id_rev= @rnd_max - @id; +SET @grp= CAST(127.0 * @rnd AS UNSIGNED); +INSERT INTO t1 (id, grp, id_rev) VALUES (@id, @grp, @id_rev); +SET @rnd= RAND(); +SET @id = CAST(@rnd * @rnd_max AS UNSIGNED); +SET @id_rev= @rnd_max - @id; +SET @grp= CAST(127.0 * @rnd AS UNSIGNED); +INSERT INTO t1 (id, grp, id_rev) VALUES (@id, @grp, @id_rev); +SET @rnd= RAND(); +SET @id = CAST(@rnd * @rnd_max AS UNSIGNED); +SET @id_rev= @rnd_max - @id; +SET @grp= CAST(127.0 * @rnd AS UNSIGNED); +INSERT INTO t1 (id, grp, id_rev) VALUES (@id, @grp, @id_rev); +SET @rnd= RAND(); +SET @id = CAST(@rnd * @rnd_max AS UNSIGNED); +SET @id_rev= @rnd_max - @id; +SET @grp= CAST(127.0 * @rnd AS UNSIGNED); +INSERT INTO t1 (id, grp, id_rev) VALUES (@id, @grp, @id_rev); +set @@read_buffer_size=2*1024*1024; +CREATE TABLE t2 SELECT * FROM t1; +INSERT INTO t1 (id, grp, id_rev) SELECT id, grp, id_rev FROM t2; +INSERT INTO t2 (id, grp, id_rev) SELECT id, grp, id_rev FROM t1; +INSERT INTO t1 (id, grp, id_rev) SELECT id, grp, id_rev FROM t2; +INSERT INTO t2 (id, grp, id_rev) SELECT id, grp, id_rev FROM t1; +INSERT INTO t1 (id, grp, id_rev) SELECT id, grp, id_rev FROM t2; +CREATE TABLE t3 (id INTEGER, grp TINYINT, id_rev INTEGER) +ENGINE= MRG_MYISAM UNION= (t1, t2); +SELECT COUNT(*) FROM t1; +COUNT(*) +130 +SELECT COUNT(*) FROM t2; +COUNT(*) +80 +SELECT COUNT(*) FROM t3; +COUNT(*) +210 +SELECT COUNT(DISTINCT a1.id) FROM t3 AS a1, t3 AS a2 +WHERE a1.id = a2.id GROUP BY a2.grp; +TRUNCATE TABLE t1; +SELECT COUNT(*) FROM t1; +COUNT(*) +0 +SELECT COUNT(*) FROM t2; +COUNT(*) +80 +SELECT COUNT(*) FROM t3; +COUNT(*) +80 +DROP TABLE t1, t2, t3; +CREATE TABLE t1 (c1 INT) ENGINE=MyISAM; +CREATE TABLE t2 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1) INSERT_METHOD=LAST; +INSERT INTO t2 VALUES (1); +SELECT * FROM t2; +c1 +1 +LOCK TABLES t2 WRITE, t1 WRITE; +FLUSH TABLES; +REPAIR TABLE t1; +Table Op Msg_type Msg_text +test.t1 repair status OK +CHECK TABLE t1; +Table Op Msg_type Msg_text +test.t1 check status OK +REPAIR TABLE t1; +Table Op Msg_type Msg_text +test.t1 repair status OK +UNLOCK TABLES; +CHECK TABLE t1 EXTENDED; +Table Op Msg_type Msg_text +test.t1 check status OK +LOCK TABLES t2 WRITE, t1 WRITE; +REPAIR TABLE t1; +Table Op Msg_type Msg_text +test.t1 repair status OK +CHECK TABLE t1; +Table Op Msg_type Msg_text +test.t1 check status OK +REPAIR TABLE t1; +Table Op Msg_type Msg_text +test.t1 repair status OK +UNLOCK TABLES; +CHECK TABLE t1 EXTENDED; +Table Op Msg_type Msg_text +test.t1 check status OK +DROP TABLE t1, t2; +CREATE TABLE t1 ( a INT ) ENGINE=MyISAM; +CREATE TABLE m1 ( a INT ) ENGINE=MRG_MYISAM UNION=(t1); +LOCK TABLES t1 WRITE, m1 WRITE; +FLUSH TABLE t1; +UNLOCK TABLES; +DROP TABLE m1, t1; +CREATE TABLE t1 ( a INT ) ENGINE=MyISAM; +CREATE TABLE m1 ( a INT ) ENGINE=MRG_MYISAM UNION=(t1); +LOCK TABLES m1 WRITE, t1 WRITE; +FLUSH TABLE t1; +UNLOCK TABLES; +DROP TABLE m1, t1; +CREATE TABLE t1 (c1 INT, c2 INT) ENGINE= MyISAM; +CREATE TABLE t2 (c1 INT, c2 INT) ENGINE= MyISAM; +CREATE TABLE t3 (c1 INT, c2 INT) ENGINE= MRG_MYISAM UNION(t1, t2); +INSERT INTO t1 VALUES (1, 1); +INSERT INTO t2 VALUES (2, 2); +SELECT * FROM t3; +c1 c2 +1 1 +2 2 +ALTER TABLE t1 ENGINE= MEMORY; +INSERT INTO t1 VALUES (0, 0); +SELECT * FROM t3; +ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist +DROP TABLE t1, t2, t3; +CREATE TABLE t1 (c1 INT, KEY(c1)); +CREATE TABLE t2 (c1 INT, KEY(c1)) ENGINE=MRG_MYISAM UNION=(t1) +INSERT_METHOD=FIRST; +LOCK TABLE t1 WRITE, t2 WRITE; +FLUSH TABLES t2, t1; +OPTIMIZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 optimize status Table is already up to date +FLUSH TABLES t1; +UNLOCK TABLES; +FLUSH TABLES; +INSERT INTO t1 VALUES (1); +LOCK TABLE t1 WRITE, t2 WRITE; +FLUSH TABLES t2, t1; +OPTIMIZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 optimize status OK +FLUSH TABLES t1; +UNLOCK TABLES; +DROP TABLE t1, t2; +CREATE TABLE t1 (ID INT) ENGINE=MYISAM; +CREATE TABLE m1 (ID INT) ENGINE=MRG_MYISAM UNION=(t1) INSERT_METHOD=FIRST; +INSERT INTO t1 VALUES (); +INSERT INTO m1 VALUES (); +LOCK TABLE t1 WRITE, m1 WRITE; +FLUSH TABLES m1, t1; +OPTIMIZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 optimize status OK +FLUSH TABLES m1, t1; +UNLOCK TABLES; +DROP TABLE t1, m1; diff --git a/mysql-test/r/metadata.result b/mysql-test/r/metadata.result index 4a776b6a253..76c6ae7d034 100644 --- a/mysql-test/r/metadata.result +++ b/mysql-test/r/metadata.result @@ -21,7 +21,7 @@ def test t1 t1 g g 5 4 0 Y 32768 3 63 def test t1 t1 h h 246 7 0 Y 0 4 63 def test t1 t1 i i 13 4 0 Y 32864 0 63 def test t1 t1 j j 10 10 0 Y 128 0 63 -def test t1 t1 k k 7 19 0 N 1249 0 63 +def test t1 t1 k k 7 19 0 N 9441 0 63 def test t1 t1 l l 12 19 0 Y 128 0 63 def test t1 t1 m m 254 1 0 Y 256 0 8 def test t1 t1 n n 254 3 0 Y 2048 0 8 diff --git a/mysql-test/r/multi_update.result b/mysql-test/r/multi_update.result index 55e47756312..0bc01e95d2d 100644 --- a/mysql-test/r/multi_update.result +++ b/mysql-test/r/multi_update.result @@ -614,6 +614,7 @@ CREATE TABLE `t2` ( `b` int(11) default NULL, PRIMARY KEY (`a`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 ; +set @sav_binlog_format= @@session.binlog_format; set @@session.binlog_format= mixed; insert into t1 values (1,1),(2,2); insert into t2 values (1,1),(4,4); @@ -626,7 +627,7 @@ a b 4 4 show master status /* there must be the UPDATE query event */; File Position Binlog_Do_DB Binlog_Ignore_DB -master-bin.000001 197 +master-bin.000001 268 delete from t1; delete from t2; insert into t1 values (1,2),(3,4),(4,4); @@ -636,6 +637,24 @@ UPDATE t2,t1 SET t2.a=t2.b where t2.a=t1.a; ERROR 23000: Duplicate entry '4' for key 'PRIMARY' show master status /* there must be the UPDATE query event */; File Position Binlog_Do_DB Binlog_Ignore_DB -master-bin.000001 212 +master-bin.000001 283 drop table t1, t2; +set @@session.binlog_format= @sav_binlog_format; +drop table if exists t1, t2, t3; +CREATE TABLE t1 (a int, PRIMARY KEY (a)); +CREATE TABLE t2 (a int, PRIMARY KEY (a)); +CREATE TABLE t3 (a int, PRIMARY KEY (a)) ENGINE=MyISAM; +create trigger trg_del_t3 before delete on t3 for each row insert into t1 values (1); +insert into t2 values (1),(2); +insert into t3 values (1),(2); +reset master; +delete t3.* from t2,t3 where t2.a=t3.a; +ERROR 23000: Duplicate entry '1' for key 'PRIMARY' +select count(*) from t1 /* must be 1 */; +count(*) +1 +select count(*) from t3 /* must be 1 */; +count(*) +1 +drop table t1, t2, t3; end of tests diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result index 73661897ee1..353d66b1ad5 100644 --- a/mysql-test/r/myisam.result +++ b/mysql-test/r/myisam.result @@ -606,24 +606,6 @@ select count(*) from t1 where a is null; count(*) 2 drop table t1; -create table t1 (c1 int, index(c1)); -create table t2 (c1 int, index(c1)) engine=merge union=(t1); -insert into t1 values (1); -flush tables; -select * from t2; -c1 -1 -flush tables; -truncate table t1; -insert into t1 values (1); -flush tables; -select * from t2; -c1 -1 -truncate table t1; -ERROR HY000: MyISAM table 't1' is in use (most likely by a MERGE table). Try FLUSH TABLES. -insert into t1 values (1); -drop table t1,t2; create table t1 (c1 int, c2 varchar(4) not null default '', key(c2(3))) default charset=utf8; insert into t1 values (1,'A'), (2, 'B'), (3, 'A'); @@ -1794,6 +1776,39 @@ SELECT a FROM t1 FORCE INDEX (inx) WHERE a=1; a 1 DROP TABLE t1; +CREATE TABLE t1 (c1 INT, c2 INT, UNIQUE INDEX (c1), INDEX (c2)) ENGINE=MYISAM; +SHOW TABLE STATUS LIKE 't1'; +Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment +t1 MyISAM 10 Fixed 0 # # # 1024 # # # # # # # +INSERT INTO t1 VALUES (1,1); +SHOW TABLE STATUS LIKE 't1'; +Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment +t1 MyISAM 10 Fixed 1 # # # 3072 # # # # # # # +ALTER TABLE t1 DISABLE KEYS; +SHOW TABLE STATUS LIKE 't1'; +Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment +t1 MyISAM 10 Fixed 1 # # # 3072 # # # # # # # +ALTER TABLE t1 ENABLE KEYS; +SHOW TABLE STATUS LIKE 't1'; +Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment +t1 MyISAM 10 Fixed 1 # # # 3072 # # # # # # # +ALTER TABLE t1 DISABLE KEYS; +SHOW TABLE STATUS LIKE 't1'; +Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment +t1 MyISAM 10 Fixed 1 # # # 3072 # # # # # # # +ALTER TABLE t1 ENABLE KEYS; +SHOW TABLE STATUS LIKE 't1'; +Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment +t1 MyISAM 10 Fixed 1 # # # 3072 # # # # # # # +# Enable keys with parallel repair +SET @@myisam_repair_threads=2; +ALTER TABLE t1 DISABLE KEYS; +ALTER TABLE t1 ENABLE KEYS; +SET @@myisam_repair_threads=1; +CHECK TABLE t1 EXTENDED; +Table Op Msg_type Msg_text +test.t1 check status OK +DROP TABLE t1; End of 5.0 tests create table t1 (a int not null, key `a` (a) key_block_size=1024); show create table t1; diff --git a/mysql-test/r/myisampack.result b/mysql-test/r/myisampack.result new file mode 100644 index 00000000000..5f39d318234 --- /dev/null +++ b/mysql-test/r/myisampack.result @@ -0,0 +1,29 @@ +CREATE TABLE t1(c1 DOUBLE, c2 DOUBLE, c3 DOUBLE, c4 DOUBLE, c5 DOUBLE, +c6 DOUBLE, c7 DOUBLE, c8 DOUBLE, c9 DOUBLE, a INT PRIMARY KEY); +INSERT INTO t1 VALUES +(-3.31168791059336e-06,-3.19054655887874e-06,-1.06528081684847e-05,-1.227278240089e-06,-1.66718069164799e-06,-2.59038972510885e-06,-2.83145227805303e-06,-4.09678491270648e-07,-2.22610091291797e-06,6), +(0.0030743000272545,2.53222044316438e-05,2.78674650061845e-05,1.95914465544536e-05,1.7347572525984e-05,1.87513810069614e-05,1.69882826885005e-05,2.44449336987598e-05,1.89914629921774e-05,9), +(2.85229319423495e-05,3.05970988282259e-05,3.77161100113133e-05,2.3055238978766e-05,2.08241267364615e-05,2.28009504270553e-05,2.12070165658947e-05,2.84350091565409e-05,2.3366822910704e-05,3), +(0,0,0,0,0,0,0,0,0,12), +(3.24544577570754e-05,3.44619021870993e-05,4.37561613201124e-05,2.57556808726748e-05,2.3195354640561e-05,2.58532400758869e-05,2.34934241667179e-05,3.1621640063232e-05,2.58229982746189e-05,19), +(2.53222044316438e-05,0.00445071933455582,2.97447268116016e-05,2.12379514059868e-05,1.86777776502663e-05,2.0170058676712e-05,1.8946030385445e-05,2.66040037173511e-05,2.09161899668946e-05,20), +(3.03462382611645e-05,3.26517930083994e-05,3.5242025468662e-05,2.53219745106391e-05,2.24384532945004e-05,2.4052346047657e-05,2.23865572957053e-05,3.1634313969082e-05,2.48285463481801e-05,21), +(1.95914465544536e-05,2.12379514059868e-05,2.27808649037128e-05,0.000341724375366877,1.4512761275113e-05,1.56475828693953e-05,1.44372366441415e-05,2.07952121981765e-05,1.61488256935919e-05,28), +(1.7347572525984e-05,1.86777776502663e-05,2.04116907052727e-05,1.4512761275113e-05,0.000432162526082388,1.38116514014465e-05,1.2712914948904e-05,1.82503165178506e-05,1.43043075345922e-05,30), +(1.68339762136661e-05,1.77836497166611e-05,2.36328309295222e-05,1.30183423732016e-05,1.18674654241553e-05,1.32467273128652e-05,1.24581739117775e-05,1.55624190959406e-05,1.33010638508213e-05,31), +(1.89643062824415e-05,2.06997140070717e-05,2.29045490159364e-05,1.57918175731019e-05,1.39864987449492e-05,1.50580274578455e-05,1.45908734129609e-05,1.95329296993327e-05,1.5814709481221e-05,32), +(1.69882826885005e-05,1.8946030385445e-05,2.00820439721439e-05,1.44372366441415e-05,1.2712914948904e-05,1.35209686474184e-05,0.00261563314789896,1.78285095864627e-05,1.46699314500019e-05,34), +(2.0278186540684e-05,2.18923409729654e-05,2.39981539939738e-05,1.71774589459438e-05,1.54654355357383e-05,1.62731485707636e-05,1.49253140625051e-05,2.18229800160297e-05,1.71923561673718e-05,35), +(2.44449336987598e-05,2.66040037173511e-05,2.84860148925308e-05,2.07952121981765e-05,1.82503165178506e-05,1.97667730441441e-05,1.78285095864627e-05,0.00166478601822712,2.0299952103232e-05,36), +(1.89914629921774e-05,2.09161899668946e-05,2.26026841007872e-05,1.61488256935919e-05,1.43043075345922e-05,1.52609063290127e-05,1.46699314500019e-05,2.0299952103232e-05,0.00306670170971682,39), +(0,0,0,0,0,0,0,0,0,41), +(0,0,0,0,0,0,0,0,0,17), +(0,0,0,0,0,0,0,0,0,18), +(2.51880677333017e-05,2.63051795435778e-05,2.79874748974906e-05,2.02888886670845e-05,1.8178636318197e-05,1.91308527003585e-05,1.83260023644133e-05,2.4422300558171e-05,1.96411467520551e-05,44), +(2.22402118719591e-05,2.37546284320705e-05,2.58463051055541e-05,1.83391609130854e-05,1.6300720519646e-05,1.74559091886791e-05,1.63733785575587e-05,2.26616253279828e-05,1.79541237435621e-05,45), +(3.01092775359837e-05,3.23865212934412e-05,4.09444584045994e-05,0,2.15470966302776e-05,2.39082636344032e-05,2.28296706429177e-05,2.9007671511595e-05,2.44201138973326e-05,46); +FLUSH TABLES; +CHECK TABLE t1 EXTENDED; +Table Op Msg_type Msg_text +test.t1 check status OK +DROP TABLE t1; diff --git a/mysql-test/r/mysql.result b/mysql-test/r/mysql.result index 4e39fb28454..a4d96c1c243 100644 --- a/mysql-test/r/mysql.result +++ b/mysql-test/r/mysql.result @@ -178,5 +178,14 @@ ERROR at line 1: DELIMITER cannot contain a backslash character 1 1 1 +This is a file starting with UTF8 BOM 0xEFBBBF +This is a file starting with UTF8 BOM 0xEFBBBF End of 5.0 tests WARNING: --server-arg option not supported in this configuration. +Warning (Code 1286): Unknown table engine 'nonexistent' +Warning (Code 1266): Using storage engine MyISAM for table 't2' +Warning (Code 1286): Unknown table engine 'nonexistent2' +Warning (Code 1266): Using storage engine MyISAM for table 't2' +Error (Code 1050): Table 't2' already exists +drop tables t1, t2; +End of tests diff --git a/mysql-test/r/mysql_comments.result b/mysql-test/r/mysql_comments.result new file mode 100644 index 00000000000..7f1c0b50c5e --- /dev/null +++ b/mysql-test/r/mysql_comments.result @@ -0,0 +1,62 @@ +drop table if exists t1; +drop function if exists foofct; +drop procedure if exists empty; +drop procedure if exists foosp; +drop procedure if exists nicesp; +drop trigger if exists t1_empty; +drop trigger if exists t1_bi; +"Pass 1 : --disable-comments" +1 +1 +2 +2 +foofct("call 1") +call 1 +Function sql_mode Create Function character_set_client collation_connection Database Collation +foofct CREATE DEFINER=`root`@`localhost` FUNCTION `foofct`(x char(20)) RETURNS char(20) CHARSET latin1\nreturn\n\n\n\nx latin1 latin1_swedish_ci latin1_swedish_ci +foofct("call 2") +call 2 +Function sql_mode Create Function character_set_client collation_connection Database Collation +foofct CREATE DEFINER=`root`@`localhost` FUNCTION `foofct`(x char(20)) RETURNS char(20) CHARSET latin1\nbegin\n \n \n \n\n \n\n \n return x;\nend latin1 latin1_swedish_ci latin1_swedish_ci +Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation +empty CREATE DEFINER=`root`@`localhost` PROCEDURE `empty`()\nbegin\nend latin1 latin1_swedish_ci latin1_swedish_ci +id data +foo 42 +Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation +foosp CREATE DEFINER=`root`@`localhost` PROCEDURE `foosp`()\ninsert into test.t1\n\n\n\n\n \n\n \n values ("foo", 42) latin1 latin1_swedish_ci latin1_swedish_ci +Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation +nicesp CREATE DEFINER=`root`@`localhost` PROCEDURE `nicesp`(a int)\nbegin\n \n declare b int;\n declare c float;\n\n \n \n\n \nend latin1 latin1_swedish_ci latin1_swedish_ci +Trigger sql_mode SQL Original Statement character_set_client collation_connection Database Collation +t1_empty CREATE DEFINER=`root`@`localhost` trigger t1_empty after delete on t1\nfor each row\nbegin\nend latin1 latin1_swedish_ci latin1_swedish_ci +Trigger sql_mode SQL Original Statement character_set_client collation_connection Database Collation +t1_bi CREATE DEFINER=`root`@`localhost` trigger t1_bi before insert on t1\nfor each row\nbegin\n\n\n\n \n declare b int;\n declare c float;\n\n \n \n\n \n set NEW.data := 12;\nend latin1 latin1_swedish_ci latin1_swedish_ci +id data +trig 12 +"Pass 2 : --enable-comments" +1 +1 +2 +2 +foofct("call 1") +call 1 +Function sql_mode Create Function character_set_client collation_connection Database Collation +foofct CREATE DEFINER=`root`@`localhost` FUNCTION `foofct`(x char(20)) RETURNS char(20) CHARSET latin1\nreturn\n-- comment 1a\n# comment 1b\n/* comment 1c */\nx # after body, on same line latin1 latin1_swedish_ci latin1_swedish_ci +foofct("call 2") +call 2 +Function sql_mode Create Function character_set_client collation_connection Database Collation +foofct CREATE DEFINER=`root`@`localhost` FUNCTION `foofct`(x char(20)) RETURNS char(20) CHARSET latin1\nbegin\n -- comment 1a\n # comment 1b\n /*\n comment 1c\n */\n\n -- empty line below\n\n -- empty line above\n return x;\nend latin1 latin1_swedish_ci latin1_swedish_ci +Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation +empty CREATE DEFINER=`root`@`localhost` PROCEDURE `empty`()\nbegin\nend latin1 latin1_swedish_ci latin1_swedish_ci +id data +foo 42 +Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation +foosp CREATE DEFINER=`root`@`localhost` PROCEDURE `foosp`()\ninsert into test.t1\n## These comments are part of the procedure body, and should be kept.\n# Comment 2a\n-- Comment 2b\n/* Comment 2c */\n -- empty line below\n\n -- empty line above\n values ("foo", 42) # comment 3, still part of the body latin1 latin1_swedish_ci latin1_swedish_ci +Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation +nicesp CREATE DEFINER=`root`@`localhost` PROCEDURE `nicesp`(a int)\nbegin\n -- declare some variables here\n declare b int;\n declare c float;\n\n -- do more stuff here\n -- commented nicely and so on\n\n -- famous last words ...\nend latin1 latin1_swedish_ci latin1_swedish_ci +Trigger sql_mode SQL Original Statement character_set_client collation_connection Database Collation +t1_empty CREATE DEFINER=`root`@`localhost` trigger t1_empty after delete on t1\nfor each row\nbegin\nend latin1 latin1_swedish_ci latin1_swedish_ci +Trigger sql_mode SQL Original Statement character_set_client collation_connection Database Collation +t1_bi CREATE DEFINER=`root`@`localhost` trigger t1_bi before insert on t1\nfor each row\nbegin\n# comment 1a\n-- comment 1b\n/*\n comment 1c\n*/\n -- declare some variables here\n declare b int;\n declare c float;\n\n -- do more stuff here\n -- commented nicely and so on\n\n -- famous last words ...\n set NEW.data := 12;\nend latin1 latin1_swedish_ci latin1_swedish_ci +id data +trig 12 +End of 5.0 tests diff --git a/mysql-test/r/mysqlbinlog.result b/mysql-test/r/mysqlbinlog.result index 287fbd7e7f3..e6485720c49 100644 --- a/mysql-test/r/mysqlbinlog.result +++ b/mysql-test/r/mysqlbinlog.result @@ -326,6 +326,7 @@ flush logs; drop table t1; 1 drop table t1; +shell> mysqlbinlog std_data/corrupt-relay-bin.000624 > var/tmp/bug31793.sql End of 5.0 tests flush logs; BUG#31611: Security risk with BINLOG statement @@ -350,4 +351,5 @@ SELECT * FROM t1; a b 1 root@localhost DROP DATABASE mysqltest1; +DROP USER untrusted@localhost; End of 5.1 tests diff --git a/mysql-test/r/mysqlcheck.result b/mysql-test/r/mysqlcheck.result index 1d7ea8590dd..94b00de3666 100644 --- a/mysql-test/r/mysqlcheck.result +++ b/mysql-test/r/mysqlcheck.result @@ -1,4 +1,4 @@ -DROP TABLE IF EXISTS t1; +DROP TABLE IF EXISTS t1, `t``1`, `t 1`; drop view if exists v1; drop database if exists client_test_db; mysql.columns_priv OK @@ -57,6 +57,11 @@ test.t1 OK test.t1 OK drop view v1; drop table t1; +create table `t``1`(a int); +create table `t 1`(a int); +test.t 1 OK +test.t`1 OK +drop table `t``1`, `t 1`; create database d_bug25347; use d_bug25347; create table t_bug25347 (a int); @@ -93,3 +98,21 @@ drop table t_bug25347; drop database d_bug25347; use test; End of 5.0 tests +create table t1(a int); +create view v1 as select * from t1; +show tables; +Tables_in_test +t1 +v1 +show tables; +Tables_in_test +t1 +#mysql50#v-1 +v1 +show tables; +Tables_in_test +t1 +v1 +v-1 +drop view v1, `v-1`; +drop table t1; diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result index c0856314ba5..d07aed5317a 100644 --- a/mysql-test/r/mysqldump.result +++ b/mysql-test/r/mysqldump.result @@ -4212,5 +4212,24 @@ TRUNCATE mysql.event; SHOW EVENTS; Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator character_set_client collation_connection Database Collation # +# Bug#31113 mysqldump 5.1 can't handle a dash ("-") in database names +# +create database `test-database`; +use `test-database`; +create table test (a int); +DROP TABLE IF EXISTS `test`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; +CREATE TABLE `test` ( + `a` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +SET character_set_client = @saved_cs_client; +LOCK TABLES `test` WRITE; +/*!40000 ALTER TABLE `test` DISABLE KEYS */; +/*!40000 ALTER TABLE `test` ENABLE KEYS */; +UNLOCK TABLES; +drop database `test-database`; +use test; +# # End of 5.1 tests # diff --git a/mysql-test/r/no-threads.result b/mysql-test/r/no-threads.result index 50e52138be8..aefecd0f7bc 100644 --- a/mysql-test/r/no-threads.result +++ b/mysql-test/r/no-threads.result @@ -4,3 +4,6 @@ select 1+1; select 1+2; 1+2 3 +SHOW GLOBAL VARIABLES LIKE 'thread_handling'; +Variable_name Value +thread_handling no-threads diff --git a/mysql-test/r/olap.result b/mysql-test/r/olap.result index 63c9590401c..4540c9d5218 100644 --- a/mysql-test/r/olap.result +++ b/mysql-test/r/olap.result @@ -726,3 +726,11 @@ count(a) 3 drop table t1; ############################################################## +CREATE TABLE t1(a INT); +INSERT INTO t1 VALUES(0); +SELECT 1 FROM t1 GROUP BY (DATE(NULL)) WITH ROLLUP; +1 +1 +1 +DROP TABLE t1; +End of 5.0 tests diff --git a/mysql-test/r/outfile_loaddata.result b/mysql-test/r/outfile_loaddata.result new file mode 100644 index 00000000000..1bcaf308b7c --- /dev/null +++ b/mysql-test/r/outfile_loaddata.result @@ -0,0 +1,85 @@ +DROP TABLE IF EXISTS t1, t2; +# +# Bug#31663 FIELDS TERMINATED BY special character +# +CREATE TABLE t1 (i1 int, i2 int, c1 VARCHAR(256), c2 VARCHAR(256)); +INSERT INTO t1 VALUES (101, 202, '-r-', '=raker='); +# FIELDS TERMINATED BY 'raker', warning: +SELECT * INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/bug31663.txt' FIELDS TERMINATED BY 'raker' FROM t1; +Warnings: +Warning 1475 First character of the FIELDS TERMINATED string is ambiguous; please use non-optional and non-empty FIELDS ENCLOSED BY +SELECT LOAD_FILE('MYSQLTEST_VARDIR/tmp/bug31663.txt'); +LOAD_FILE('MYSQLTEST_VARDIR/tmp/bug31663.txt') +101raker202raker-r-raker=raker= + +CREATE TABLE t2 SELECT * FROM t1; +LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/bug31663.txt' INTO TABLE t2 FIELDS TERMINATED BY 'raker'; +Warnings: +Warning 1262 Row 1 was truncated; it contained more data than there were input columns +SELECT * FROM t2; +i1 i2 c1 c2 +101 202 -r- =raker= +101 202 -r- = +DROP TABLE t2; +# Only numeric fields, FIELDS TERMINATED BY 'r', no warnings: +SELECT i1, i2 INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/bug31663.txt' FIELDS TERMINATED BY 'r' FROM t1; +SELECT LOAD_FILE('MYSQLTEST_VARDIR/tmp/bug31663.txt'); +LOAD_FILE('MYSQLTEST_VARDIR/tmp/bug31663.txt') +101r202 + +CREATE TABLE t2 SELECT i1, i2 FROM t1; +LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/bug31663.txt' INTO TABLE t2 FIELDS TERMINATED BY 'r'; +SELECT i1, i2 FROM t2; +i1 i2 +101 202 +101 202 +DROP TABLE t2; +# FIELDS TERMINATED BY '0', warning: +SELECT * INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/bug31663.txt' FIELDS TERMINATED BY '0' FROM t1; +Warnings: +Warning 1475 First character of the FIELDS TERMINATED string is ambiguous; please use non-optional and non-empty FIELDS ENCLOSED BY +SELECT LOAD_FILE('MYSQLTEST_VARDIR/tmp/bug31663.txt'); +LOAD_FILE('MYSQLTEST_VARDIR/tmp/bug31663.txt') +10102020-r-0=raker= + +CREATE TABLE t2 SELECT * FROM t1; +LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/bug31663.txt' INTO TABLE t2 FIELDS TERMINATED BY '0'; +Warnings: +Warning 1262 Row 1 was truncated; it contained more data than there were input columns +SELECT * FROM t2; +i1 i2 c1 c2 +101 202 -r- =raker= +1 1 2 2 +DROP TABLE t2; +# FIELDS OPTIONALLY ENCLOSED BY '"' TERMINATED BY '0', warning: +SELECT * INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/bug31663.txt' FIELDS OPTIONALLY ENCLOSED BY '"' TERMINATED BY '0' FROM t1; +Warnings: +Warning 1475 First character of the FIELDS TERMINATED string is ambiguous; please use non-optional and non-empty FIELDS ENCLOSED BY +SELECT LOAD_FILE('MYSQLTEST_VARDIR/tmp/bug31663.txt'); +LOAD_FILE('MYSQLTEST_VARDIR/tmp/bug31663.txt') +10102020"-r-"0"=raker=" + +CREATE TABLE t2 SELECT * FROM t1; +LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/bug31663.txt' INTO TABLE t2 FIELDS OPTIONALLY ENCLOSED BY '"' TERMINATED BY '0'; +Warnings: +Warning 1262 Row 1 was truncated; it contained more data than there were input columns +SELECT * FROM t2; +i1 i2 c1 c2 +101 202 -r- =raker= +1 1 2 2 +DROP TABLE t2; +# Only string fields, FIELDS OPTIONALLY ENCLOSED BY '"' TERMINATED BY '0', no warnings: +SELECT c1, c2 INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/bug31663.txt' FIELDS OPTIONALLY ENCLOSED BY '"' TERMINATED BY '0' FROM t1; +SELECT LOAD_FILE('MYSQLTEST_VARDIR/tmp/bug31663.txt'); +LOAD_FILE('MYSQLTEST_VARDIR/tmp/bug31663.txt') +"-r-"0"=raker=" + +CREATE TABLE t2 SELECT c1, c2 FROM t1; +LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/bug31663.txt' INTO TABLE t2 FIELDS OPTIONALLY ENCLOSED BY '"' TERMINATED BY '0'; +SELECT c1, c2 FROM t2; +c1 c2 +-r- =raker= +-r- =raker= +DROP TABLE t2; +DROP TABLE t1; +# End of 5.0 tests. diff --git a/mysql-test/r/parser.result b/mysql-test/r/parser.result index 76326f65f08..ef53f227ec0 100644 --- a/mysql-test/r/parser.result +++ b/mysql-test/r/parser.result @@ -484,3 +484,46 @@ select atan(10, 20 "p2"); ERROR 42000: Incorrect parameters in the call to native function 'atan' select atan(10 AS p1, 20 AS p2); ERROR 42000: Incorrect parameters in the call to native function 'atan' +DROP TABLE IF EXISTS t1; +SELECT STR_TO_DATE('10:00 PM', '%h:%i %p') + INTERVAL 10 MINUTE; +STR_TO_DATE('10:00 PM', '%h:%i %p') + INTERVAL 10 MINUTE +NULL +SELECT STR_TO_DATE('10:00 PM', '%h:%i %p') + INTERVAL (INTERVAL(1,2,3) + 1) MINUTE; +STR_TO_DATE('10:00 PM', '%h:%i %p') + INTERVAL (INTERVAL(1,2,3) + 1) MINUTE +NULL +SELECT "1997-12-31 23:59:59" + INTERVAL 1 SECOND; +"1997-12-31 23:59:59" + INTERVAL 1 SECOND +1998-01-01 00:00:00 +SELECT 1 + INTERVAL(1,0,1,2) + 1; +1 + INTERVAL(1,0,1,2) + 1 +4 +SELECT INTERVAL(1^1,0,1,2) + 1; +INTERVAL(1^1,0,1,2) + 1 +2 +SELECT INTERVAL(1,0+1,2,3) * 5.5; +INTERVAL(1,0+1,2,3) * 5.5 +5.5 +SELECT INTERVAL(3,3,1+3,4+4) / 0.5; +INTERVAL(3,3,1+3,4+4) / 0.5 +2.0000 +SELECT (INTERVAL(1,0,1,2) + 5) * 7 + INTERVAL(1,0,1,2) / 2; +(INTERVAL(1,0,1,2) + 5) * 7 + INTERVAL(1,0,1,2) / 2 +50.0000 +SELECT INTERVAL(1,0,1,2) + 1, 5 * INTERVAL(1,0,1,2); +INTERVAL(1,0,1,2) + 1 5 * INTERVAL(1,0,1,2) +3 10 +SELECT INTERVAL(0,(1*5)/2) + INTERVAL(5,4,3); +INTERVAL(0,(1*5)/2) + INTERVAL(5,4,3) +2 +SELECT 1^1 + INTERVAL 1+1 SECOND & 1 + INTERVAL 1+1 SECOND; +1^1 + INTERVAL 1+1 SECOND & 1 + INTERVAL 1+1 SECOND +NULL +SELECT 1%2 - INTERVAL 1^1 SECOND | 1%2 - INTERVAL 1^1 SECOND; +1%2 - INTERVAL 1^1 SECOND | 1%2 - INTERVAL 1^1 SECOND +NULL +CREATE TABLE t1 (a INT, b DATETIME); +INSERT INTO t1 VALUES (INTERVAL(3,2,1) + 1, "1997-12-31 23:59:59" + INTERVAL 1 SECOND); +SELECT * FROM t1 WHERE a = INTERVAL(3,2,1) + 1; +a b +3 1998-01-01 00:00:00 +DROP TABLE t1; diff --git a/mysql-test/r/partition.result b/mysql-test/r/partition.result index b8ca0a247d9..7c25e948d6c 100644 --- a/mysql-test/r/partition.result +++ b/mysql-test/r/partition.result @@ -1,4 +1,32 @@ drop table if exists t1; +CREATE TABLE t1 ( +d DATE NOT NULL +) +PARTITION BY RANGE( YEAR(d) ) ( +PARTITION p0 VALUES LESS THAN (1960), +PARTITION p1 VALUES LESS THAN (1970), +PARTITION p2 VALUES LESS THAN (1980), +PARTITION p3 VALUES LESS THAN (1990) +); +ALTER TABLE t1 ADD PARTITION ( +PARTITION `p5` VALUES LESS THAN (2010) +COMMENT 'APSTART \' APEND' +); +SELECT * FROM t1 LIMIT 1; +d +DROP TABLE t1; +create table t1 (id int auto_increment, s1 int, primary key (id)); +insert into t1 values (null,1); +insert into t1 values (null,6); +select * from t1; +id s1 +1 1 +2 6 +alter table t1 partition by range (id) ( +partition p0 values less than (3), +partition p1 values less than maxvalue +); +drop table t1; create table t1 (a int) partition by key(a) partitions 0.2+e1; @@ -261,6 +289,13 @@ select * from t1 where a = 4; a b 4 4 drop table t1; +CREATE TABLE t1 (c1 INT, c2 INT, PRIMARY KEY USING BTREE (c1,c2)) ENGINE=MEMORY +PARTITION BY KEY(c2,c1) PARTITIONS 4; +INSERT INTO t1 VALUES (0,0),(1,1),(2,2),(3,3),(4,4),(5,5),(6,6); +SELECT * FROM t1 WHERE c1 = 4; +c1 c2 +4 4 +DROP TABLE t1; CREATE TABLE t1 (a int) PARTITION BY LIST (a) PARTITIONS 1 @@ -687,7 +722,7 @@ partition by range (a) alter table t1 add partition (partition p1 values in (2)); ERROR HY000: Only LIST PARTITIONING can use VALUES IN in partition definition alter table t1 add partition (partition p1); -ERROR HY000: RANGE PARTITIONING requires definition of VALUES LESS THAN for each partition +ERROR HY000: Syntax error: RANGE PARTITIONING requires definition of VALUES LESS THAN for each partition drop table t1; create table t1 (a int) partition by list (a) @@ -695,7 +730,7 @@ partition by list (a) alter table t1 add partition (partition p1 values less than (2)); ERROR HY000: Only RANGE PARTITIONING can use VALUES LESS THAN in partition definition alter table t1 add partition (partition p1); -ERROR HY000: LIST PARTITIONING requires definition of VALUES IN for each partition +ERROR HY000: Syntax error: LIST PARTITIONING requires definition of VALUES IN for each partition drop table t1; create table t1 (a int) partition by hash (a) @@ -1257,4 +1292,19 @@ t1 CREATE TABLE `t1` ( `b` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 /*!50100 PARTITION BY RANGE (b) (PARTITION p1 VALUES LESS THAN (10) ENGINE = MyISAM, PARTITION p2 VALUES LESS THAN (20) ENGINE = MyISAM) */ drop table t1, t2; +create table t1 +(s1 timestamp on update current_timestamp, s2 int) +partition by key(s1) partitions 3; +insert into t1 values (null,null); +drop table t1; +CREATE TABLE t1(a int) +PARTITION BY RANGE (a) ( +PARTITION p1 VALUES LESS THAN (10), +PARTITION p2 VALUES LESS THAN (20) +); +ALTER TABLE t1 OPTIMIZE PARTITION p1 EXTENDED; +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 'EXTENDED' at line 1 +ALTER TABLE t1 ANALYZE PARTITION p1 EXTENDED; +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 'EXTENDED' at line 1 +DROP TABLE t1; End of 5.1 tests diff --git a/mysql-test/r/partition_02myisam.result b/mysql-test/r/partition_02myisam.result deleted file mode 100644 index 55263e4f8ce..00000000000 --- a/mysql-test/r/partition_02myisam.result +++ /dev/null @@ -1,1725 +0,0 @@ -SET SESSION storage_engine='MYISAM'; -SET @max_row = 200; -SET AUTOCOMMIT= 1; - -#------------------------------------------------------------------------ -# There are several testcases disabled because ouf the open bugs -# #15407 , #15408 , #15890 , #15961 , #13447 , #15966 , #15968, #16370 -#------------------------------------------------------------------------ - -#------------------------------------------------------------------------ -# 0. Setting of auxiliary variables + Creation of an auxiliary table -# needed in all testcases -#------------------------------------------------------------------------ -DROP TABLE IF EXISTS t0_template; -CREATE TABLE t0_template ( f1 INTEGER, f2 char(20), PRIMARY KEY(f1)) -ENGINE = MEMORY; -# Logging of INSERTs into t0_template suppressed - -#------------------------------------------------------------------------ -# 1. Some syntax checks -#------------------------------------------------------------------------ -# 1.1 Subpartioned table without subpartitioning rule must be rejected -DROP TABLE IF EXISTS t1; -# FIXME Implement testcases, where it is checked that all create and -# alter table statements -# - with missing mandatory parameters are rejected -# - with optional parameters are accepted -# - with wrong combinations of optional parameters are rejected -# - ............ - -#------------------------------------------------------------------------ -# 2. Checks where the engine is assigned on all supported (CREATE TABLE -# statement) positions + basic operations on the tables -# Storage engine mixups are currently (2005-12-23) not supported -#------------------------------------------------------------------------ -DROP TABLE IF EXISTS t1; -# 2.1 non partitioned table (for comparison) -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) ENGINE = 'MYISAM'; -SHOW CREATE TABLE t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `f1` int(11) DEFAULT NULL, - `f2` char(20) DEFAULT NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1 -SELECT COUNT(*) = 0 AS my_value FROM t1; -my_value -1 -INSERT INTO t1 SELECT * FROM t0_template WHERE f1 BETWEEN 1 AND 200; -SELECT (COUNT(*) = 200) AND (MIN(f1) = 1) AND (MAX(f1) = 200) -AS my_value FROM t1; -my_value -1 -UPDATE t1 SET f1 = f1 + 200 -WHERE f1 BETWEEN 100 - 50 AND 100 + 50; -SELECT (COUNT(*) = 200) AND (MIN(f1) = 1) AND (MAX(f1) = 100 + 50 + 200 ) -AS my_value FROM t1; -my_value -1 -DELETE FROM t1 -WHERE f1 BETWEEN 100 - 50 + 200 AND 100 + 50 + 200; -SELECT (COUNT(*) = 200 - 50 - 50 - 1) AND (MIN(f1) = 1) AND (MAX(f1) = 200) -AS my_value FROM t1; -my_value -1 -INSERT INTO t1 SET f1 = 0 , f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 0 AND f2 = '#######'; -my_value -1 -INSERT INTO t1 SET f1 = 200 + 1, f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 200 + 1 AND f2 = '#######'; -my_value -1 -UPDATE t1 SET f1 = 200 + 2, f2 = 'ZZZZZZZ' - WHERE f1 = 0 AND f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 200 + 2 AND f2 = 'ZZZZZZZ'; -my_value -1 -DELETE FROM t1 WHERE f1 = 200 + 2 AND f2 = 'ZZZZZZZ'; -SELECT COUNT(*) = 0 AS my_value FROM t1 WHERE f2 = 'ZZZZZZZ'; -my_value -1 -TRUNCATE t1; -SELECT COUNT(*) = 0 AS my_value FROM t1; -my_value -1 -DROP TABLE t1; -# 2.2 Assignment of storage engine just after column list only -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) ENGINE = 'MYISAM' -PARTITION BY HASH(f1) PARTITIONS 2; -SHOW CREATE TABLE t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `f1` int(11) DEFAULT NULL, - `f2` char(20) DEFAULT NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1 /*!50100 PARTITION BY HASH (f1) PARTITIONS 2 */ -SELECT COUNT(*) = 0 AS my_value FROM t1; -my_value -1 -INSERT INTO t1 SELECT * FROM t0_template WHERE f1 BETWEEN 1 AND 200; -SELECT (COUNT(*) = 200) AND (MIN(f1) = 1) AND (MAX(f1) = 200) -AS my_value FROM t1; -my_value -1 -UPDATE t1 SET f1 = f1 + 200 -WHERE f1 BETWEEN 100 - 50 AND 100 + 50; -SELECT (COUNT(*) = 200) AND (MIN(f1) = 1) AND (MAX(f1) = 100 + 50 + 200 ) -AS my_value FROM t1; -my_value -1 -DELETE FROM t1 -WHERE f1 BETWEEN 100 - 50 + 200 AND 100 + 50 + 200; -SELECT (COUNT(*) = 200 - 50 - 50 - 1) AND (MIN(f1) = 1) AND (MAX(f1) = 200) -AS my_value FROM t1; -my_value -1 -INSERT INTO t1 SET f1 = 0 , f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 0 AND f2 = '#######'; -my_value -1 -INSERT INTO t1 SET f1 = 200 + 1, f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 200 + 1 AND f2 = '#######'; -my_value -1 -UPDATE t1 SET f1 = 200 + 2, f2 = 'ZZZZZZZ' - WHERE f1 = 0 AND f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 200 + 2 AND f2 = 'ZZZZZZZ'; -my_value -1 -DELETE FROM t1 WHERE f1 = 200 + 2 AND f2 = 'ZZZZZZZ'; -SELECT COUNT(*) = 0 AS my_value FROM t1 WHERE f2 = 'ZZZZZZZ'; -my_value -1 -TRUNCATE t1; -SELECT COUNT(*) = 0 AS my_value FROM t1; -my_value -1 -DROP TABLE t1; -# 2.3 Assignment of storage engine just after partition or subpartition -# name only -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY HASH(f1) -( PARTITION part1 STORAGE ENGINE = 'MYISAM', -PARTITION part2 STORAGE ENGINE = 'MYISAM' -); -SHOW CREATE TABLE t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `f1` int(11) DEFAULT NULL, - `f2` char(20) DEFAULT NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1 /*!50100 PARTITION BY HASH (f1) (PARTITION part1 ENGINE = MyISAM, PARTITION part2 ENGINE = MyISAM) */ -SELECT COUNT(*) = 0 AS my_value FROM t1; -my_value -1 -INSERT INTO t1 SELECT * FROM t0_template WHERE f1 BETWEEN 1 AND 200; -SELECT (COUNT(*) = 200) AND (MIN(f1) = 1) AND (MAX(f1) = 200) -AS my_value FROM t1; -my_value -1 -UPDATE t1 SET f1 = f1 + 200 -WHERE f1 BETWEEN 100 - 50 AND 100 + 50; -SELECT (COUNT(*) = 200) AND (MIN(f1) = 1) AND (MAX(f1) = 100 + 50 + 200 ) -AS my_value FROM t1; -my_value -1 -DELETE FROM t1 -WHERE f1 BETWEEN 100 - 50 + 200 AND 100 + 50 + 200; -SELECT (COUNT(*) = 200 - 50 - 50 - 1) AND (MIN(f1) = 1) AND (MAX(f1) = 200) -AS my_value FROM t1; -my_value -1 -INSERT INTO t1 SET f1 = 0 , f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 0 AND f2 = '#######'; -my_value -1 -INSERT INTO t1 SET f1 = 200 + 1, f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 200 + 1 AND f2 = '#######'; -my_value -1 -UPDATE t1 SET f1 = 200 + 2, f2 = 'ZZZZZZZ' - WHERE f1 = 0 AND f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 200 + 2 AND f2 = 'ZZZZZZZ'; -my_value -1 -DELETE FROM t1 WHERE f1 = 200 + 2 AND f2 = 'ZZZZZZZ'; -SELECT COUNT(*) = 0 AS my_value FROM t1 WHERE f2 = 'ZZZZZZZ'; -my_value -1 -TRUNCATE t1; -SELECT COUNT(*) = 0 AS my_value FROM t1; -my_value -1 -DROP TABLE t1; -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY RANGE(f1) -SUBPARTITION BY HASH(f1) -( PARTITION part1 VALUES LESS THAN (100) -(SUBPARTITION subpart11 STORAGE ENGINE = 'MYISAM', -SUBPARTITION subpart12 STORAGE ENGINE = 'MYISAM'), -PARTITION part2 VALUES LESS THAN (2147483647) -(SUBPARTITION subpart21 STORAGE ENGINE = 'MYISAM', -SUBPARTITION subpart22 STORAGE ENGINE = 'MYISAM') -); -SHOW CREATE TABLE t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `f1` int(11) DEFAULT NULL, - `f2` char(20) DEFAULT NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1 /*!50100 PARTITION BY RANGE (f1) SUBPARTITION BY HASH (f1) (PARTITION part1 VALUES LESS THAN (100) (SUBPARTITION subpart11 ENGINE = MyISAM, SUBPARTITION subpart12 ENGINE = MyISAM), PARTITION part2 VALUES LESS THAN (2147483647) (SUBPARTITION subpart21 ENGINE = MyISAM, SUBPARTITION subpart22 ENGINE = MyISAM)) */ -SELECT COUNT(*) = 0 AS my_value FROM t1; -my_value -1 -INSERT INTO t1 SELECT * FROM t0_template WHERE f1 BETWEEN 1 AND 200; -SELECT (COUNT(*) = 200) AND (MIN(f1) = 1) AND (MAX(f1) = 200) -AS my_value FROM t1; -my_value -1 -UPDATE t1 SET f1 = f1 + 200 -WHERE f1 BETWEEN 100 - 50 AND 100 + 50; -SELECT (COUNT(*) = 200) AND (MIN(f1) = 1) AND (MAX(f1) = 100 + 50 + 200 ) -AS my_value FROM t1; -my_value -1 -DELETE FROM t1 -WHERE f1 BETWEEN 100 - 50 + 200 AND 100 + 50 + 200; -SELECT (COUNT(*) = 200 - 50 - 50 - 1) AND (MIN(f1) = 1) AND (MAX(f1) = 200) -AS my_value FROM t1; -my_value -1 -INSERT INTO t1 SET f1 = 0 , f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 0 AND f2 = '#######'; -my_value -1 -INSERT INTO t1 SET f1 = 200 + 1, f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 200 + 1 AND f2 = '#######'; -my_value -1 -UPDATE t1 SET f1 = 200 + 2, f2 = 'ZZZZZZZ' - WHERE f1 = 0 AND f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 200 + 2 AND f2 = 'ZZZZZZZ'; -my_value -1 -DELETE FROM t1 WHERE f1 = 200 + 2 AND f2 = 'ZZZZZZZ'; -SELECT COUNT(*) = 0 AS my_value FROM t1 WHERE f2 = 'ZZZZZZZ'; -my_value -1 -TRUNCATE t1; -SELECT COUNT(*) = 0 AS my_value FROM t1; -my_value -1 -DROP TABLE t1; -# 2.4 Some but not all named partitions or subpartitions get a storage -# engine assigned -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY HASH(f1) -( PARTITION part1 STORAGE ENGINE = 'MYISAM', -PARTITION part2 -); -SHOW CREATE TABLE t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `f1` int(11) DEFAULT NULL, - `f2` char(20) DEFAULT NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1 /*!50100 PARTITION BY HASH (f1) (PARTITION part1 ENGINE = MyISAM, PARTITION part2 ENGINE = MyISAM) */ -SELECT COUNT(*) = 0 AS my_value FROM t1; -my_value -1 -INSERT INTO t1 SELECT * FROM t0_template WHERE f1 BETWEEN 1 AND 200; -SELECT (COUNT(*) = 200) AND (MIN(f1) = 1) AND (MAX(f1) = 200) -AS my_value FROM t1; -my_value -1 -UPDATE t1 SET f1 = f1 + 200 -WHERE f1 BETWEEN 100 - 50 AND 100 + 50; -SELECT (COUNT(*) = 200) AND (MIN(f1) = 1) AND (MAX(f1) = 100 + 50 + 200 ) -AS my_value FROM t1; -my_value -1 -DELETE FROM t1 -WHERE f1 BETWEEN 100 - 50 + 200 AND 100 + 50 + 200; -SELECT (COUNT(*) = 200 - 50 - 50 - 1) AND (MIN(f1) = 1) AND (MAX(f1) = 200) -AS my_value FROM t1; -my_value -1 -INSERT INTO t1 SET f1 = 0 , f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 0 AND f2 = '#######'; -my_value -1 -INSERT INTO t1 SET f1 = 200 + 1, f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 200 + 1 AND f2 = '#######'; -my_value -1 -UPDATE t1 SET f1 = 200 + 2, f2 = 'ZZZZZZZ' - WHERE f1 = 0 AND f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 200 + 2 AND f2 = 'ZZZZZZZ'; -my_value -1 -DELETE FROM t1 WHERE f1 = 200 + 2 AND f2 = 'ZZZZZZZ'; -SELECT COUNT(*) = 0 AS my_value FROM t1 WHERE f2 = 'ZZZZZZZ'; -my_value -1 -TRUNCATE t1; -SELECT COUNT(*) = 0 AS my_value FROM t1; -my_value -1 -DROP TABLE t1; -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY HASH(f1) -( PARTITION part1 , -PARTITION part2 STORAGE ENGINE = 'MYISAM' -); -SHOW CREATE TABLE t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `f1` int(11) DEFAULT NULL, - `f2` char(20) DEFAULT NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1 /*!50100 PARTITION BY HASH (f1) (PARTITION part1 ENGINE = MyISAM, PARTITION part2 ENGINE = MyISAM) */ -SELECT COUNT(*) = 0 AS my_value FROM t1; -my_value -1 -INSERT INTO t1 SELECT * FROM t0_template WHERE f1 BETWEEN 1 AND 200; -SELECT (COUNT(*) = 200) AND (MIN(f1) = 1) AND (MAX(f1) = 200) -AS my_value FROM t1; -my_value -1 -UPDATE t1 SET f1 = f1 + 200 -WHERE f1 BETWEEN 100 - 50 AND 100 + 50; -SELECT (COUNT(*) = 200) AND (MIN(f1) = 1) AND (MAX(f1) = 100 + 50 + 200 ) -AS my_value FROM t1; -my_value -1 -DELETE FROM t1 -WHERE f1 BETWEEN 100 - 50 + 200 AND 100 + 50 + 200; -SELECT (COUNT(*) = 200 - 50 - 50 - 1) AND (MIN(f1) = 1) AND (MAX(f1) = 200) -AS my_value FROM t1; -my_value -1 -INSERT INTO t1 SET f1 = 0 , f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 0 AND f2 = '#######'; -my_value -1 -INSERT INTO t1 SET f1 = 200 + 1, f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 200 + 1 AND f2 = '#######'; -my_value -1 -UPDATE t1 SET f1 = 200 + 2, f2 = 'ZZZZZZZ' - WHERE f1 = 0 AND f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 200 + 2 AND f2 = 'ZZZZZZZ'; -my_value -1 -DELETE FROM t1 WHERE f1 = 200 + 2 AND f2 = 'ZZZZZZZ'; -SELECT COUNT(*) = 0 AS my_value FROM t1 WHERE f2 = 'ZZZZZZZ'; -my_value -1 -TRUNCATE t1; -SELECT COUNT(*) = 0 AS my_value FROM t1; -my_value -1 -DROP TABLE t1; -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY RANGE(f1) -SUBPARTITION BY HASH(f1) -( PARTITION part1 VALUES LESS THAN (100) -(SUBPARTITION subpart11, -SUBPARTITION subpart12 STORAGE ENGINE = 'MYISAM'), -PARTITION part2 VALUES LESS THAN (2147483647) -(SUBPARTITION subpart21 STORAGE ENGINE = 'MYISAM', -SUBPARTITION subpart22 STORAGE ENGINE = 'MYISAM') -); -SHOW CREATE TABLE t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `f1` int(11) DEFAULT NULL, - `f2` char(20) DEFAULT NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1 /*!50100 PARTITION BY RANGE (f1) SUBPARTITION BY HASH (f1) (PARTITION part1 VALUES LESS THAN (100) (SUBPARTITION subpart11 ENGINE = MyISAM, SUBPARTITION subpart12 ENGINE = MyISAM), PARTITION part2 VALUES LESS THAN (2147483647) (SUBPARTITION subpart21 ENGINE = MyISAM, SUBPARTITION subpart22 ENGINE = MyISAM)) */ -SELECT COUNT(*) = 0 AS my_value FROM t1; -my_value -1 -INSERT INTO t1 SELECT * FROM t0_template WHERE f1 BETWEEN 1 AND 200; -SELECT (COUNT(*) = 200) AND (MIN(f1) = 1) AND (MAX(f1) = 200) -AS my_value FROM t1; -my_value -1 -UPDATE t1 SET f1 = f1 + 200 -WHERE f1 BETWEEN 100 - 50 AND 100 + 50; -SELECT (COUNT(*) = 200) AND (MIN(f1) = 1) AND (MAX(f1) = 100 + 50 + 200 ) -AS my_value FROM t1; -my_value -1 -DELETE FROM t1 -WHERE f1 BETWEEN 100 - 50 + 200 AND 100 + 50 + 200; -SELECT (COUNT(*) = 200 - 50 - 50 - 1) AND (MIN(f1) = 1) AND (MAX(f1) = 200) -AS my_value FROM t1; -my_value -1 -INSERT INTO t1 SET f1 = 0 , f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 0 AND f2 = '#######'; -my_value -1 -INSERT INTO t1 SET f1 = 200 + 1, f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 200 + 1 AND f2 = '#######'; -my_value -1 -UPDATE t1 SET f1 = 200 + 2, f2 = 'ZZZZZZZ' - WHERE f1 = 0 AND f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 200 + 2 AND f2 = 'ZZZZZZZ'; -my_value -1 -DELETE FROM t1 WHERE f1 = 200 + 2 AND f2 = 'ZZZZZZZ'; -SELECT COUNT(*) = 0 AS my_value FROM t1 WHERE f2 = 'ZZZZZZZ'; -my_value -1 -TRUNCATE t1; -SELECT COUNT(*) = 0 AS my_value FROM t1; -my_value -1 -DROP TABLE t1; -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY RANGE(f1) -SUBPARTITION BY HASH(f1) -( PARTITION part1 VALUES LESS THAN (100) -(SUBPARTITION subpart11 STORAGE ENGINE = 'MYISAM', -SUBPARTITION subpart12 STORAGE ENGINE = 'MYISAM'), -PARTITION part2 VALUES LESS THAN (2147483647) -(SUBPARTITION subpart21, -SUBPARTITION subpart22 ) -); -SHOW CREATE TABLE t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `f1` int(11) DEFAULT NULL, - `f2` char(20) DEFAULT NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1 /*!50100 PARTITION BY RANGE (f1) SUBPARTITION BY HASH (f1) (PARTITION part1 VALUES LESS THAN (100) (SUBPARTITION subpart11 ENGINE = MyISAM, SUBPARTITION subpart12 ENGINE = MyISAM), PARTITION part2 VALUES LESS THAN (2147483647) (SUBPARTITION subpart21 ENGINE = MyISAM, SUBPARTITION subpart22 ENGINE = MyISAM)) */ -SELECT COUNT(*) = 0 AS my_value FROM t1; -my_value -1 -INSERT INTO t1 SELECT * FROM t0_template WHERE f1 BETWEEN 1 AND 200; -SELECT (COUNT(*) = 200) AND (MIN(f1) = 1) AND (MAX(f1) = 200) -AS my_value FROM t1; -my_value -1 -UPDATE t1 SET f1 = f1 + 200 -WHERE f1 BETWEEN 100 - 50 AND 100 + 50; -SELECT (COUNT(*) = 200) AND (MIN(f1) = 1) AND (MAX(f1) = 100 + 50 + 200 ) -AS my_value FROM t1; -my_value -1 -DELETE FROM t1 -WHERE f1 BETWEEN 100 - 50 + 200 AND 100 + 50 + 200; -SELECT (COUNT(*) = 200 - 50 - 50 - 1) AND (MIN(f1) = 1) AND (MAX(f1) = 200) -AS my_value FROM t1; -my_value -1 -INSERT INTO t1 SET f1 = 0 , f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 0 AND f2 = '#######'; -my_value -1 -INSERT INTO t1 SET f1 = 200 + 1, f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 200 + 1 AND f2 = '#######'; -my_value -1 -UPDATE t1 SET f1 = 200 + 2, f2 = 'ZZZZZZZ' - WHERE f1 = 0 AND f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 200 + 2 AND f2 = 'ZZZZZZZ'; -my_value -1 -DELETE FROM t1 WHERE f1 = 200 + 2 AND f2 = 'ZZZZZZZ'; -SELECT COUNT(*) = 0 AS my_value FROM t1 WHERE f2 = 'ZZZZZZZ'; -my_value -1 -TRUNCATE t1; -SELECT COUNT(*) = 0 AS my_value FROM t1; -my_value -1 -DROP TABLE t1; -# 2.5 Storage engine assignment after partition name + after name of -# subpartitions belonging to another partition -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY RANGE(f1) -SUBPARTITION BY HASH(f1) -( PARTITION part1 VALUES LESS THAN (100) ENGINE = 'MYISAM' -(SUBPARTITION subpart11, -SUBPARTITION subpart12), -PARTITION part2 VALUES LESS THAN (2147483647) -(SUBPARTITION subpart21 STORAGE ENGINE = 'MYISAM', -SUBPARTITION subpart22 STORAGE ENGINE = 'MYISAM') -); -SHOW CREATE TABLE t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `f1` int(11) DEFAULT NULL, - `f2` char(20) DEFAULT NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1 /*!50100 PARTITION BY RANGE (f1) SUBPARTITION BY HASH (f1) (PARTITION part1 VALUES LESS THAN (100) (SUBPARTITION subpart11 ENGINE = MyISAM, SUBPARTITION subpart12 ENGINE = MyISAM), PARTITION part2 VALUES LESS THAN (2147483647) (SUBPARTITION subpart21 ENGINE = MyISAM, SUBPARTITION subpart22 ENGINE = MyISAM)) */ -SELECT COUNT(*) = 0 AS my_value FROM t1; -my_value -1 -INSERT INTO t1 SELECT * FROM t0_template WHERE f1 BETWEEN 1 AND 200; -SELECT (COUNT(*) = 200) AND (MIN(f1) = 1) AND (MAX(f1) = 200) -AS my_value FROM t1; -my_value -1 -UPDATE t1 SET f1 = f1 + 200 -WHERE f1 BETWEEN 100 - 50 AND 100 + 50; -SELECT (COUNT(*) = 200) AND (MIN(f1) = 1) AND (MAX(f1) = 100 + 50 + 200 ) -AS my_value FROM t1; -my_value -1 -DELETE FROM t1 -WHERE f1 BETWEEN 100 - 50 + 200 AND 100 + 50 + 200; -SELECT (COUNT(*) = 200 - 50 - 50 - 1) AND (MIN(f1) = 1) AND (MAX(f1) = 200) -AS my_value FROM t1; -my_value -1 -INSERT INTO t1 SET f1 = 0 , f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 0 AND f2 = '#######'; -my_value -1 -INSERT INTO t1 SET f1 = 200 + 1, f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 200 + 1 AND f2 = '#######'; -my_value -1 -UPDATE t1 SET f1 = 200 + 2, f2 = 'ZZZZZZZ' - WHERE f1 = 0 AND f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 200 + 2 AND f2 = 'ZZZZZZZ'; -my_value -1 -DELETE FROM t1 WHERE f1 = 200 + 2 AND f2 = 'ZZZZZZZ'; -SELECT COUNT(*) = 0 AS my_value FROM t1 WHERE f2 = 'ZZZZZZZ'; -my_value -1 -TRUNCATE t1; -SELECT COUNT(*) = 0 AS my_value FROM t1; -my_value -1 -DROP TABLE t1; -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY RANGE(f1) -SUBPARTITION BY HASH(f1) -( PARTITION part1 VALUES LESS THAN (100) -(SUBPARTITION subpart11 STORAGE ENGINE = 'MYISAM', -SUBPARTITION subpart12 STORAGE ENGINE = 'MYISAM'), -PARTITION part2 VALUES LESS THAN (2147483647) ENGINE = 'MYISAM' -(SUBPARTITION subpart21, -SUBPARTITION subpart22) -); -SHOW CREATE TABLE t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `f1` int(11) DEFAULT NULL, - `f2` char(20) DEFAULT NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1 /*!50100 PARTITION BY RANGE (f1) SUBPARTITION BY HASH (f1) (PARTITION part1 VALUES LESS THAN (100) (SUBPARTITION subpart11 ENGINE = MyISAM, SUBPARTITION subpart12 ENGINE = MyISAM), PARTITION part2 VALUES LESS THAN (2147483647) (SUBPARTITION subpart21 ENGINE = MyISAM, SUBPARTITION subpart22 ENGINE = MyISAM)) */ -SELECT COUNT(*) = 0 AS my_value FROM t1; -my_value -1 -INSERT INTO t1 SELECT * FROM t0_template WHERE f1 BETWEEN 1 AND 200; -SELECT (COUNT(*) = 200) AND (MIN(f1) = 1) AND (MAX(f1) = 200) -AS my_value FROM t1; -my_value -1 -UPDATE t1 SET f1 = f1 + 200 -WHERE f1 BETWEEN 100 - 50 AND 100 + 50; -SELECT (COUNT(*) = 200) AND (MIN(f1) = 1) AND (MAX(f1) = 100 + 50 + 200 ) -AS my_value FROM t1; -my_value -1 -DELETE FROM t1 -WHERE f1 BETWEEN 100 - 50 + 200 AND 100 + 50 + 200; -SELECT (COUNT(*) = 200 - 50 - 50 - 1) AND (MIN(f1) = 1) AND (MAX(f1) = 200) -AS my_value FROM t1; -my_value -1 -INSERT INTO t1 SET f1 = 0 , f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 0 AND f2 = '#######'; -my_value -1 -INSERT INTO t1 SET f1 = 200 + 1, f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 200 + 1 AND f2 = '#######'; -my_value -1 -UPDATE t1 SET f1 = 200 + 2, f2 = 'ZZZZZZZ' - WHERE f1 = 0 AND f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 200 + 2 AND f2 = 'ZZZZZZZ'; -my_value -1 -DELETE FROM t1 WHERE f1 = 200 + 2 AND f2 = 'ZZZZZZZ'; -SELECT COUNT(*) = 0 AS my_value FROM t1 WHERE f2 = 'ZZZZZZZ'; -my_value -1 -TRUNCATE t1; -SELECT COUNT(*) = 0 AS my_value FROM t1; -my_value -1 -DROP TABLE t1; -# 2.6 Precedence of storage engine assignments -# 2.6.1 Storage engine assignment after column list + after partition -# or subpartition name -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) ENGINE = 'MYISAM' -PARTITION BY HASH(f1) -( PARTITION part1 STORAGE ENGINE = 'MYISAM', -PARTITION part2 STORAGE ENGINE = 'MYISAM' -); -SHOW CREATE TABLE t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `f1` int(11) DEFAULT NULL, - `f2` char(20) DEFAULT NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1 /*!50100 PARTITION BY HASH (f1) (PARTITION part1 ENGINE = MyISAM, PARTITION part2 ENGINE = MyISAM) */ -SELECT COUNT(*) = 0 AS my_value FROM t1; -my_value -1 -INSERT INTO t1 SELECT * FROM t0_template WHERE f1 BETWEEN 1 AND 200; -SELECT (COUNT(*) = 200) AND (MIN(f1) = 1) AND (MAX(f1) = 200) -AS my_value FROM t1; -my_value -1 -UPDATE t1 SET f1 = f1 + 200 -WHERE f1 BETWEEN 100 - 50 AND 100 + 50; -SELECT (COUNT(*) = 200) AND (MIN(f1) = 1) AND (MAX(f1) = 100 + 50 + 200 ) -AS my_value FROM t1; -my_value -1 -DELETE FROM t1 -WHERE f1 BETWEEN 100 - 50 + 200 AND 100 + 50 + 200; -SELECT (COUNT(*) = 200 - 50 - 50 - 1) AND (MIN(f1) = 1) AND (MAX(f1) = 200) -AS my_value FROM t1; -my_value -1 -INSERT INTO t1 SET f1 = 0 , f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 0 AND f2 = '#######'; -my_value -1 -INSERT INTO t1 SET f1 = 200 + 1, f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 200 + 1 AND f2 = '#######'; -my_value -1 -UPDATE t1 SET f1 = 200 + 2, f2 = 'ZZZZZZZ' - WHERE f1 = 0 AND f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 200 + 2 AND f2 = 'ZZZZZZZ'; -my_value -1 -DELETE FROM t1 WHERE f1 = 200 + 2 AND f2 = 'ZZZZZZZ'; -SELECT COUNT(*) = 0 AS my_value FROM t1 WHERE f2 = 'ZZZZZZZ'; -my_value -1 -TRUNCATE t1; -SELECT COUNT(*) = 0 AS my_value FROM t1; -my_value -1 -DROP TABLE t1; -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) ENGINE = 'MYISAM' -PARTITION BY RANGE(f1) -SUBPARTITION BY HASH(f1) -( PARTITION part1 VALUES LESS THAN (100) -(SUBPARTITION subpart11 STORAGE ENGINE = 'MYISAM', -SUBPARTITION subpart12 STORAGE ENGINE = 'MYISAM'), -PARTITION part2 VALUES LESS THAN (2147483647) -(SUBPARTITION subpart21 STORAGE ENGINE = 'MYISAM', -SUBPARTITION subpart22 STORAGE ENGINE = 'MYISAM') -); -SHOW CREATE TABLE t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `f1` int(11) DEFAULT NULL, - `f2` char(20) DEFAULT NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1 /*!50100 PARTITION BY RANGE (f1) SUBPARTITION BY HASH (f1) (PARTITION part1 VALUES LESS THAN (100) (SUBPARTITION subpart11 ENGINE = MyISAM, SUBPARTITION subpart12 ENGINE = MyISAM), PARTITION part2 VALUES LESS THAN (2147483647) (SUBPARTITION subpart21 ENGINE = MyISAM, SUBPARTITION subpart22 ENGINE = MyISAM)) */ -SELECT COUNT(*) = 0 AS my_value FROM t1; -my_value -1 -INSERT INTO t1 SELECT * FROM t0_template WHERE f1 BETWEEN 1 AND 200; -SELECT (COUNT(*) = 200) AND (MIN(f1) = 1) AND (MAX(f1) = 200) -AS my_value FROM t1; -my_value -1 -UPDATE t1 SET f1 = f1 + 200 -WHERE f1 BETWEEN 100 - 50 AND 100 + 50; -SELECT (COUNT(*) = 200) AND (MIN(f1) = 1) AND (MAX(f1) = 100 + 50 + 200 ) -AS my_value FROM t1; -my_value -1 -DELETE FROM t1 -WHERE f1 BETWEEN 100 - 50 + 200 AND 100 + 50 + 200; -SELECT (COUNT(*) = 200 - 50 - 50 - 1) AND (MIN(f1) = 1) AND (MAX(f1) = 200) -AS my_value FROM t1; -my_value -1 -INSERT INTO t1 SET f1 = 0 , f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 0 AND f2 = '#######'; -my_value -1 -INSERT INTO t1 SET f1 = 200 + 1, f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 200 + 1 AND f2 = '#######'; -my_value -1 -UPDATE t1 SET f1 = 200 + 2, f2 = 'ZZZZZZZ' - WHERE f1 = 0 AND f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 200 + 2 AND f2 = 'ZZZZZZZ'; -my_value -1 -DELETE FROM t1 WHERE f1 = 200 + 2 AND f2 = 'ZZZZZZZ'; -SELECT COUNT(*) = 0 AS my_value FROM t1 WHERE f2 = 'ZZZZZZZ'; -my_value -1 -TRUNCATE t1; -SELECT COUNT(*) = 0 AS my_value FROM t1; -my_value -1 -DROP TABLE t1; -# 2.6.2 Storage engine assignment after partition name + after -# subpartition name -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY RANGE(f1) -SUBPARTITION BY HASH(f1) -( PARTITION part1 VALUES LESS THAN (100) STORAGE ENGINE = 'MYISAM' -(SUBPARTITION subpart11 STORAGE ENGINE = 'MYISAM', -SUBPARTITION subpart12 STORAGE ENGINE = 'MYISAM'), -PARTITION part2 VALUES LESS THAN (2147483647) -(SUBPARTITION subpart21 STORAGE ENGINE = 'MYISAM', -SUBPARTITION subpart22 STORAGE ENGINE = 'MYISAM') -); -SHOW CREATE TABLE t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `f1` int(11) DEFAULT NULL, - `f2` char(20) DEFAULT NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1 /*!50100 PARTITION BY RANGE (f1) SUBPARTITION BY HASH (f1) (PARTITION part1 VALUES LESS THAN (100) (SUBPARTITION subpart11 ENGINE = MyISAM, SUBPARTITION subpart12 ENGINE = MyISAM), PARTITION part2 VALUES LESS THAN (2147483647) (SUBPARTITION subpart21 ENGINE = MyISAM, SUBPARTITION subpart22 ENGINE = MyISAM)) */ -SELECT COUNT(*) = 0 AS my_value FROM t1; -my_value -1 -INSERT INTO t1 SELECT * FROM t0_template WHERE f1 BETWEEN 1 AND 200; -SELECT (COUNT(*) = 200) AND (MIN(f1) = 1) AND (MAX(f1) = 200) -AS my_value FROM t1; -my_value -1 -UPDATE t1 SET f1 = f1 + 200 -WHERE f1 BETWEEN 100 - 50 AND 100 + 50; -SELECT (COUNT(*) = 200) AND (MIN(f1) = 1) AND (MAX(f1) = 100 + 50 + 200 ) -AS my_value FROM t1; -my_value -1 -DELETE FROM t1 -WHERE f1 BETWEEN 100 - 50 + 200 AND 100 + 50 + 200; -SELECT (COUNT(*) = 200 - 50 - 50 - 1) AND (MIN(f1) = 1) AND (MAX(f1) = 200) -AS my_value FROM t1; -my_value -1 -INSERT INTO t1 SET f1 = 0 , f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 0 AND f2 = '#######'; -my_value -1 -INSERT INTO t1 SET f1 = 200 + 1, f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 200 + 1 AND f2 = '#######'; -my_value -1 -UPDATE t1 SET f1 = 200 + 2, f2 = 'ZZZZZZZ' - WHERE f1 = 0 AND f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 200 + 2 AND f2 = 'ZZZZZZZ'; -my_value -1 -DELETE FROM t1 WHERE f1 = 200 + 2 AND f2 = 'ZZZZZZZ'; -SELECT COUNT(*) = 0 AS my_value FROM t1 WHERE f2 = 'ZZZZZZZ'; -my_value -1 -TRUNCATE t1; -SELECT COUNT(*) = 0 AS my_value FROM t1; -my_value -1 -DROP TABLE t1; -# 2.7 Session default engine differs from engine used within create table -SET SESSION storage_engine='MEMORY'; -SET SESSION storage_engine='MYISAM'; - -#------------------------------------------------------------------------ -# 3. Check assigning the number of partitions and subpartitions -# with and without named partitions/subpartitions -#------------------------------------------------------------------------ -DROP TABLE IF EXISTS t1; -# 3.1 (positive) without partition/subpartition number assignment -# 3.1.1 no partition number, no named partitions -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY HASH(f1); -SHOW CREATE TABLE t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `f1` int(11) DEFAULT NULL, - `f2` char(20) DEFAULT NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1 /*!50100 PARTITION BY HASH (f1) */ -SELECT COUNT(*) = 0 AS my_value FROM t1; -my_value -1 -INSERT INTO t1 SELECT * FROM t0_template WHERE f1 BETWEEN 1 AND 200; -SELECT (COUNT(*) = 200) AND (MIN(f1) = 1) AND (MAX(f1) = 200) -AS my_value FROM t1; -my_value -1 -UPDATE t1 SET f1 = f1 + 200 -WHERE f1 BETWEEN 100 - 50 AND 100 + 50; -SELECT (COUNT(*) = 200) AND (MIN(f1) = 1) AND (MAX(f1) = 100 + 50 + 200 ) -AS my_value FROM t1; -my_value -1 -DELETE FROM t1 -WHERE f1 BETWEEN 100 - 50 + 200 AND 100 + 50 + 200; -SELECT (COUNT(*) = 200 - 50 - 50 - 1) AND (MIN(f1) = 1) AND (MAX(f1) = 200) -AS my_value FROM t1; -my_value -1 -INSERT INTO t1 SET f1 = 0 , f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 0 AND f2 = '#######'; -my_value -1 -INSERT INTO t1 SET f1 = 200 + 1, f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 200 + 1 AND f2 = '#######'; -my_value -1 -UPDATE t1 SET f1 = 200 + 2, f2 = 'ZZZZZZZ' - WHERE f1 = 0 AND f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 200 + 2 AND f2 = 'ZZZZZZZ'; -my_value -1 -DELETE FROM t1 WHERE f1 = 200 + 2 AND f2 = 'ZZZZZZZ'; -SELECT COUNT(*) = 0 AS my_value FROM t1 WHERE f2 = 'ZZZZZZZ'; -my_value -1 -TRUNCATE t1; -SELECT COUNT(*) = 0 AS my_value FROM t1; -my_value -1 -DROP TABLE t1; -# 3.1.2 no partition number, named partitions -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY HASH(f1) (PARTITION part1, PARTITION part2); -SHOW CREATE TABLE t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `f1` int(11) DEFAULT NULL, - `f2` char(20) DEFAULT NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1 /*!50100 PARTITION BY HASH (f1) (PARTITION part1 ENGINE = MyISAM, PARTITION part2 ENGINE = MyISAM) */ -SELECT COUNT(*) = 0 AS my_value FROM t1; -my_value -1 -INSERT INTO t1 SELECT * FROM t0_template WHERE f1 BETWEEN 1 AND 200; -SELECT (COUNT(*) = 200) AND (MIN(f1) = 1) AND (MAX(f1) = 200) -AS my_value FROM t1; -my_value -1 -UPDATE t1 SET f1 = f1 + 200 -WHERE f1 BETWEEN 100 - 50 AND 100 + 50; -SELECT (COUNT(*) = 200) AND (MIN(f1) = 1) AND (MAX(f1) = 100 + 50 + 200 ) -AS my_value FROM t1; -my_value -1 -DELETE FROM t1 -WHERE f1 BETWEEN 100 - 50 + 200 AND 100 + 50 + 200; -SELECT (COUNT(*) = 200 - 50 - 50 - 1) AND (MIN(f1) = 1) AND (MAX(f1) = 200) -AS my_value FROM t1; -my_value -1 -INSERT INTO t1 SET f1 = 0 , f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 0 AND f2 = '#######'; -my_value -1 -INSERT INTO t1 SET f1 = 200 + 1, f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 200 + 1 AND f2 = '#######'; -my_value -1 -UPDATE t1 SET f1 = 200 + 2, f2 = 'ZZZZZZZ' - WHERE f1 = 0 AND f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 200 + 2 AND f2 = 'ZZZZZZZ'; -my_value -1 -DELETE FROM t1 WHERE f1 = 200 + 2 AND f2 = 'ZZZZZZZ'; -SELECT COUNT(*) = 0 AS my_value FROM t1 WHERE f2 = 'ZZZZZZZ'; -my_value -1 -TRUNCATE t1; -SELECT COUNT(*) = 0 AS my_value FROM t1; -my_value -1 -DROP TABLE t1; -# 3.1.3 variations on no partition/subpartition number, named partitions, -# different subpartitions are/are not named -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY RANGE(f1) SUBPARTITION BY HASH(f1) (PARTITION part1 VALUES LESS THAN (100), PARTITION part2 VALUES LESS THAN (200), PARTITION part3 VALUES LESS THAN (2147483647)) ; -DROP TABLE t1; -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY RANGE(f1) SUBPARTITION BY HASH(f1) (PARTITION part1 VALUES LESS THAN (100) -(SUBPARTITION subpart11 , SUBPARTITION subpart12 ), PARTITION part2 VALUES LESS THAN (200) -(SUBPARTITION subpart21 , SUBPARTITION subpart22 ), PARTITION part3 VALUES LESS THAN (2147483647) -(SUBPARTITION subpart31 , SUBPARTITION subpart32 )) ; -SHOW CREATE TABLE t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `f1` int(11) DEFAULT NULL, - `f2` char(20) DEFAULT NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1 /*!50100 PARTITION BY RANGE (f1) SUBPARTITION BY HASH (f1) (PARTITION part1 VALUES LESS THAN (100) (SUBPARTITION subpart11 ENGINE = MyISAM, SUBPARTITION subpart12 ENGINE = MyISAM), PARTITION part2 VALUES LESS THAN (200) (SUBPARTITION subpart21 ENGINE = MyISAM, SUBPARTITION subpart22 ENGINE = MyISAM), PARTITION part3 VALUES LESS THAN (2147483647) (SUBPARTITION subpart31 ENGINE = MyISAM, SUBPARTITION subpart32 ENGINE = MyISAM)) */ -SELECT COUNT(*) = 0 AS my_value FROM t1; -my_value -1 -INSERT INTO t1 SELECT * FROM t0_template WHERE f1 BETWEEN 1 AND 200; -SELECT (COUNT(*) = 200) AND (MIN(f1) = 1) AND (MAX(f1) = 200) -AS my_value FROM t1; -my_value -1 -UPDATE t1 SET f1 = f1 + 200 -WHERE f1 BETWEEN 100 - 50 AND 100 + 50; -SELECT (COUNT(*) = 200) AND (MIN(f1) = 1) AND (MAX(f1) = 100 + 50 + 200 ) -AS my_value FROM t1; -my_value -1 -DELETE FROM t1 -WHERE f1 BETWEEN 100 - 50 + 200 AND 100 + 50 + 200; -SELECT (COUNT(*) = 200 - 50 - 50 - 1) AND (MIN(f1) = 1) AND (MAX(f1) = 200) -AS my_value FROM t1; -my_value -1 -INSERT INTO t1 SET f1 = 0 , f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 0 AND f2 = '#######'; -my_value -1 -INSERT INTO t1 SET f1 = 200 + 1, f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 200 + 1 AND f2 = '#######'; -my_value -1 -UPDATE t1 SET f1 = 200 + 2, f2 = 'ZZZZZZZ' - WHERE f1 = 0 AND f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 200 + 2 AND f2 = 'ZZZZZZZ'; -my_value -1 -DELETE FROM t1 WHERE f1 = 200 + 2 AND f2 = 'ZZZZZZZ'; -SELECT COUNT(*) = 0 AS my_value FROM t1 WHERE f2 = 'ZZZZZZZ'; -my_value -1 -TRUNCATE t1; -SELECT COUNT(*) = 0 AS my_value FROM t1; -my_value -1 -DROP TABLE t1; -# 3.2 partition/subpartition numbers good and bad values and notations -DROP TABLE IF EXISTS t1; -# 3.2.1 partition/subpartition numbers INTEGER notation -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY HASH(f1) PARTITIONS 2; -SHOW CREATE TABLE t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `f1` int(11) DEFAULT NULL, - `f2` char(20) DEFAULT NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1 /*!50100 PARTITION BY HASH (f1) PARTITIONS 2 */ -SELECT COUNT(*) = 0 AS my_value FROM t1; -my_value -1 -INSERT INTO t1 SELECT * FROM t0_template WHERE f1 BETWEEN 1 AND 200; -SELECT (COUNT(*) = 200) AND (MIN(f1) = 1) AND (MAX(f1) = 200) -AS my_value FROM t1; -my_value -1 -UPDATE t1 SET f1 = f1 + 200 -WHERE f1 BETWEEN 100 - 50 AND 100 + 50; -SELECT (COUNT(*) = 200) AND (MIN(f1) = 1) AND (MAX(f1) = 100 + 50 + 200 ) -AS my_value FROM t1; -my_value -1 -DELETE FROM t1 -WHERE f1 BETWEEN 100 - 50 + 200 AND 100 + 50 + 200; -SELECT (COUNT(*) = 200 - 50 - 50 - 1) AND (MIN(f1) = 1) AND (MAX(f1) = 200) -AS my_value FROM t1; -my_value -1 -INSERT INTO t1 SET f1 = 0 , f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 0 AND f2 = '#######'; -my_value -1 -INSERT INTO t1 SET f1 = 200 + 1, f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 200 + 1 AND f2 = '#######'; -my_value -1 -UPDATE t1 SET f1 = 200 + 2, f2 = 'ZZZZZZZ' - WHERE f1 = 0 AND f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 200 + 2 AND f2 = 'ZZZZZZZ'; -my_value -1 -DELETE FROM t1 WHERE f1 = 200 + 2 AND f2 = 'ZZZZZZZ'; -SELECT COUNT(*) = 0 AS my_value FROM t1 WHERE f2 = 'ZZZZZZZ'; -my_value -1 -TRUNCATE t1; -SELECT COUNT(*) = 0 AS my_value FROM t1; -my_value -1 -DROP TABLE t1; -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY RANGE(f1) SUBPARTITION BY HASH(f1) -SUBPARTITIONS 2 -(PARTITION part1 VALUES LESS THAN (100), PARTITION part2 VALUES LESS THAN (2147483647)); -SHOW CREATE TABLE t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `f1` int(11) DEFAULT NULL, - `f2` char(20) DEFAULT NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1 /*!50100 PARTITION BY RANGE (f1) SUBPARTITION BY HASH (f1) SUBPARTITIONS 2 (PARTITION part1 VALUES LESS THAN (100) ENGINE = MyISAM, PARTITION part2 VALUES LESS THAN (2147483647) ENGINE = MyISAM) */ -SELECT COUNT(*) = 0 AS my_value FROM t1; -my_value -1 -INSERT INTO t1 SELECT * FROM t0_template WHERE f1 BETWEEN 1 AND 200; -SELECT (COUNT(*) = 200) AND (MIN(f1) = 1) AND (MAX(f1) = 200) -AS my_value FROM t1; -my_value -1 -UPDATE t1 SET f1 = f1 + 200 -WHERE f1 BETWEEN 100 - 50 AND 100 + 50; -SELECT (COUNT(*) = 200) AND (MIN(f1) = 1) AND (MAX(f1) = 100 + 50 + 200 ) -AS my_value FROM t1; -my_value -1 -DELETE FROM t1 -WHERE f1 BETWEEN 100 - 50 + 200 AND 100 + 50 + 200; -SELECT (COUNT(*) = 200 - 50 - 50 - 1) AND (MIN(f1) = 1) AND (MAX(f1) = 200) -AS my_value FROM t1; -my_value -1 -INSERT INTO t1 SET f1 = 0 , f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 0 AND f2 = '#######'; -my_value -1 -INSERT INTO t1 SET f1 = 200 + 1, f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 200 + 1 AND f2 = '#######'; -my_value -1 -UPDATE t1 SET f1 = 200 + 2, f2 = 'ZZZZZZZ' - WHERE f1 = 0 AND f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 200 + 2 AND f2 = 'ZZZZZZZ'; -my_value -1 -DELETE FROM t1 WHERE f1 = 200 + 2 AND f2 = 'ZZZZZZZ'; -SELECT COUNT(*) = 0 AS my_value FROM t1 WHERE f2 = 'ZZZZZZZ'; -my_value -1 -TRUNCATE t1; -SELECT COUNT(*) = 0 AS my_value FROM t1; -my_value -1 -DROP TABLE t1; -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY HASH(f1) PARTITIONS 1; -SHOW CREATE TABLE t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `f1` int(11) DEFAULT NULL, - `f2` char(20) DEFAULT NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1 /*!50100 PARTITION BY HASH (f1) PARTITIONS 1 */ -SELECT COUNT(*) = 0 AS my_value FROM t1; -my_value -1 -INSERT INTO t1 SELECT * FROM t0_template WHERE f1 BETWEEN 1 AND 200; -SELECT (COUNT(*) = 200) AND (MIN(f1) = 1) AND (MAX(f1) = 200) -AS my_value FROM t1; -my_value -1 -UPDATE t1 SET f1 = f1 + 200 -WHERE f1 BETWEEN 100 - 50 AND 100 + 50; -SELECT (COUNT(*) = 200) AND (MIN(f1) = 1) AND (MAX(f1) = 100 + 50 + 200 ) -AS my_value FROM t1; -my_value -1 -DELETE FROM t1 -WHERE f1 BETWEEN 100 - 50 + 200 AND 100 + 50 + 200; -SELECT (COUNT(*) = 200 - 50 - 50 - 1) AND (MIN(f1) = 1) AND (MAX(f1) = 200) -AS my_value FROM t1; -my_value -1 -INSERT INTO t1 SET f1 = 0 , f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 0 AND f2 = '#######'; -my_value -1 -INSERT INTO t1 SET f1 = 200 + 1, f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 200 + 1 AND f2 = '#######'; -my_value -1 -UPDATE t1 SET f1 = 200 + 2, f2 = 'ZZZZZZZ' - WHERE f1 = 0 AND f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 200 + 2 AND f2 = 'ZZZZZZZ'; -my_value -1 -DELETE FROM t1 WHERE f1 = 200 + 2 AND f2 = 'ZZZZZZZ'; -SELECT COUNT(*) = 0 AS my_value FROM t1 WHERE f2 = 'ZZZZZZZ'; -my_value -1 -TRUNCATE t1; -SELECT COUNT(*) = 0 AS my_value FROM t1; -my_value -1 -DROP TABLE t1; -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY RANGE(f1) SUBPARTITION BY HASH(f1) -SUBPARTITIONS 1 -(PARTITION part1 VALUES LESS THAN (100), PARTITION part2 VALUES LESS THAN (2147483647)); -SHOW CREATE TABLE t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `f1` int(11) DEFAULT NULL, - `f2` char(20) DEFAULT NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1 /*!50100 PARTITION BY RANGE (f1) SUBPARTITION BY HASH (f1) SUBPARTITIONS 1 (PARTITION part1 VALUES LESS THAN (100) ENGINE = MyISAM, PARTITION part2 VALUES LESS THAN (2147483647) ENGINE = MyISAM) */ -SELECT COUNT(*) = 0 AS my_value FROM t1; -my_value -1 -INSERT INTO t1 SELECT * FROM t0_template WHERE f1 BETWEEN 1 AND 200; -SELECT (COUNT(*) = 200) AND (MIN(f1) = 1) AND (MAX(f1) = 200) -AS my_value FROM t1; -my_value -1 -UPDATE t1 SET f1 = f1 + 200 -WHERE f1 BETWEEN 100 - 50 AND 100 + 50; -SELECT (COUNT(*) = 200) AND (MIN(f1) = 1) AND (MAX(f1) = 100 + 50 + 200 ) -AS my_value FROM t1; -my_value -1 -DELETE FROM t1 -WHERE f1 BETWEEN 100 - 50 + 200 AND 100 + 50 + 200; -SELECT (COUNT(*) = 200 - 50 - 50 - 1) AND (MIN(f1) = 1) AND (MAX(f1) = 200) -AS my_value FROM t1; -my_value -1 -INSERT INTO t1 SET f1 = 0 , f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 0 AND f2 = '#######'; -my_value -1 -INSERT INTO t1 SET f1 = 200 + 1, f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 200 + 1 AND f2 = '#######'; -my_value -1 -UPDATE t1 SET f1 = 200 + 2, f2 = 'ZZZZZZZ' - WHERE f1 = 0 AND f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 200 + 2 AND f2 = 'ZZZZZZZ'; -my_value -1 -DELETE FROM t1 WHERE f1 = 200 + 2 AND f2 = 'ZZZZZZZ'; -SELECT COUNT(*) = 0 AS my_value FROM t1 WHERE f2 = 'ZZZZZZZ'; -my_value -1 -TRUNCATE t1; -SELECT COUNT(*) = 0 AS my_value FROM t1; -my_value -1 -DROP TABLE t1; -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY HASH(f1) PARTITIONS 0; -ERROR HY000: Number of partitions = 0 is not an allowed value -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY RANGE(f1) SUBPARTITION BY HASH(f1) -SUBPARTITIONS 0 -(PARTITION part1 VALUES LESS THAN (100), PARTITION part2 VALUES LESS THAN (2147483647)); -ERROR HY000: Number of subpartitions = 0 is not an allowed value -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY HASH(f1) PARTITIONS -1; -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 '-1' at line 2 -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY RANGE(f1) SUBPARTITION BY HASH(f1) -SUBPARTITIONS -1 -(PARTITION part1 VALUES LESS THAN (100), PARTITION part2 VALUES LESS THAN (2147483647)); -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 '-1 -(PARTITION part1 VALUES LESS THAN (100), PARTITION part2 VALUES LESS THAN (21' at line 3 -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY HASH(f1) PARTITIONS 1000000; -ERROR HY000: Too many partitions (including subpartitions) were defined -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY RANGE(f1) SUBPARTITION BY HASH(f1) -SUBPARTITIONS 1000000 -(PARTITION part1 VALUES LESS THAN (100), PARTITION part2 VALUES LESS THAN (2147483647)); -ERROR HY000: Too many partitions (including subpartitions) were defined -# 3.2.4 partition/subpartition numbers STRING notation -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY HASH(f1) PARTITIONS '2'; -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 ''2'' at line 2 -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY RANGE(f1) SUBPARTITION BY HASH(f1) -SUBPARTITIONS '2' -(PARTITION part1 VALUES LESS THAN (100), PARTITION part2 VALUES LESS THAN (2147483647)); -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 ''2' -(PARTITION part1 VALUES LESS THAN (100), PARTITION part2 VALUES LESS THAN (2' at line 3 -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY HASH(f1) PARTITIONS '2.0'; -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 ''2.0'' at line 2 -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY RANGE(f1) SUBPARTITION BY HASH(f1) -SUBPARTITIONS '2.0' -(PARTITION part1 VALUES LESS THAN (100), PARTITION part2 VALUES LESS THAN (2147483647)); -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 ''2.0' -(PARTITION part1 VALUES LESS THAN (100), PARTITION part2 VALUES LESS THAN ' at line 3 -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY HASH(f1) PARTITIONS '0.2E+1'; -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 ''0.2E+1'' at line 2 -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY RANGE(f1) SUBPARTITION BY HASH(f1) -SUBPARTITIONS '0.2E+1' -(PARTITION part1 VALUES LESS THAN (100), PARTITION part2 VALUES LESS THAN (2147483647)); -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 ''0.2E+1' -(PARTITION part1 VALUES LESS THAN (100), PARTITION part2 VALUES LESS TH' at line 3 -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY HASH(f1) PARTITIONS '2A'; -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 ''2A'' at line 2 -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY RANGE(f1) SUBPARTITION BY HASH(f1) -SUBPARTITIONS '2A' -(PARTITION part1 VALUES LESS THAN (100), PARTITION part2 VALUES LESS THAN (2147483647)); -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 ''2A' -(PARTITION part1 VALUES LESS THAN (100), PARTITION part2 VALUES LESS THAN (' at line 3 -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY HASH(f1) PARTITIONS 'A2'; -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 ''A2'' at line 2 -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY RANGE(f1) SUBPARTITION BY HASH(f1) -SUBPARTITIONS 'A2' -(PARTITION part1 VALUES LESS THAN (100), PARTITION part2 VALUES LESS THAN (2147483647)); -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 ''A2' -(PARTITION part1 VALUES LESS THAN (100), PARTITION part2 VALUES LESS THAN (' at line 3 -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY HASH(f1) PARTITIONS ''; -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 -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY RANGE(f1) SUBPARTITION BY HASH(f1) -SUBPARTITIONS '' -(PARTITION part1 VALUES LESS THAN (100), PARTITION part2 VALUES LESS THAN (2147483647)); -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 ''' -(PARTITION part1 VALUES LESS THAN (100), PARTITION part2 VALUES LESS THAN (21' at line 3 -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY HASH(f1) PARTITIONS 'GARBAGE'; -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 ''GARBAGE'' at line 2 -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY RANGE(f1) SUBPARTITION BY HASH(f1) -SUBPARTITIONS 'GARBAGE' -(PARTITION part1 VALUES LESS THAN (100), PARTITION part2 VALUES LESS THAN (2147483647)); -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 ''GARBAGE' -(PARTITION part1 VALUES LESS THAN (100), PARTITION part2 VALUES LESS T' at line 3 -# 3.2.5 partition/subpartition numbers other notations -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY HASH(f1) PARTITIONS 2A; -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 '2A' at line 2 -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY RANGE(f1) SUBPARTITION BY HASH(f1) -SUBPARTITIONS 2A -(PARTITION part1 VALUES LESS THAN (100), PARTITION part2 VALUES LESS THAN (2147483647)); -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 '2A -(PARTITION part1 VALUES LESS THAN (100), PARTITION part2 VALUES LESS THAN (21' at line 3 -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY HASH(f1) PARTITIONS A2; -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 'A2' at line 2 -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY RANGE(f1) SUBPARTITION BY HASH(f1) -SUBPARTITIONS A2 -(PARTITION part1 VALUES LESS THAN (100), PARTITION part2 VALUES LESS THAN (2147483647)); -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 'A2 -(PARTITION part1 VALUES LESS THAN (100), PARTITION part2 VALUES LESS THAN (21' at line 3 -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY HASH(f1) PARTITIONS GARBAGE; -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 'GARBAGE' at line 2 -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY RANGE(f1) SUBPARTITION BY HASH(f1) -SUBPARTITIONS GARBAGE -(PARTITION part1 VALUES LESS THAN (100), PARTITION part2 VALUES LESS THAN (2147483647)); -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 'GARBAGE -(PARTITION part1 VALUES LESS THAN (100), PARTITION part2 VALUES LESS THA' at line 3 -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY HASH(f1) PARTITIONS "2"; -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 '"2"' at line 2 -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY RANGE(f1) SUBPARTITION BY HASH(f1) -SUBPARTITIONS "2" -(PARTITION part1 VALUES LESS THAN (100), PARTITION part2 VALUES LESS THAN (2147483647)); -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 '"2" -(PARTITION part1 VALUES LESS THAN (100), PARTITION part2 VALUES LESS THAN (2' at line 3 -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY HASH(f1) PARTITIONS "2A"; -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 '"2A"' at line 2 -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY RANGE(f1) SUBPARTITION BY HASH(f1) -SUBPARTITIONS "2A" -(PARTITION part1 VALUES LESS THAN (100), PARTITION part2 VALUES LESS THAN (2147483647)); -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 '"2A" -(PARTITION part1 VALUES LESS THAN (100), PARTITION part2 VALUES LESS THAN (' at line 3 -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY HASH(f1) PARTITIONS "A2"; -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 '"A2"' at line 2 -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY RANGE(f1) SUBPARTITION BY HASH(f1) -SUBPARTITIONS "A2" -(PARTITION part1 VALUES LESS THAN (100), PARTITION part2 VALUES LESS THAN (2147483647)); -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 '"A2" -(PARTITION part1 VALUES LESS THAN (100), PARTITION part2 VALUES LESS THAN (' at line 3 -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY HASH(f1) PARTITIONS "GARBAGE"; -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 '"GARBAGE"' at line 2 -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY RANGE(f1) SUBPARTITION BY HASH(f1) -SUBPARTITIONS "GARBAGE" -(PARTITION part1 VALUES LESS THAN (100), PARTITION part2 VALUES LESS THAN (2147483647)); -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 '"GARBAGE" -(PARTITION part1 VALUES LESS THAN (100), PARTITION part2 VALUES LESS T' at line 3 -# 3.3 Mixups of assigned partition/subpartition numbers and names -# 3.3.1 (positive) number of partition/subpartition -# = number of named partition/subpartition -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY HASH(f1) PARTITIONS 2 ( PARTITION part1, PARTITION part2 ) ; -SHOW CREATE TABLE t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `f1` int(11) DEFAULT NULL, - `f2` char(20) DEFAULT NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1 /*!50100 PARTITION BY HASH (f1) (PARTITION part1 ENGINE = MyISAM, PARTITION part2 ENGINE = MyISAM) */ -DROP TABLE t1; -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY RANGE(f1) PARTITIONS 2 -SUBPARTITION BY HASH(f1) SUBPARTITIONS 2 -( PARTITION part1 VALUES LESS THAN (1000) -(SUBPARTITION subpart11, SUBPARTITION subpart12), -PARTITION part2 VALUES LESS THAN (2147483647) -(SUBPARTITION subpart21, SUBPARTITION subpart22) -); -SHOW CREATE TABLE t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `f1` int(11) DEFAULT NULL, - `f2` char(20) DEFAULT NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1 /*!50100 PARTITION BY RANGE (f1) SUBPARTITION BY HASH (f1) (PARTITION part1 VALUES LESS THAN (1000) (SUBPARTITION subpart11 ENGINE = MyISAM, SUBPARTITION subpart12 ENGINE = MyISAM), PARTITION part2 VALUES LESS THAN (2147483647) (SUBPARTITION subpart21 ENGINE = MyISAM, SUBPARTITION subpart22 ENGINE = MyISAM)) */ -DROP TABLE t1; -# 3.3.2 (positive) number of partition/subpartition , -# 0 (= no) named partition/subpartition -# already checked above -# 3.3.3 (negative) number of partitions/subpartitions -# > number of named partitions/subpartitions -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY HASH(f1) PARTITIONS 2 ( PARTITION part1 ) ; -ERROR 42000: Wrong number of partitions defined, mismatch with previous setting near ')' at line 2 -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY RANGE(f1) -SUBPARTITION BY HASH(f1) SUBPARTITIONS 2 -( PARTITION part1 VALUES LESS THAN (1000) -(SUBPARTITION subpart11 ), -PARTITION part2 VALUES LESS THAN (2147483647) -(SUBPARTITION subpart21, SUBPARTITION subpart22) -); -ERROR 42000: Wrong number of subpartitions defined, mismatch with previous setting near '), -PARTITION part2 VALUES LESS THAN (2147483647) -(SUBPARTITION subpart21, SUBPAR' at line 5 -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY RANGE(f1) -SUBPARTITION BY HASH(f1) SUBPARTITIONS 2 -( PARTITION part1 VALUES LESS THAN (1000) -(SUBPARTITION subpart11, SUBPARTITION subpart12), -PARTITION part2 VALUES LESS THAN (2000) -(SUBPARTITION subpart21 ), -PARTITION part3 VALUES LESS THAN (2147483647) -(SUBPARTITION subpart31, SUBPARTITION subpart32) -); -ERROR 42000: Wrong number of subpartitions defined, mismatch with previous setting near '), -PARTITION part3 VALUES LESS THAN (2147483647) -(SUBPARTITION subpart31, SUBPAR' at line 7 -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY RANGE(f1) PARTITIONS 2 -SUBPARTITION BY HASH(f1) SUBPARTITIONS 2 -( PARTITION part1 VALUES LESS THAN (1000) -(SUBPARTITION subpart11, SUBPARTITION subpart12), -PARTITION part2 VALUES LESS THAN (2147483647) -(SUBPARTITION subpart21 ) -); -ERROR 42000: Wrong number of subpartitions defined, mismatch with previous setting near ') -)' at line 7 -# 3.3.4 (negative) number of partitions < number of named partitions -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY HASH(f1) PARTITIONS 1 ( PARTITION part1, PARTITION part2 ) ; -ERROR 42000: Wrong number of partitions defined, mismatch with previous setting near ')' at line 2 -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY RANGE(f1) -SUBPARTITION BY HASH(f1) SUBPARTITIONS 1 -( PARTITION part1 VALUES LESS THAN (1000) -(SUBPARTITION subpart11, SUBPARTITION subpart12), -PARTITION part2 VALUES LESS THAN (2147483647) -(SUBPARTITION subpart21, SUBPARTITION subpart22) -); -ERROR 42000: Wrong number of subpartitions defined, mismatch with previous setting near '), -PARTITION part2 VALUES LESS THAN (2147483647) -(SUBPARTITION subpart21, SUBPAR' at line 5 -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY RANGE(f1) -SUBPARTITION BY HASH(f1) SUBPARTITIONS 1 -( PARTITION part1 VALUES LESS THAN (1000) -(SUBPARTITION subpart11, SUBPARTITION subpart12), -PARTITION part2 VALUES LESS THAN (2000) -(SUBPARTITION subpart21 ), -PARTITION part3 VALUES LESS THAN (2147483647) -(SUBPARTITION subpart31, SUBPARTITION subpart32) -); -ERROR 42000: Wrong number of subpartitions defined, mismatch with previous setting near '), -PARTITION part2 VALUES LESS THAN (2000) -(SUBPARTITION subpart21 ' at line 5 -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY RANGE(f1) -SUBPARTITION BY HASH(f1) SUBPARTITIONS 1 -( PARTITION part1 VALUES LESS THAN (1000) -(SUBPARTITION subpart11, SUBPARTITION subpart12), -PARTITION part2 VALUES LESS THAN (2147483647) -(SUBPARTITION subpart21, SUBPARTITION subpart22) -); -ERROR 42000: Wrong number of subpartitions defined, mismatch with previous setting near '), -PARTITION part2 VALUES LESS THAN (2147483647) -(SUBPARTITION subpart21, SUBPAR' at line 5 - -#------------------------------------------------------------------------ -# 4. Checks of logical partition/subpartition name -# file name clashes during CREATE TABLE -#------------------------------------------------------------------------ -DROP TABLE IF EXISTS t1; -# 4.1 (negative) A partition name used more than once -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY HASH(f1) (PARTITION part1, PARTITION part1); -ERROR HY000: Duplicate partition name part1 -# FIXME Implement testcases with filename problems -# existing file of other table --- partition/subpartition file name -# partition/subpartition file name --- file of the same table - -#------------------------------------------------------------------------ -# 5. Alter table experiments -#------------------------------------------------------------------------ -DROP TABLE IF EXISTS t1; -# 5.1 alter table add partition -# 5.1.1 (negative) add partition to non partitioned table -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)); -SHOW CREATE TABLE t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `f1` int(11) DEFAULT NULL, - `f2` char(20) DEFAULT NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1 -ALTER TABLE t1 ADD PARTITION (PARTITION part1); -Got one of the listed errors -SHOW CREATE TABLE t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `f1` int(11) DEFAULT NULL, - `f2` char(20) DEFAULT NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1 -DROP TABLE t1; -# 5.1.2 Add one partition to a table with one partition -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY HASH(f1); -SHOW CREATE TABLE t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `f1` int(11) DEFAULT NULL, - `f2` char(20) DEFAULT NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1 /*!50100 PARTITION BY HASH (f1) */ -INSERT INTO t1 SELECT * FROM t0_template WHERE f1 BETWEEN 1 AND 100 - 1; -ALTER TABLE t1 ADD PARTITION (PARTITION part1); -SHOW CREATE TABLE t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `f1` int(11) DEFAULT NULL, - `f2` char(20) DEFAULT NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1 /*!50100 PARTITION BY HASH (f1) (PARTITION p0 ENGINE = MyISAM, PARTITION part1 ENGINE = MyISAM) */ -INSERT INTO t1 SELECT * FROM t0_template WHERE f1 BETWEEN 100 AND 200; -SELECT (COUNT(*) = 200) AND (MIN(f1) = 1) AND (MAX(f1) = 200) -AS my_value FROM t1; -my_value -1 -UPDATE t1 SET f1 = f1 + 200 -WHERE f1 BETWEEN 100 - 50 AND 100 + 50; -SELECT (COUNT(*) = 200) AND (MIN(f1) = 1) AND (MAX(f1) = 100 + 50 + 200 ) -AS my_value FROM t1; -my_value -1 -DELETE FROM t1 -WHERE f1 BETWEEN 100 - 50 + 200 AND 100 + 50 + 200; -SELECT (COUNT(*) = 200 - 50 - 50 - 1) AND (MIN(f1) = 1) AND (MAX(f1) = 200) -AS my_value FROM t1; -my_value -1 -INSERT INTO t1 SET f1 = 0 , f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 0 AND f2 = '#######'; -my_value -1 -INSERT INTO t1 SET f1 = 200 + 1, f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 200 + 1 AND f2 = '#######'; -my_value -1 -UPDATE t1 SET f1 = 200 + 2, f2 = 'ZZZZZZZ' - WHERE f1 = 0 AND f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 200 + 2 AND f2 = 'ZZZZZZZ'; -my_value -1 -DELETE FROM t1 WHERE f1 = 200 + 2 AND f2 = 'ZZZZZZZ'; -SELECT COUNT(*) = 0 AS my_value FROM t1 WHERE f2 = 'ZZZZZZZ'; -my_value -1 -TRUNCATE t1; -SELECT COUNT(*) = 0 AS my_value FROM t1; -my_value -1 -DROP TABLE t1; -# 5.1.3 Several times add one partition to a table with some partitions -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY HASH(f1) (PARTITION part1, PARTITION part3); -SHOW CREATE TABLE t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `f1` int(11) DEFAULT NULL, - `f2` char(20) DEFAULT NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1 /*!50100 PARTITION BY HASH (f1) (PARTITION part1 ENGINE = MyISAM, PARTITION part3 ENGINE = MyISAM) */ -INSERT INTO t1 SELECT * FROM t0_template WHERE f1 BETWEEN 1 AND 100 - 1; -ALTER TABLE t1 ADD PARTITION (PARTITION part0); -SHOW CREATE TABLE t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `f1` int(11) DEFAULT NULL, - `f2` char(20) DEFAULT NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1 /*!50100 PARTITION BY HASH (f1) (PARTITION part1 ENGINE = MyISAM, PARTITION part3 ENGINE = MyISAM, PARTITION part0 ENGINE = MyISAM) */ -INSERT INTO t1 SELECT * FROM t0_template WHERE f1 BETWEEN 100 AND 200; -SELECT (COUNT(*) = 200) AND (MIN(f1) = 1) AND (MAX(f1) = 200) -AS my_value FROM t1; -my_value -1 -UPDATE t1 SET f1 = f1 + 200 -WHERE f1 BETWEEN 100 - 50 AND 100 + 50; -SELECT (COUNT(*) = 200) AND (MIN(f1) = 1) AND (MAX(f1) = 100 + 50 + 200 ) -AS my_value FROM t1; -my_value -1 -DELETE FROM t1 -WHERE f1 BETWEEN 100 - 50 + 200 AND 100 + 50 + 200; -SELECT (COUNT(*) = 200 - 50 - 50 - 1) AND (MIN(f1) = 1) AND (MAX(f1) = 200) -AS my_value FROM t1; -my_value -1 -INSERT INTO t1 SET f1 = 0 , f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 0 AND f2 = '#######'; -my_value -1 -INSERT INTO t1 SET f1 = 200 + 1, f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 200 + 1 AND f2 = '#######'; -my_value -1 -UPDATE t1 SET f1 = 200 + 2, f2 = 'ZZZZZZZ' - WHERE f1 = 0 AND f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 200 + 2 AND f2 = 'ZZZZZZZ'; -my_value -1 -DELETE FROM t1 WHERE f1 = 200 + 2 AND f2 = 'ZZZZZZZ'; -SELECT COUNT(*) = 0 AS my_value FROM t1 WHERE f2 = 'ZZZZZZZ'; -my_value -1 -TRUNCATE t1; -SELECT COUNT(*) = 0 AS my_value FROM t1; -my_value -1 -DELETE FROM t1; -INSERT INTO t1 SELECT * FROM t0_template WHERE f1 BETWEEN 1 AND 100 - 1; -ALTER TABLE t1 ADD PARTITION (PARTITION part2); -SHOW CREATE TABLE t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `f1` int(11) DEFAULT NULL, - `f2` char(20) DEFAULT NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1 /*!50100 PARTITION BY HASH (f1) (PARTITION part1 ENGINE = MyISAM, PARTITION part3 ENGINE = MyISAM, PARTITION part0 ENGINE = MyISAM, PARTITION part2 ENGINE = MyISAM) */ -INSERT INTO t1 SELECT * FROM t0_template WHERE f1 BETWEEN 100 AND 200; -SELECT (COUNT(*) = 200) AND (MIN(f1) = 1) AND (MAX(f1) = 200) -AS my_value FROM t1; -my_value -1 -UPDATE t1 SET f1 = f1 + 200 -WHERE f1 BETWEEN 100 - 50 AND 100 + 50; -SELECT (COUNT(*) = 200) AND (MIN(f1) = 1) AND (MAX(f1) = 100 + 50 + 200 ) -AS my_value FROM t1; -my_value -1 -DELETE FROM t1 -WHERE f1 BETWEEN 100 - 50 + 200 AND 100 + 50 + 200; -SELECT (COUNT(*) = 200 - 50 - 50 - 1) AND (MIN(f1) = 1) AND (MAX(f1) = 200) -AS my_value FROM t1; -my_value -1 -INSERT INTO t1 SET f1 = 0 , f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 0 AND f2 = '#######'; -my_value -1 -INSERT INTO t1 SET f1 = 200 + 1, f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 200 + 1 AND f2 = '#######'; -my_value -1 -UPDATE t1 SET f1 = 200 + 2, f2 = 'ZZZZZZZ' - WHERE f1 = 0 AND f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 200 + 2 AND f2 = 'ZZZZZZZ'; -my_value -1 -DELETE FROM t1 WHERE f1 = 200 + 2 AND f2 = 'ZZZZZZZ'; -SELECT COUNT(*) = 0 AS my_value FROM t1 WHERE f2 = 'ZZZZZZZ'; -my_value -1 -TRUNCATE t1; -SELECT COUNT(*) = 0 AS my_value FROM t1; -my_value -1 -DELETE FROM t1; -INSERT INTO t1 SELECT * FROM t0_template WHERE f1 BETWEEN 1 AND 100 - 1; -SHOW CREATE TABLE t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `f1` int(11) DEFAULT NULL, - `f2` char(20) DEFAULT NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1 /*!50100 PARTITION BY HASH (f1) (PARTITION part1 ENGINE = MyISAM, PARTITION part3 ENGINE = MyISAM, PARTITION part0 ENGINE = MyISAM, PARTITION part2 ENGINE = MyISAM) */ -INSERT INTO t1 SELECT * FROM t0_template WHERE f1 BETWEEN 100 AND 200; -SELECT (COUNT(*) = 200) AND (MIN(f1) = 1) AND (MAX(f1) = 200) -AS my_value FROM t1; -my_value -1 -UPDATE t1 SET f1 = f1 + 200 -WHERE f1 BETWEEN 100 - 50 AND 100 + 50; -SELECT (COUNT(*) = 200) AND (MIN(f1) = 1) AND (MAX(f1) = 100 + 50 + 200 ) -AS my_value FROM t1; -my_value -1 -DELETE FROM t1 -WHERE f1 BETWEEN 100 - 50 + 200 AND 100 + 50 + 200; -SELECT (COUNT(*) = 200 - 50 - 50 - 1) AND (MIN(f1) = 1) AND (MAX(f1) = 200) -AS my_value FROM t1; -my_value -1 -INSERT INTO t1 SET f1 = 0 , f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 0 AND f2 = '#######'; -my_value -1 -INSERT INTO t1 SET f1 = 200 + 1, f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 200 + 1 AND f2 = '#######'; -my_value -1 -UPDATE t1 SET f1 = 200 + 2, f2 = 'ZZZZZZZ' - WHERE f1 = 0 AND f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 200 + 2 AND f2 = 'ZZZZZZZ'; -my_value -1 -DELETE FROM t1 WHERE f1 = 200 + 2 AND f2 = 'ZZZZZZZ'; -SELECT COUNT(*) = 0 AS my_value FROM t1 WHERE f2 = 'ZZZZZZZ'; -my_value -1 -TRUNCATE t1; -SELECT COUNT(*) = 0 AS my_value FROM t1; -my_value -1 -DROP TABLE t1; -# 5.1.4 Add several partitions to a table with some partitions -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY HASH(f1) (PARTITION part1, PARTITION part3); -SHOW CREATE TABLE t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `f1` int(11) DEFAULT NULL, - `f2` char(20) DEFAULT NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1 /*!50100 PARTITION BY HASH (f1) (PARTITION part1 ENGINE = MyISAM, PARTITION part3 ENGINE = MyISAM) */ -INSERT INTO t1 SELECT * FROM t0_template WHERE f1 BETWEEN 1 AND 100 - 1; -SHOW CREATE TABLE t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `f1` int(11) DEFAULT NULL, - `f2` char(20) DEFAULT NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1 /*!50100 PARTITION BY HASH (f1) (PARTITION part1 ENGINE = MyISAM, PARTITION part3 ENGINE = MyISAM) */ -INSERT INTO t1 SELECT * FROM t0_template WHERE f1 BETWEEN 100 AND 200; -SELECT (COUNT(*) = 200) AND (MIN(f1) = 1) AND (MAX(f1) = 200) -AS my_value FROM t1; -my_value -1 -UPDATE t1 SET f1 = f1 + 200 -WHERE f1 BETWEEN 100 - 50 AND 100 + 50; -SELECT (COUNT(*) = 200) AND (MIN(f1) = 1) AND (MAX(f1) = 100 + 50 + 200 ) -AS my_value FROM t1; -my_value -1 -DELETE FROM t1 -WHERE f1 BETWEEN 100 - 50 + 200 AND 100 + 50 + 200; -SELECT (COUNT(*) = 200 - 50 - 50 - 1) AND (MIN(f1) = 1) AND (MAX(f1) = 200) -AS my_value FROM t1; -my_value -1 -INSERT INTO t1 SET f1 = 0 , f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 0 AND f2 = '#######'; -my_value -1 -INSERT INTO t1 SET f1 = 200 + 1, f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 200 + 1 AND f2 = '#######'; -my_value -1 -UPDATE t1 SET f1 = 200 + 2, f2 = 'ZZZZZZZ' - WHERE f1 = 0 AND f2 = '#######'; -SELECT COUNT(*) = 1 AS my_value FROM t1 WHERE f1 = 200 + 2 AND f2 = 'ZZZZZZZ'; -my_value -1 -DELETE FROM t1 WHERE f1 = 200 + 2 AND f2 = 'ZZZZZZZ'; -SELECT COUNT(*) = 0 AS my_value FROM t1 WHERE f2 = 'ZZZZZZZ'; -my_value -1 -TRUNCATE t1; -SELECT COUNT(*) = 0 AS my_value FROM t1; -my_value -1 -DROP TABLE t1; -# 5.1.5 (negative) Add partitions to a table with some partitions -# clash on new and already existing partition names -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY HASH(f1) (PARTITION part1, PARTITION part2, PARTITION part3); -ALTER TABLE t1 ADD PARTITION (PARTITION part1); -ERROR HY000: Duplicate partition name part1 -ALTER TABLE t1 ADD PARTITION (PARTITION part2); -ERROR HY000: Duplicate partition name part2 -ALTER TABLE t1 ADD PARTITION (PARTITION part3); -ERROR HY000: Duplicate partition name part3 -ALTER TABLE t1 ADD PARTITION (PARTITION part1, PARTITION part2, PARTITION part3); -ERROR HY000: Duplicate partition name part1 -DROP TABLE t1; -# 5.2 alter table add subpartition -# 5.2.1 Add one subpartition to a table with subpartitioning rule and -# no explicit defined subpartitions -CREATE TABLE t1 ( f1 INTEGER, f2 char(20)) -PARTITION BY RANGE(f1) -SUBPARTITION BY HASH(f1) -(PARTITION part1 VALUES LESS THAN (100)); -INSERT INTO t1 SELECT * FROM t0_template WHERE f1 BETWEEN 1 AND 100 - 1; -ALTER TABLE t1 ADD PARTITION (PARTITION part2 VALUES LESS THAN (2147483647) -(SUBPARTITION subpart21)); -DROP TABLE t1; -DROP TABLE if exists t0_template; diff --git a/mysql-test/r/partition_datatype.result b/mysql-test/r/partition_datatype.result new file mode 100644 index 00000000000..c6506178b03 --- /dev/null +++ b/mysql-test/r/partition_datatype.result @@ -0,0 +1,282 @@ +drop table if exists t1; +create table t1 (a tinyint not null) partition by key (a); +insert into t1 values (2); +select * from t1 where a = 2; +a +2 +drop table t1; +create table t1 (a smallint not null) partition by key (a); +insert into t1 values (2); +select * from t1 where a = 2; +a +2 +drop table t1; +create table t1 (a mediumint not null) partition by key (a); +insert into t1 values (2); +select * from t1 where a = 2; +a +2 +drop table t1; +create table t1 (a int not null) partition by key (a); +insert into t1 values (2); +select * from t1 where a = 2; +a +2 +drop table t1; +create table t1 (a bigint not null) partition by key (a); +insert into t1 values (2); +select * from t1 where a = 2; +a +2 +drop table t1; +create table t1 (a float not null) partition by key (a); +insert into t1 values (2.1); +select * from t1 where a = 2.1; +a +drop table t1; +create table t1 (a double not null) partition by key (a); +insert into t1 values (2.1); +select * from t1 where a = 2.1; +a +2.1 +drop table t1; +create table t1 (a decimal not null) partition by key (a); +insert into t1 values (2.1); +Warnings: +Note 1265 Data truncated for column 'a' at row 1 +select * from t1 where a = 2.1; +a +drop table t1; +create table t1 (a date not null) partition by key (a); +insert into t1 values ('2001-01-01'); +select * from t1 where a = '2001-01-01'; +a +2001-01-01 +drop table t1; +create table t1 (a datetime not null) partition by key (a); +insert into t1 values ('2001-01-01 01:02:03'); +select * from t1 where a = '2001-01-01 01:02:03'; +a +2001-01-01 01:02:03 +drop table t1; +create table t1 (a timestamp not null) partition by key (a); +insert into t1 values ('2001-01-01 01:02:03'); +select * from t1 where a = '2001-01-01 01:02:03'; +a +2001-01-01 01:02:03 +drop table t1; +create table t1 (a time not null) partition by key (a); +insert into t1 values ('01:02:03'); +select * from t1 where a = '01:02:03'; +a +01:02:03 +drop table t1; +create table t1 (a year not null) partition by key (a); +insert into t1 values ('2001'); +select * from t1 where a = '2001'; +a +2001 +drop table t1; +create table t1 (a varchar(10) character set utf8 not null) partition by key (a); +insert into t1 values ('abc'); +select * from t1 where a = 'abc'; +a +abc +drop table t1; +create table t1 (a varchar(300) character set utf8 not null) partition by key (a); +insert into t1 values ('abc'); +select * from t1 where a = 'abc'; +a +abc +drop table t1; +create table t1 (a varchar(10) character set latin1 not null) partition by key (a); +insert into t1 values ('abc'); +select * from t1 where a = 'abc'; +a +abc +drop table t1; +create table t1 (a varchar(300) character set latin1 not null) partition by key (a); +insert into t1 values ('abc'); +select * from t1 where a = 'abc'; +a +abc +drop table t1; +create table t1 (a char(10) character set utf8 not null) partition by key (a); +insert into t1 values ('abc'); +select * from t1 where a = 'abc'; +a +abc +drop table t1; +create table t1 (a char(10) character set latin1 not null) partition by key (a); +insert into t1 values ('abc'); +select * from t1 where a = 'abc'; +a +abc +drop table t1; +create table t1 (a enum('y','n') not null) partition by key (a); +insert into t1 values ('y'); +select * from t1 where a = 'y'; +a +y +drop table t1; +create table t1 (a set('y','n') not null) partition by key (a); +insert into t1 values ('y'); +select * from t1 where a = 'y'; +a +y +drop table t1; +create table t1 (a tinyint) partition by key (a); +insert into t1 values (2); +select * from t1 where a = 2; +a +2 +drop table t1; +create table t1 (a smallint) partition by key (a); +insert into t1 values (2); +select * from t1 where a = 2; +a +2 +drop table t1; +create table t1 (a mediumint) partition by key (a); +insert into t1 values (2); +select * from t1 where a = 2; +a +2 +drop table t1; +create table t1 (a int) partition by key (a); +insert into t1 values (2); +select * from t1 where a = 2; +a +2 +drop table t1; +create table t1 (a bigint) partition by key (a); +insert into t1 values (2); +select * from t1 where a = 2; +a +2 +drop table t1; +create table t1 (a float) partition by key (a); +insert into t1 values (2.1); +select * from t1 where a = 2.1; +a +drop table t1; +create table t1 (a double) partition by key (a); +insert into t1 values (2.1); +select * from t1 where a = 2.1; +a +2.1 +drop table t1; +create table t1 (a decimal) partition by key (a); +insert into t1 values (2.1); +Warnings: +Note 1265 Data truncated for column 'a' at row 1 +select * from t1 where a = 2.1; +a +drop table t1; +create table t1 (a date) partition by key (a); +insert into t1 values ('2001-01-01'); +select * from t1 where a = '2001-01-01'; +a +2001-01-01 +drop table t1; +create table t1 (a datetime) partition by key (a); +insert into t1 values ('2001-01-01 01:02:03'); +select * from t1 where a = '2001-01-01 01:02:03'; +a +2001-01-01 01:02:03 +drop table t1; +create table t1 (a timestamp null) partition by key (a); +insert into t1 values ('2001-01-01 01:02:03'); +select * from t1 where a = '2001-01-01 01:02:03'; +a +2001-01-01 01:02:03 +drop table t1; +create table t1 (a time) partition by key (a); +insert into t1 values ('01:02:03'); +select * from t1 where a = '01:02:03'; +a +01:02:03 +drop table t1; +create table t1 (a year) partition by key (a); +insert into t1 values ('2001'); +select * from t1 where a = '2001'; +a +2001 +drop table t1; +create table t1 (a varchar(10) character set utf8) partition by key (a); +insert into t1 values ('abc'); +select * from t1 where a = 'abc'; +a +abc +drop table t1; +create table t1 (a varchar(300) character set utf8) partition by key (a); +insert into t1 values ('abc'); +select * from t1 where a = 'abc'; +a +abc +drop table t1; +create table t1 (a varchar(10) character set latin1) partition by key (a); +insert into t1 values ('abc'); +select * from t1 where a = 'abc'; +a +abc +drop table t1; +create table t1 (a varchar(300) character set latin1) partition by key (a); +insert into t1 values ('abc'); +select * from t1 where a = 'abc'; +a +abc +drop table t1; +create table t1 (a char(10) character set utf8) partition by key (a); +insert into t1 values ('abc'); +select * from t1 where a = 'abc'; +a +abc +drop table t1; +create table t1 (a char(10) character set latin1) partition by key (a); +insert into t1 values ('abc'); +select * from t1 where a = 'abc'; +a +abc +drop table t1; +create table t1 (a enum('y','n')) partition by key (a); +insert into t1 values ('y'); +select * from t1 where a = 'y'; +a +y +drop table t1; +create table t1 (a set('y','n')) partition by key (a); +insert into t1 values ('y'); +select * from t1 where a = 'y'; +a +y +drop table t1; +create table t1 (a varchar(65531)) partition by key (a); +insert into t1 values ('bbbb'); +insert into t1 values ('aaaa'); +select * from t1 where a = 'aaa%'; +a +select * from t1 where a like 'aaa%'; +a +aaaa +drop table t1; +create table t1 (a varchar(65532)) partition by key (a); +insert into t1 values ('bbbb'); +insert into t1 values ('aaaa'); +select * from t1 where a = 'aaa%'; +a +select * from t1 where a like 'aaa%'; +a +aaaa +drop table t1; +create table t1 (a varchar(65533) not null) partition by key (a); +insert into t1 values ('aaaa'); +select * from t1 where a = 'aaa%'; +a +drop table t1; +create table t1 (a varchar(65533)) partition by key (a); +ERROR 42000: Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. You have to change some columns to TEXT or BLOBs +create table t1 (a varchar(65534) not null) partition by key (a); +ERROR 42000: Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. You have to change some columns to TEXT or BLOBs +create table t1 (a varchar(65535)) partition by key (a); +ERROR 42000: Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. You have to change some columns to TEXT or BLOBs diff --git a/mysql-test/r/partition_error.result b/mysql-test/r/partition_error.result index 7952c8df609..46532cb32ab 100644 --- a/mysql-test/r/partition_error.result +++ b/mysql-test/r/partition_error.result @@ -1,4 +1,13 @@ drop table if exists t1; +CREATE TABLE t1 ( +a int +) +PARTITION BY RANGE (a) +( +PARTITION p0 VALUES LESS THAN (1), +PARTITION p1 VALU ES LESS THAN (2) +); +ERROR HY000: Syntax error: RANGE PARTITIONING requires definition of VALUES LESS THAN for each partition partition by list (a) partitions 3 (partition x1 values in (1,2,9,4) tablespace ts1, @@ -351,7 +360,7 @@ partition by range (a) partitions 2 (partition x1 values less than (4), partition x2); -ERROR HY000: RANGE PARTITIONING requires definition of VALUES LESS THAN for each partition +ERROR HY000: Syntax error: RANGE PARTITIONING requires definition of VALUES LESS THAN for each partition CREATE TABLE t1 ( a int not null, b int not null, @@ -531,7 +540,7 @@ partition by list (a) partitions 2 (partition x1 values in (4), partition x2); -ERROR HY000: LIST PARTITIONING requires definition of VALUES IN for each partition +ERROR HY000: Syntax error: LIST PARTITIONING requires definition of VALUES IN for each partition CREATE TABLE t1 ( a int not null, b int not null, @@ -551,7 +560,7 @@ partition by list (a) partitions 2 (partition x1 values in (4,6), partition x2); -ERROR HY000: LIST PARTITIONING requires definition of VALUES IN for each partition +ERROR HY000: Syntax error: LIST PARTITIONING requires definition of VALUES IN for each partition CREATE TABLE t1 ( a int not null, b int not null, diff --git a/mysql-test/r/partition_hash.result b/mysql-test/r/partition_hash.result index 9a82a36d902..72f036be099 100644 --- a/mysql-test/r/partition_hash.result +++ b/mysql-test/r/partition_hash.result @@ -183,3 +183,6 @@ c1 c2 c3 182 abc 2002-11-09 184 abc 2002-11-22 drop table t1; +CREATE TABLE t1 (c1 INT) ENGINE=MyISAM PARTITION BY HASH(c1) PARTITIONS 1; +INSERT DELAYED INTO t1 VALUES (1); +DROP TABLE t1; diff --git a/mysql-test/r/partition_innodb.result b/mysql-test/r/partition_innodb.result index 5b755b6bfd5..f80e0001ea8 100644 --- a/mysql-test/r/partition_innodb.result +++ b/mysql-test/r/partition_innodb.result @@ -136,3 +136,16 @@ SELECT COUNT(*) FROM t1; COUNT(*) 2 DROP TABLE t1; +create table t1 (int_column int, char_column char(5)) +PARTITION BY RANGE (int_column) subpartition by key (char_column) subpartitions 2 +(PARTITION p1 VALUES LESS THAN (5) ENGINE = InnoDB); +alter table t1 PARTITION BY RANGE (int_column) +subpartition by key (char_column) subpartitions 2 +(PARTITION p1 VALUES LESS THAN (5) ENGINE = myisam); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `int_column` int(11) DEFAULT NULL, + `char_column` char(5) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 /*!50100 PARTITION BY RANGE (int_column) SUBPARTITION BY KEY (char_column) SUBPARTITIONS 2 (PARTITION p1 VALUES LESS THAN (5) ENGINE = MyISAM) */ +drop table t1; diff --git a/mysql-test/r/partition_mgm.result b/mysql-test/r/partition_mgm.result index 04ac603fea7..9ef220028b3 100644 --- a/mysql-test/r/partition_mgm.result +++ b/mysql-test/r/partition_mgm.result @@ -17,12 +17,6 @@ t1 CREATE TABLE `t1` ( `f_date` date DEFAULT NULL, `f_varchar` varchar(30) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 /*!50100 PARTITION BY HASH (YEAR(f_date)) PARTITIONS 2 */ -hello/master-data/test/t1#P#p0.MYD -hello/master-data/test/t1#P#p0.MYI -hello/master-data/test/t1#P#p1.MYD -hello/master-data/test/t1#P#p1.MYI -hello/master-data/test/t1.frm -hello/master-data/test/t1.par ALTER TABLE t1 COALESCE PARTITION 1; SHOW CREATE TABLE t1; Table Create Table @@ -30,10 +24,6 @@ t1 CREATE TABLE `t1` ( `f_date` date DEFAULT NULL, `f_varchar` varchar(30) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 /*!50100 PARTITION BY HASH (YEAR(f_date)) PARTITIONS 1 */ -hello/master-data/test/t1#P#p0.MYD -hello/master-data/test/t1#P#p0.MYI -hello/master-data/test/t1.frm -hello/master-data/test/t1.par drop table t1; create table t1 (a int) partition by list (a) diff --git a/mysql-test/r/partition_symlink.result b/mysql-test/r/partition_symlink.result new file mode 100644 index 00000000000..20e841d2e0e --- /dev/null +++ b/mysql-test/r/partition_symlink.result @@ -0,0 +1,83 @@ +DROP TABLE IF EXISTS t1; +DROP DATABASE IF EXISTS mysqltest2; +# Creating two non colliding tables mysqltest2.t1 and test.t1 +# test.t1 have partitions in mysqltest2-directory! +# user root: +CREATE USER mysqltest_1@localhost; +CREATE DATABASE mysqltest2; +USE mysqltest2; +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (0); +# user mysqltest_1: +USE test; +CREATE TABLE t1 (a INT) +PARTITION BY LIST (a) ( +PARTITION p0 VALUES IN (0) +DATA DIRECTORY 'MYSQLTEST_VARDIR/master-data/mysqltest2' + INDEX DIRECTORY 'MYSQLTEST_VARDIR/master-data/mysqltest2', +PARTITION p1 VALUES IN (1) +DATA DIRECTORY 'MYSQLTEST_VARDIR/master-data/test' + INDEX DIRECTORY 'MYSQLTEST_VARDIR/master-data/test', +PARTITION p2 VALUES IN (2) +); +# without the patch for bug#32091 this would create +# files mysqltest2/t1.MYD + .MYI and possible overwrite +# the mysqltest2.t1 table (depending on bug#32111) +ALTER TABLE t1 REMOVE PARTITIONING; +INSERT INTO t1 VALUES (1); +SELECT * FROM t1; +a +1 +# user root: +USE mysqltest2; +FLUSH TABLES; +# if the patch works, this should be different +# and before the patch they were the same! +SELECT * FROM t1; +a +0 +USE test; +SELECT * FROM t1; +a +1 +DROP TABLE t1; +DROP DATABASE mysqltest2; +# test that symlinks can not overwrite files when CREATE TABLE +# user root: +CREATE DATABASE mysqltest2; +USE mysqltest2; +CREATE TABLE t1 (a INT) +PARTITION BY LIST (a) ( +PARTITION p0 VALUES IN (0) +DATA DIRECTORY 'MYSQLTEST_VARDIR/master-data/mysqltest2' + INDEX DIRECTORY 'MYSQLTEST_VARDIR/master-data/mysqltest2', +PARTITION p1 VALUES IN (1) +DATA DIRECTORY 'MYSQLTEST_VARDIR/master-data/test' + INDEX DIRECTORY 'MYSQLTEST_VARDIR/master-data/test' + ); +# user mysqltest_1: +USE test; +CREATE TABLE t1 (a INT) +PARTITION BY LIST (a) ( +PARTITION p0 VALUES IN (0) +DATA DIRECTORY 'MYSQLTEST_VARDIR/master-data/mysqltest2' + INDEX DIRECTORY 'MYSQLTEST_VARDIR/master-data/mysqltest2', +PARTITION p1 VALUES IN (1) +DATA DIRECTORY 'MYSQLTEST_VARDIR/master-data/test' + INDEX DIRECTORY 'MYSQLTEST_VARDIR/master-data/test' + ); +Got one of the listed errors +CREATE TABLE t1 (a INT) +PARTITION BY LIST (a) ( +PARTITION p0 VALUES IN (0) +DATA DIRECTORY 'MYSQLTEST_VARDIR/master-data/test' + INDEX DIRECTORY 'MYSQLTEST_VARDIR/master-data/test', +PARTITION p1 VALUES IN (1) +DATA DIRECTORY 'MYSQLTEST_VARDIR/master-data/mysqltest2' + INDEX DIRECTORY 'MYSQLTEST_VARDIR/master-data/mysqltest2' + ); +Got one of the listed errors +# user root (cleanup): +DROP DATABASE mysqltest2; +USE test; +DROP USER mysqltest_1@localhost; diff --git a/mysql-test/r/plugin.result b/mysql-test/r/plugin.result index 8628acecf55..e4af1535775 100644 --- a/mysql-test/r/plugin.result +++ b/mysql-test/r/plugin.result @@ -17,3 +17,13 @@ UNINSTALL PLUGIN EXAMPLE; ERROR 42000: PLUGIN EXAMPLE does not exist UNINSTALL PLUGIN non_exist; ERROR 42000: PLUGIN non_exist does not exist +# +# Bug#32034: check_func_enum() does not check correct values but set it +# to impossible int val +# +INSTALL PLUGIN example SONAME 'ha_example.so'; +SET GLOBAL example_enum_var= e1; +SET GLOBAL example_enum_var= e2; +SET GLOBAL example_enum_var= impossible; +ERROR 42000: Variable 'enum_var' can't be set to the value of 'impossible' +UNINSTALL PLUGIN example; diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index 9d0906ad5e7..ae68f8a4c5e 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -1143,6 +1143,11 @@ a 13 DEALLOCATE PREPARE st1; DROP TABLE t1; +create table t1 (a int, b tinyint); +prepare st1 from 'update t1 set b= (str_to_date(a, a))'; +execute st1; +deallocate prepare st1; +drop table t1; End of 4.1 tests. create table t1 (a varchar(20)); insert into t1 values ('foo'); diff --git a/mysql-test/r/ps_2myisam.result b/mysql-test/r/ps_2myisam.result index 6f0bad71f23..eb8ef7a85c3 100644 --- a/mysql-test/r/ps_2myisam.result +++ b/mysql-test/r/ps_2myisam.result @@ -63,7 +63,7 @@ def test t9 t9 c11 c11 246 9 6 Y 0 4 63 def test t9 t9 c12 c12 246 10 6 Y 0 4 63 def test t9 t9 c13 c13 10 10 10 Y 128 0 63 def test t9 t9 c14 c14 12 19 19 Y 128 0 63 -def test t9 t9 c15 c15 7 19 19 N 1249 0 63 +def test t9 t9 c15 c15 7 19 19 N 9441 0 63 def test t9 t9 c16 c16 11 8 8 Y 128 0 63 def test t9 t9 c17 c17 13 4 4 Y 32864 0 63 def test t9 t9 c18 c18 1 4 1 Y 32768 0 63 diff --git a/mysql-test/r/ps_3innodb.result b/mysql-test/r/ps_3innodb.result index 85a109b0630..15650efa41d 100644 --- a/mysql-test/r/ps_3innodb.result +++ b/mysql-test/r/ps_3innodb.result @@ -63,7 +63,7 @@ def test t9 t9 c11 c11 246 9 6 Y 0 4 63 def test t9 t9 c12 c12 246 10 6 Y 0 4 63 def test t9 t9 c13 c13 10 10 10 Y 128 0 63 def test t9 t9 c14 c14 12 19 19 Y 128 0 63 -def test t9 t9 c15 c15 7 19 19 N 1249 0 63 +def test t9 t9 c15 c15 7 19 19 N 9441 0 63 def test t9 t9 c16 c16 11 8 8 Y 128 0 63 def test t9 t9 c17 c17 13 4 4 Y 32864 0 63 def test t9 t9 c18 c18 1 4 1 Y 32768 0 63 diff --git a/mysql-test/r/ps_4heap.result b/mysql-test/r/ps_4heap.result index 980b89ad504..486f770220e 100644 --- a/mysql-test/r/ps_4heap.result +++ b/mysql-test/r/ps_4heap.result @@ -64,7 +64,7 @@ def test t9 t9 c11 c11 246 9 6 Y 0 4 63 def test t9 t9 c12 c12 246 10 6 Y 0 4 63 def test t9 t9 c13 c13 10 10 10 Y 128 0 63 def test t9 t9 c14 c14 12 19 19 Y 128 0 63 -def test t9 t9 c15 c15 7 19 19 N 1249 0 63 +def test t9 t9 c15 c15 7 19 19 N 9441 0 63 def test t9 t9 c16 c16 11 8 8 Y 128 0 63 def test t9 t9 c17 c17 13 4 4 Y 32864 0 63 def test t9 t9 c18 c18 1 4 1 Y 32768 0 63 diff --git a/mysql-test/r/ps_5merge.result b/mysql-test/r/ps_5merge.result index e95f8766a24..0229b0ece08 100644 --- a/mysql-test/r/ps_5merge.result +++ b/mysql-test/r/ps_5merge.result @@ -106,7 +106,7 @@ def test t9 t9 c11 c11 246 9 6 Y 0 4 63 def test t9 t9 c12 c12 246 10 6 Y 0 4 63 def test t9 t9 c13 c13 10 10 10 Y 128 0 63 def test t9 t9 c14 c14 12 19 19 Y 128 0 63 -def test t9 t9 c15 c15 7 19 19 N 1249 0 63 +def test t9 t9 c15 c15 7 19 19 N 9441 0 63 def test t9 t9 c16 c16 11 8 8 Y 128 0 63 def test t9 t9 c17 c17 13 4 4 Y 32864 0 63 def test t9 t9 c18 c18 1 4 1 Y 32768 0 63 @@ -3128,7 +3128,7 @@ def test t9 t9 c11 c11 246 9 6 Y 0 4 63 def test t9 t9 c12 c12 246 10 6 Y 0 4 63 def test t9 t9 c13 c13 10 10 10 Y 128 0 63 def test t9 t9 c14 c14 12 19 19 Y 128 0 63 -def test t9 t9 c15 c15 7 19 19 N 1249 0 63 +def test t9 t9 c15 c15 7 19 19 N 9441 0 63 def test t9 t9 c16 c16 11 8 8 Y 128 0 63 def test t9 t9 c17 c17 13 4 4 Y 32864 0 63 def test t9 t9 c18 c18 1 4 1 Y 32768 0 63 diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index 1acb82e4137..719d0926022 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -2827,6 +2827,14 @@ FFFFFFFFFFFFFFFF 7FFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF 7FFFFFFFFFFFFFFF 8FFFFFFFFFFFFFFF 7FFFFFFFFFFFFFFF drop table t1; +CREATE TABLE t1 (c0 int); +CREATE TABLE t2 (c0 int); +INSERT INTO t1 VALUES(@@connect_timeout); +INSERT INTO t2 VALUES(@@connect_timeout); +SELECT * FROM t1 JOIN t2 ON t1.c0 = t2.c0 WHERE (t1.c0 <=> @@connect_timeout); +c0 c0 +X X +DROP TABLE t1, t2; End of 4.1 tests CREATE TABLE t1 ( K2C4 varchar(4) character set latin1 collate latin1_bin NOT NULL default '', @@ -3233,40 +3241,40 @@ drop table t1, t2 ,t3; create table t1(f1 int, f2 date); insert into t1 values(1,'2005-01-01'),(2,'2005-09-01'),(3,'2005-09-30'), (4,'2005-10-01'),(5,'2005-12-30'); -select * from t1 where f2 >= 0; +select * from t1 where f2 >= 0 order by f2; f1 f2 1 2005-01-01 2 2005-09-01 3 2005-09-30 4 2005-10-01 5 2005-12-30 -select * from t1 where f2 >= '0000-00-00'; +select * from t1 where f2 >= '0000-00-00' order by f2; f1 f2 1 2005-01-01 2 2005-09-01 3 2005-09-30 4 2005-10-01 5 2005-12-30 -select * from t1 where f2 >= '2005-09-31'; +select * from t1 where f2 >= '2005-09-31' order by f2; f1 f2 4 2005-10-01 5 2005-12-30 -select * from t1 where f2 >= '2005-09-3a'; +select * from t1 where f2 >= '2005-09-3a' order by f2; f1 f2 +3 2005-09-30 4 2005-10-01 5 2005-12-30 Warnings: Warning 1292 Incorrect date value: '2005-09-3a' for column 'f2' at row 1 -select * from t1 where f2 <= '2005-09-31'; +select * from t1 where f2 <= '2005-09-31' order by f2; f1 f2 1 2005-01-01 2 2005-09-01 3 2005-09-30 -select * from t1 where f2 <= '2005-09-3a'; +select * from t1 where f2 <= '2005-09-3a' order by f2; f1 f2 1 2005-01-01 2 2005-09-01 -3 2005-09-30 Warnings: Warning 1292 Incorrect date value: '2005-09-3a' for column 'f2' at row 1 drop table t1; @@ -4062,25 +4070,208 @@ x 1 Warnings: Warning 1466 Leading spaces are removed from name ' x' +CREATE VIEW v1 AS SELECT 1 AS ``; +ERROR 42000: Incorrect column name '' CREATE VIEW v1 AS SELECT 1 AS ` `; -Warnings: -Warning 1474 Name ' ' has become '' -SELECT `` FROM v1; - -1 -CREATE VIEW v2 AS SELECT 1 AS ` `; -Warnings: -Warning 1474 Name ' ' has become '' -SELECT `` FROM v2; - -1 -CREATE VIEW v3 AS SELECT 1 AS ` x`; +ERROR 42000: Incorrect column name ' ' +CREATE VIEW v1 AS SELECT 1 AS ` `; +ERROR 42000: Incorrect column name ' ' +CREATE VIEW v1 AS SELECT (SELECT 1 AS ` `); +ERROR 42000: Incorrect column name ' ' +CREATE VIEW v1 AS SELECT 1 AS ` x`; Warnings: Warning 1466 Leading spaces are removed from name ' x' -SELECT `x` FROM v3; +SELECT `x` FROM v1; x 1 -DROP VIEW v1, v2, v3; +ALTER VIEW v1 AS SELECT 1 AS ` `; +ERROR 42000: Incorrect column name ' ' +DROP VIEW v1; +select str_to_date('2007-10-09','%Y-%m-%d') between '2007/10/01 00:00:00 GMT' + and '2007/10/20 00:00:00 GMT'; +str_to_date('2007-10-09','%Y-%m-%d') between '2007/10/01 00:00:00 GMT' + and '2007/10/20 00:00:00 GMT' +1 +Warnings: +Warning 1292 Truncated incorrect datetime value: '2007/10/01 00:00:00 GMT' +Warning 1292 Truncated incorrect datetime value: '2007/10/20 00:00:00 GMT' +select str_to_date('2007-10-09','%Y-%m-%d') > '2007/10/01 00:00:00 GMT-6'; +str_to_date('2007-10-09','%Y-%m-%d') > '2007/10/01 00:00:00 GMT-6' +1 +Warnings: +Warning 1292 Truncated incorrect date value: '2007/10/01 00:00:00 GMT-6' +select str_to_date('2007-10-09','%Y-%m-%d') <= '2007/10/2000:00:00 GMT-6'; +str_to_date('2007-10-09','%Y-%m-%d') <= '2007/10/2000:00:00 GMT-6' +1 +Warnings: +Warning 1292 Truncated incorrect date value: '2007/10/2000:00:00 GMT-6' +select str_to_date('2007-10-01','%Y-%m-%d') = '2007-10-1 00:00:00 GMT-6'; +str_to_date('2007-10-01','%Y-%m-%d') = '2007-10-1 00:00:00 GMT-6' +1 +Warnings: +Warning 1292 Truncated incorrect date value: '2007-10-1 00:00:00 GMT-6' +select str_to_date('2007-10-01','%Y-%m-%d') = '2007-10-01 x00:00:00 GMT-6'; +str_to_date('2007-10-01','%Y-%m-%d') = '2007-10-01 x00:00:00 GMT-6' +1 +Warnings: +Warning 1292 Truncated incorrect date value: '2007-10-01 x00:00:00 GMT-6' +select str_to_date('2007-10-01','%Y-%m-%d %H:%i:%s') = '2007-10-01 00:00:00 GMT-6'; +str_to_date('2007-10-01','%Y-%m-%d %H:%i:%s') = '2007-10-01 00:00:00 GMT-6' +1 +Warnings: +Warning 1292 Truncated incorrect datetime value: '2007-10-01 00:00:00 GMT-6' +select str_to_date('2007-10-01','%Y-%m-%d %H:%i:%s') = '2007-10-01 00:x00:00 GMT-6'; +str_to_date('2007-10-01','%Y-%m-%d %H:%i:%s') = '2007-10-01 00:x00:00 GMT-6' +1 +Warnings: +Warning 1292 Truncated incorrect datetime value: '2007-10-01 00:x00:00 GMT-6' +select str_to_date('2007-10-01','%Y-%m-%d %H:%i:%s') = '2007-10-01 x12:34:56 GMT-6'; +str_to_date('2007-10-01','%Y-%m-%d %H:%i:%s') = '2007-10-01 x12:34:56 GMT-6' +1 +Warnings: +Warning 1292 Truncated incorrect datetime value: '2007-10-01 x12:34:56 GMT-6' +select str_to_date('2007-10-01 12:34:00','%Y-%m-%d %H:%i:%s') = '2007-10-01 12:34x:56 GMT-6'; +str_to_date('2007-10-01 12:34:00','%Y-%m-%d %H:%i:%s') = '2007-10-01 12:34x:56 GMT-6' +1 +Warnings: +Warning 1292 Truncated incorrect datetime value: '2007-10-01 12:34x:56 GMT-6' +select str_to_date('2007-10-01 12:34:56','%Y-%m-%d %H:%i:%s') = '2007-10-01 12:34x:56 GMT-6'; +str_to_date('2007-10-01 12:34:56','%Y-%m-%d %H:%i:%s') = '2007-10-01 12:34x:56 GMT-6' +0 +Warnings: +Warning 1292 Truncated incorrect datetime value: '2007-10-01 12:34x:56 GMT-6' +select str_to_date('2007-10-01 12:34:56','%Y-%m-%d %H:%i:%s') = '2007-10-01 12:34:56'; +str_to_date('2007-10-01 12:34:56','%Y-%m-%d %H:%i:%s') = '2007-10-01 12:34:56' +1 +select str_to_date('2007-10-01','%Y-%m-%d') = '2007-10-01 12:00:00'; +str_to_date('2007-10-01','%Y-%m-%d') = '2007-10-01 12:00:00' +0 +select str_to_date('2007-10-01 12','%Y-%m-%d %H') = '2007-10-01 12:00:00'; +str_to_date('2007-10-01 12','%Y-%m-%d %H') = '2007-10-01 12:00:00' +1 +select str_to_date('2007-10-01 12:34','%Y-%m-%d %H') = '2007-10-01 12:00:00'; +str_to_date('2007-10-01 12:34','%Y-%m-%d %H') = '2007-10-01 12:00:00' +1 +Warnings: +Warning 1292 Truncated incorrect datetime value: '2007-10-01 12:34' +select str_to_date('2007-02-30 12:34','%Y-%m-%d %H:%i') = '2007-02-30 12:34'; +str_to_date('2007-02-30 12:34','%Y-%m-%d %H:%i') = '2007-02-30 12:34' +1 +select str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = '2007-10-00 12:34'; +str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = '2007-10-00 12:34' +1 +select str_to_date('2007-10-00','%Y-%m-%d') between '2007/09/01 00:00:00' + and '2007/10/20 00:00:00'; +str_to_date('2007-10-00','%Y-%m-%d') between '2007/09/01 00:00:00' + and '2007/10/20 00:00:00' +1 +set SQL_MODE=TRADITIONAL; +select str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = '2007-10-00 12:34'; +str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = '2007-10-00 12:34' +0 +Warnings: +Warning 1292 Truncated incorrect datetime value: '2007-10-00 12:34' +select str_to_date('2007-10-01 12:34','%Y-%m-%d %H:%i') = '2007-10-00 12:34'; +str_to_date('2007-10-01 12:34','%Y-%m-%d %H:%i') = '2007-10-00 12:34' +0 +Warnings: +Warning 1292 Truncated incorrect datetime value: '2007-10-00 12:34' +select str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = '2007-10-01 12:34'; +str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = '2007-10-01 12:34' +0 +Warnings: +Warning 1292 Truncated incorrect datetime value: '2007-10-00 12:34:00' +select str_to_date('2007-10-00','%Y-%m-%d') between '2007/09/01' + and '2007/10/20'; +str_to_date('2007-10-00','%Y-%m-%d') between '2007/09/01' + and '2007/10/20' +0 +Warnings: +Warning 1292 Incorrect datetime value: '2007-10-00' for column '2007/09/01' at row 1 +Warning 1292 Incorrect datetime value: '2007-10-00' for column '2007/10/20' at row 1 +set SQL_MODE=DEFAULT; +select str_to_date('2007-10-00','%Y-%m-%d') between '' and '2007/10/20'; +str_to_date('2007-10-00','%Y-%m-%d') between '' and '2007/10/20' +1 +Warnings: +Warning 1292 Truncated incorrect datetime value: '' +select str_to_date('','%Y-%m-%d') between '2007/10/01' and '2007/10/20'; +str_to_date('','%Y-%m-%d') between '2007/10/01' and '2007/10/20' +0 +select str_to_date('','%Y-%m-%d %H:%i') = '2007-10-01 12:34'; +str_to_date('','%Y-%m-%d %H:%i') = '2007-10-01 12:34' +0 +select str_to_date(NULL,'%Y-%m-%d %H:%i') = '2007-10-01 12:34'; +str_to_date(NULL,'%Y-%m-%d %H:%i') = '2007-10-01 12:34' +NULL +select str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = ''; +str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = '' +0 +Warnings: +Warning 1292 Truncated incorrect datetime value: '' +select str_to_date('1','%Y-%m-%d') = '1'; +str_to_date('1','%Y-%m-%d') = '1' +0 +Warnings: +Warning 1292 Truncated incorrect date value: '1' +select str_to_date('1','%Y-%m-%d') = '1'; +str_to_date('1','%Y-%m-%d') = '1' +0 +Warnings: +Warning 1292 Truncated incorrect date value: '1' +select str_to_date('','%Y-%m-%d') = ''; +str_to_date('','%Y-%m-%d') = '' +0 +Warnings: +Warning 1292 Truncated incorrect date value: '' +select str_to_date('1000-01-01','%Y-%m-%d') between '0000-00-00' and NULL; +str_to_date('1000-01-01','%Y-%m-%d') between '0000-00-00' and NULL +0 +select str_to_date('1000-01-01','%Y-%m-%d') between NULL and '2000-00-00'; +str_to_date('1000-01-01','%Y-%m-%d') between NULL and '2000-00-00' +0 +select str_to_date('1000-01-01','%Y-%m-%d') between NULL and NULL; +str_to_date('1000-01-01','%Y-%m-%d') between NULL and NULL +0 +CREATE TABLE t1 (c11 INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY); +CREATE TABLE t2 (c21 INT UNSIGNED NOT NULL, +c22 INT DEFAULT NULL, +KEY(c21, c22)); +CREATE TABLE t3 (c31 INT UNSIGNED NOT NULL DEFAULT 0, +c32 INT DEFAULT NULL, +c33 INT NOT NULL, +c34 INT UNSIGNED DEFAULT 0, +KEY (c33, c34, c32)); +INSERT INTO t1 values (),(),(),(),(); +INSERT INTO t2 SELECT a.c11, b.c11 FROM t1 a, t1 b; +INSERT INTO t3 VALUES (1, 1, 1, 0), +(2, 2, 0, 0), +(3, 3, 1, 0), +(4, 4, 0, 0), +(5, 5, 1, 0); +SELECT c32 FROM t1, t2, t3 WHERE t1.c11 IN (1, 3, 5) AND +t3.c31 = t1.c11 AND t2.c21 = t1.c11 AND +t3.c33 = 1 AND t2.c22 in (1, 3) +ORDER BY c32; +c32 +1 +1 +3 +3 +5 +5 +SELECT c32 FROM t1, t2, t3 WHERE t1.c11 IN (1, 3, 5) AND +t3.c31 = t1.c11 AND t2.c21 = t1.c11 AND +t3.c33 = 1 AND t2.c22 in (1, 3) +ORDER BY c32 DESC; +c32 +5 +5 +3 +3 +1 +1 +DROP TABLE t1, t2, t3; # # Bug#30736: Row Size Too Large Error Creating a Table and diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result index 04a5253e6a8..ff32d2a1512 100644 --- a/mysql-test/r/show_check.result +++ b/mysql-test/r/show_check.result @@ -979,7 +979,7 @@ def COLUMNS CHARACTER_SET_NAME CHARACTER_SET_NAME 253 192 0 Y 0 0 33 def COLUMNS COLLATION_NAME COLLATION_NAME 253 192 0 Y 0 0 33 def COLUMNS COLUMN_TYPE COLUMN_TYPE 252 589815 7 N 17 0 33 def COLUMNS COLUMN_KEY COLUMN_KEY 253 9 3 N 1 0 33 -def COLUMNS EXTRA EXTRA 253 60 0 N 1 0 33 +def COLUMNS EXTRA EXTRA 253 81 0 N 1 0 33 def COLUMNS PRIVILEGES PRIVILEGES 253 240 31 N 1 0 33 def COLUMNS COLUMN_COMMENT COLUMN_COMMENT 253 765 0 N 1 0 33 TABLE_CATALOG TABLE_SCHEMA TABLE_NAME COLUMN_NAME COLUMN_DEFAULT IS_NULLABLE DATA_TYPE CHARACTER_SET_NAME COLLATION_NAME COLUMN_TYPE COLUMN_KEY EXTRA PRIVILEGES COLUMN_COMMENT @@ -998,7 +998,7 @@ def COLUMNS COLUMN_TYPE Type 252 589815 7 N 17 0 33 def COLUMNS IS_NULLABLE Null 253 9 2 N 1 0 33 def COLUMNS COLUMN_KEY Key 253 9 3 N 1 0 33 def COLUMNS COLUMN_DEFAULT Default 252 589815 0 Y 16 0 33 -def COLUMNS EXTRA Extra 253 60 0 N 1 0 33 +def COLUMNS EXTRA Extra 253 81 0 N 1 0 33 Field Type Null Key Default Extra c int(11) NO PRI NULL ---------------------------------------------------------------- diff --git a/mysql-test/r/skip_grants.result b/mysql-test/r/skip_grants.result index 6bb8cbea2f1..bf0f16a174f 100644 --- a/mysql-test/r/skip_grants.result +++ b/mysql-test/r/skip_grants.result @@ -72,3 +72,15 @@ count(*) select count(*) from information_schema.USER_PRIVILEGES; count(*) 0 +CREATE FUNCTION a RETURNS STRING SONAME ''; +ERROR HY000: Can't initialize function 'a'; UDFs are unavailable with the --skip-grant-tables option +DROP FUNCTION a; +ERROR 42000: FUNCTION test.a does not exist +End of 5.0 tests +# +# Bug#29817 Queries with UDF fail with non-descriptive error +# if mysql.proc is missing +# +select no_such_function(1); +ERROR 42000: FUNCTION test.no_such_function does not exist +End of 5.1 tests diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 412f6b94fa2..68aa278585f 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -5670,7 +5670,7 @@ drop function if exists pi; create function pi() returns varchar(50) return "pie, my favorite desert."; Warnings: -Note 1584 This function 'pi' has the same name as a native function +Note 1585 This function 'pi' has the same name as a native function SET @save_sql_mode=@@sql_mode; SET SQL_MODE='IGNORE_SPACE'; select pi(), pi (); @@ -5719,15 +5719,15 @@ use test; create function `database`() returns varchar(50) return "Stored function database"; Warnings: -Note 1584 This function 'database' has the same name as a native function +Note 1585 This function 'database' has the same name as a native function create function `current_user`() returns varchar(50) return "Stored function current_user"; Warnings: -Note 1584 This function 'current_user' has the same name as a native function +Note 1585 This function 'current_user' has the same name as a native function create function md5(x varchar(50)) returns varchar(50) return "Stored function md5"; Warnings: -Note 1584 This function 'md5' has the same name as a native function +Note 1585 This function 'md5' has the same name as a native function SET SQL_MODE='IGNORE_SPACE'; select database(), database (); database() database () diff --git a/mysql-test/r/sp_gis.result b/mysql-test/r/sp_gis.result index b0960dec647..7a76507754f 100644 --- a/mysql-test/r/sp_gis.result +++ b/mysql-test/r/sp_gis.result @@ -7,11 +7,11 @@ return 1; create function x() returns int return 2; Warnings: -Note 1584 This function 'x' has the same name as a native function +Note 1585 This function 'x' has the same name as a native function create function y() returns int return 3; Warnings: -Note 1584 This function 'y' has the same name as a native function +Note 1585 This function 'y' has the same name as a native function select a(); a() 1 diff --git a/mysql-test/r/status.result b/mysql-test/r/status.result index db75044ee5d..c95b09597fc 100644 --- a/mysql-test/r/status.result +++ b/mysql-test/r/status.result @@ -8,6 +8,8 @@ VARIABLE_NAME VARIABLE_VALUE TABLE_LOCKS_IMMEDIATE 2 TABLE_LOCKS_WAITED 0 SET SQL_LOG_BIN=0; +set @old_general_log = @@global.general_log; +set global general_log = 'OFF'; drop table if exists t1; create table t1(n int) engine=myisam; insert into t1 values(1); @@ -20,6 +22,7 @@ show status like 'Table_locks_waited'; Variable_name Value Table_locks_waited 1 drop table t1; +set global general_log = @old_general_log; select 1; 1 1 diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index a25183a0e6d..25df7a56aa3 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -4139,6 +4139,66 @@ SELECT (SELECT SUM(t1.a) FROM t2 WHERE a=1) FROM t1; (SELECT SUM(t1.a) FROM t2 WHERE a=1) 3 DROP TABLE t1,t2; +CREATE TABLE t1 (a1 INT, a2 INT); +CREATE TABLE t2 (b1 INT, b2 INT); +INSERT INTO t1 VALUES (100, 200); +INSERT INTO t1 VALUES (101, 201); +INSERT INTO t2 VALUES (101, 201); +INSERT INTO t2 VALUES (103, 203); +SELECT ((a1,a2) IN (SELECT * FROM t2 WHERE b2 > 0)) IS NULL FROM t1; +((a1,a2) IN (SELECT * FROM t2 WHERE b2 > 0)) IS NULL +0 +0 +DROP TABLE t1, t2; +CREATE TABLE t1 (s1 BINARY(5), s2 VARBINARY(5)); +INSERT INTO t1 VALUES (0x41,0x41), (0x42,0x42), (0x43,0x43); +SELECT s1, s2 FROM t1 WHERE s2 IN (SELECT s1 FROM t1); +s1 s2 +SELECT s1, s2 FROM t1 WHERE (s2, 10) IN (SELECT s1, 10 FROM t1); +s1 s2 +CREATE INDEX I1 ON t1 (s1); +CREATE INDEX I2 ON t1 (s2); +SELECT s1, s2 FROM t1 WHERE s2 IN (SELECT s1 FROM t1); +s1 s2 +SELECT s1, s2 FROM t1 WHERE (s2, 10) IN (SELECT s1, 10 FROM t1); +s1 s2 +TRUNCATE t1; +INSERT INTO t1 VALUES (0x41,0x41); +SELECT * FROM t1 WHERE s1 = (SELECT s2 FROM t1); +s1 s2 +DROP TABLE t1; +CREATE TABLE t1 (a1 VARBINARY(2) NOT NULL DEFAULT '0', PRIMARY KEY (a1)); +CREATE TABLE t2 (a2 BINARY(2) default '0', INDEX (a2)); +CREATE TABLE t3 (a3 BINARY(2) default '0'); +INSERT INTO t1 VALUES (1),(2),(3),(4); +INSERT INTO t2 VALUES (1),(2),(3); +INSERT INTO t3 VALUES (1),(2),(3); +SELECT LEFT(t2.a2, 1) FROM t2,t3 WHERE t3.a3=t2.a2; +LEFT(t2.a2, 1) +1 +2 +3 +SELECT t1.a1, t1.a1 in (SELECT t2.a2 FROM t2,t3 WHERE t3.a3=t2.a2) FROM t1; +a1 t1.a1 in (SELECT t2.a2 FROM t2,t3 WHERE t3.a3=t2.a2) +1 0 +2 0 +3 0 +4 0 +DROP TABLE t1,t2,t3; +CREATE TABLE t1 (a1 BINARY(3) PRIMARY KEY, b1 VARBINARY(3)); +CREATE TABLE t2 (a2 VARBINARY(3) PRIMARY KEY); +CREATE TABLE t3 (a3 VARBINARY(3) PRIMARY KEY); +INSERT INTO t1 VALUES (1,10), (2,20), (3,30), (4,40); +INSERT INTO t2 VALUES (2), (3), (4), (5); +INSERT INTO t3 VALUES (10), (20), (30); +SELECT LEFT(t1.a1,1) FROM t1,t3 WHERE t1.b1=t3.a3; +LEFT(t1.a1,1) +1 +2 +3 +SELECT a2 FROM t2 WHERE t2.a2 IN (SELECT t1.a1 FROM t1,t3 WHERE t1.b1=t3.a3); +a2 +DROP TABLE t1, t2, t3; End of 5.0 tests. CREATE TABLE t1 (a int, b int); INSERT INTO t1 VALUES (2,22),(1,11),(2,22); diff --git a/mysql-test/r/symlink.result b/mysql-test/r/symlink.result index aba60f757c6..4eece9d5b5a 100644 --- a/mysql-test/r/symlink.result +++ b/mysql-test/r/symlink.result @@ -99,6 +99,12 @@ t1 CREATE TABLE `t1` ( `b` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; +CREATE TABLE t1(a INT) +DATA DIRECTORY='TEST_DIR/master-data/mysql' +INDEX DIRECTORY='TEST_DIR/master-data/mysql'; +RENAME TABLE t1 TO user; +ERROR HY000: Can't create/write to file 'TEST_DIR/master-data/mysql/user.MYI' (Errcode: 17) +DROP TABLE t1; show create table t1; Table Create Table t1 CREATE TABLE `t1` ( diff --git a/mysql-test/r/trigger.result b/mysql-test/r/trigger.result index 189722bfe9b..8b384dfdc4e 100644 --- a/mysql-test/r/trigger.result +++ b/mysql-test/r/trigger.result @@ -1978,3 +1978,42 @@ a 1 drop table table_25411_a; drop table table_25411_b; +DROP TRIGGER IF EXISTS trg; +SHOW CREATE TRIGGER trg; +ERROR HY000: Trigger does not exist +drop table if exists t1; +create table t1 (i int, j int); +create trigger t1_bi before insert on t1 for each row begin end; +create trigger t1_bi before insert on t1 for each row begin end; +ERROR 42000: This version of MySQL doesn't yet support 'multiple triggers with the same action time and event for one table' +drop trigger t1_bi; +drop trigger t1_bi; +ERROR HY000: Trigger does not exist +lock tables t1 read; +create trigger t1_bi before insert on t1 for each row begin end; +ERROR HY000: Table 't1' was locked with a READ lock and can't be updated +create trigger t1_bi before insert on t1 for each row begin end; +ERROR HY000: Table 't1' was locked with a READ lock and can't be updated +drop trigger t1_bi; +ERROR HY000: Trigger does not exist +unlock tables; +create trigger t1_bi before insert on t1 for each row begin end; +lock tables t1 read; +create trigger t1_bi before insert on t1 for each row begin end; +ERROR HY000: Table 't1' was locked with a READ lock and can't be updated +drop trigger t1_bi; +ERROR HY000: Table 't1' was locked with a READ lock and can't be updated +unlock tables; +drop trigger t1_bi; +lock tables t1 write; +create trigger b1_bi before insert on t1 for each row set new.i = new.i + 10; +insert into t1 values (10, 10); +drop trigger b1_bi; +insert into t1 values (10, 10); +select * from t1; +i j +20 10 +10 10 +unlock tables; +drop table t1; +End of 5.1 tests. diff --git a/mysql-test/r/trigger-grant.result b/mysql-test/r/trigger_notembedded.result similarity index 99% rename from mysql-test/r/trigger-grant.result rename to mysql-test/r/trigger_notembedded.result index 14b8c98f2fa..d56f83993a6 100644 --- a/mysql-test/r/trigger-grant.result +++ b/mysql-test/r/trigger_notembedded.result @@ -448,3 +448,4 @@ DROP TABLE t1; DROP DATABASE mysqltest_db1; USE test; End of 5.0 tests. +End of 5.1 tests. diff --git a/mysql-test/r/type_date.result b/mysql-test/r/type_date.result index 904db1a14d0..392260edb55 100644 --- a/mysql-test/r/type_date.result +++ b/mysql-test/r/type_date.result @@ -224,3 +224,10 @@ ERROR 22007: Incorrect date value: '0000-00-00' for column 'a' at row 1 SET SQL_MODE=DEFAULT; DROP TABLE t1,t2; End of 5.0 tests +create table t1 (a date, primary key (a))engine=memory; +insert into t1 values ('0000-01-01'), ('0000-00-01'), ('0001-01-01'); +select * from t1 where a between '0000-00-01' and '0000-00-02'; +a +0000-00-01 +drop table t1; +End of 5.1 tests diff --git a/mysql-test/r/type_decimal.result b/mysql-test/r/type_decimal.result index 42276a004bb..e37a398d22e 100644 --- a/mysql-test/r/type_decimal.result +++ b/mysql-test/r/type_decimal.result @@ -812,4 +812,81 @@ select group_concat(f1),group_concat(f2) from t1; group_concat(f1) group_concat(f2) -0.123456 0.123456 drop table t1; +create table t1 ( +ua_id decimal(22,0) not null, +ua_invited_by_id decimal(22,0) default NULL, +primary key(ua_id) +); +insert into t1 values (123, NULL), (456, NULL); +this must not produce error 1048: +select * from t1 where ua_invited_by_id not in (select ua_id from t1); +ua_id ua_invited_by_id +drop table t1; +DROP TABLE IF EXISTS t3; +DROP TABLE IF EXISTS t4; +CREATE TABLE t1( a NUMERIC, b INT ); +INSERT INTO t1 VALUES (123456, 40), (123456, 40); +SELECT TRUNCATE( a, b ) AS c FROM t1 ORDER BY c; +c +123456 +123456 +SELECT ROUND( a, b ) AS c FROM t1 ORDER BY c; +c +123456 +123456 +SELECT ROUND( a, 100 ) AS c FROM t1 ORDER BY c; +c +123456.000000000000000000000000000000 +123456.000000000000000000000000000000 +CREATE TABLE t2( a NUMERIC, b INT ); +INSERT INTO t2 VALUES (123456, 100); +SELECT TRUNCATE( a, b ) AS c FROM t2 ORDER BY c; +c +123456 +SELECT ROUND( a, b ) AS c FROM t2 ORDER BY c; +c +123456 +CREATE TABLE t3( a DECIMAL, b INT ); +INSERT INTO t3 VALUES (123456, 40), (123456, 40); +SELECT TRUNCATE( a, b ) AS c FROM t3 ORDER BY c; +c +123456 +123456 +SELECT ROUND( a, b ) AS c FROM t3 ORDER BY c; +c +123456 +123456 +SELECT ROUND( a, 100 ) AS c FROM t3 ORDER BY c; +c +123456.000000000000000000000000000000 +123456.000000000000000000000000000000 +CREATE TABLE t4( a DECIMAL, b INT ); +INSERT INTO t4 VALUES (123456, 40), (123456, 40); +SELECT TRUNCATE( a, b ) AS c FROM t4 ORDER BY c; +c +123456 +123456 +SELECT ROUND( a, b ) AS c FROM t4 ORDER BY c; +c +123456 +123456 +SELECT ROUND( a, 100 ) AS c FROM t4 ORDER BY c; +c +123456.000000000000000000000000000000 +123456.000000000000000000000000000000 +delete from t1; +INSERT INTO t1 VALUES (1234567890, 20), (999.99, 5); +Warnings: +Note 1265 Data truncated for column 'a' at row 2 +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` decimal(10,0) DEFAULT NULL, + `b` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +select round(a,b) as c from t1 order by c; +c +1000 +1234567890 +DROP TABLE t1, t2, t3, t4; End of 5.0 tests diff --git a/mysql-test/r/type_newdecimal.result b/mysql-test/r/type_newdecimal.result index 24be10a7a29..71be41b106f 100644 --- a/mysql-test/r/type_newdecimal.result +++ b/mysql-test/r/type_newdecimal.result @@ -1509,6 +1509,26 @@ SELECT 1 FROM t1 GROUP BY @b := @a, @b; 1 1 DROP TABLE t1; +CREATE TABLE t1 SELECT 0.123456789012345678901234567890123456 AS f1; +Warnings: +Note 1265 Data truncated for column 'f1' at row 1 +DESC t1; +Field Type Null Key Default Extra +f1 decimal(31,30) NO 0.000000000000000000000000000000 +SELECT f1 FROM t1; +f1 +0.123456789012345678901234567890 +DROP TABLE t1; +CREATE TABLE t1 SELECT 123451234512345123451234512345123451234512345.678906789067890678906789067890678906789067890 AS f1; +Warnings: +Warning 1264 Out of range value for column 'f1' at row 1 +DESC t1; +Field Type Null Key Default Extra +f1 decimal(59,30) NO 0.000000000000000000000000000000 +SELECT f1 FROM t1; +f1 +99999999999999999999999999999.999999999999999999999999999999 +DROP TABLE t1; End of 5.0 tests select cast(143.481 as decimal(4,1)); cast(143.481 as decimal(4,1)) diff --git a/mysql-test/r/type_ranges.result b/mysql-test/r/type_ranges.result index 149f0d2dca5..6e08067d8a4 100644 --- a/mysql-test/r/type_ranges.result +++ b/mysql-test/r/type_ranges.result @@ -57,7 +57,7 @@ ushort smallint(5) unsigned zerofill NULL NO MUL 00000 # umedium mediumint(8) unsigned NULL NO MUL 0 # ulong int(11) unsigned NULL NO MUL 0 # ulonglong bigint(13) unsigned NULL NO MUL 0 # -time_stamp timestamp NULL NO CURRENT_TIMESTAMP # +time_stamp timestamp NULL NO CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP # date_field date NULL YES NULL # time_field time NULL YES NULL # date_time datetime NULL YES NULL # @@ -225,7 +225,7 @@ ushort smallint(5) unsigned zerofill NULL NO 00000 # umedium mediumint(8) unsigned NULL NO MUL 0 # ulong int(11) unsigned NULL NO MUL 0 # ulonglong bigint(13) unsigned NULL NO MUL 0 # -time_stamp timestamp NULL NO CURRENT_TIMESTAMP # +time_stamp timestamp NULL NO CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP # date_field char(10) latin1_swedish_ci YES NULL # time_field time NULL YES NULL # date_time datetime NULL YES NULL # diff --git a/mysql-test/r/type_timestamp.result b/mysql-test/r/type_timestamp.result index 7caf7e78fe9..596dcbf432c 100644 --- a/mysql-test/r/type_timestamp.result +++ b/mysql-test/r/type_timestamp.result @@ -251,7 +251,7 @@ t1 CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 show columns from t1; Field Type Null Key Default Extra -t1 timestamp NO 2003-01-01 00:00:00 +t1 timestamp NO 2003-01-01 00:00:00 on update CURRENT_TIMESTAMP t2 datetime YES NULL drop table t1; create table t1 (t1 timestamp default now() on update now(), t2 datetime); @@ -276,7 +276,7 @@ t1 CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 show columns from t1; Field Type Null Key Default Extra -t1 timestamp NO CURRENT_TIMESTAMP +t1 timestamp NO CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP t2 datetime YES NULL drop table t1; create table t1 (t1 timestamp, t2 datetime, t3 timestamp); @@ -302,7 +302,7 @@ t1 CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 show columns from t1; Field Type Null Key Default Extra -t1 timestamp NO CURRENT_TIMESTAMP +t1 timestamp NO CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP t2 datetime YES NULL t3 timestamp NO 0000-00-00 00:00:00 drop table t1; @@ -328,7 +328,7 @@ t1 CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 show columns from t1; Field Type Null Key Default Extra -t1 timestamp NO CURRENT_TIMESTAMP +t1 timestamp NO CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP t2 datetime YES NULL truncate table t1; insert into t1 values ('2004-04-01 00:00:00', '2004-04-01 00:00:00'); diff --git a/mysql-test/r/user_var.result b/mysql-test/r/user_var.result index 6fd7b39f226..431134b03c7 100644 --- a/mysql-test/r/user_var.result +++ b/mysql-test/r/user_var.result @@ -353,3 +353,14 @@ select @a:=f4, count(f4) from t1 group by 1 desc; 2.6 1 1.6 4 drop table t1; +create table t1(a int); +insert into t1 values(5),(4),(4),(3),(2),(2),(2),(1); +set @rownum := 0; +set @rank := 0; +set @prev_score := NULL; +select @rownum := @rownum + 1 as row, +@rank := IF(@prev_score!=a, @rownum, @rank) as rank, +@prev_score := a as score +from t1 order by score desc; +drop table t1; +End of 5.1 tests diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 60c3ff68e67..2971af7347d 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -3617,4 +3617,47 @@ DROP TABLE `t-2`; DROP VIEW `v-2`; DROP DATABASE `d-1`; USE test; + +# +# Bug#26676: VIEW using old table schema in a session. +# + +DROP VIEW IF EXISTS v1; +DROP TABLE IF EXISTS t1; +CREATE TABLE t1(c1 INT, c2 INT); +INSERT INTO t1 VALUES (1, 2), (3, 4); + +SELECT * FROM t1; +c1 c2 +1 2 +3 4 + +CREATE VIEW v1 AS SELECT * FROM t1; + +SELECT * FROM v1; +c1 c2 +1 2 +3 4 + +ALTER TABLE t1 ADD COLUMN c3 INT AFTER c2; + +SELECT * FROM t1; +c1 c2 c3 +1 2 NULL +3 4 NULL + +SELECT * FROM v1; +c1 c2 +1 2 +3 4 + +SHOW CREATE VIEW v1; +View Create View character_set_client collation_connection +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`c1` AS `c1`,`t1`.`c2` AS `c2` from `t1` latin1 latin1_swedish_ci + +DROP VIEW v1; +DROP TABLE t1; + +# End of test case for Bug#26676. + End of 5.1 tests. diff --git a/mysql-test/r/xml.result b/mysql-test/r/xml.result index 552f4896698..56c884343e3 100644 --- a/mysql-test/r/xml.result +++ b/mysql-test/r/xml.result @@ -647,32 +647,32 @@ select extractValue('a','/a'); extractValue('a','/a') NULL Warnings: -Warning 1524 Incorrect XML value: 'parse error at line 1 pos 5: unexpected END-OF-INPUT' +Warning 1525 Incorrect XML value: 'parse error at line 1 pos 5: unexpected END-OF-INPUT' select extractValue('a<','/a'); extractValue('a<','/a') NULL Warnings: -Warning 1524 Incorrect XML value: 'parse error at line 1 pos 6: END-OF-INPUT unexpected (ident or '/' wanted)' +Warning 1525 Incorrect XML value: 'parse error at line 1 pos 6: END-OF-INPUT unexpected (ident or '/' wanted)' select extractValue('aaaa' wanted)' +Warning 1525 Incorrect XML value: 'parse error at line 1 pos 8: END-OF-INPUT unexpected ('>' wanted)' select extractValue('a','/a'); extractValue('a','/a') NULL Warnings: -Warning 1524 Incorrect XML value: 'parse error at line 1 pos 12: '' unexpected (END-OF-INPUT wanted)' +Warning 1525 Incorrect XML value: 'parse error at line 1 pos 12: '' unexpected (END-OF-INPUT wanted)' select extractValue('a','/a'); extractValue('a','/a') NULL Warnings: -Warning 1524 Incorrect XML value: 'parse error at line 1 pos 7: '>' unexpected (ident or string wanted)' +Warning 1525 Incorrect XML value: 'parse error at line 1 pos 7: '>' unexpected (ident or string wanted)' select extractValue('1','position()'); ERROR HY000: XPATH syntax error: '' select extractValue('1','last()'); @@ -723,17 +723,17 @@ select extractValue('<01>10:39:15<02>140','//* extractValue('<01>10:39:15<02>140','//*') NULL Warnings: -Warning 1524 Incorrect XML value: 'parse error at line 1 pos 13: unknown token unexpected (ident or '/' wanted)' +Warning 1525 Incorrect XML value: 'parse error at line 1 pos 13: unknown token unexpected (ident or '/' wanted)' select extractValue('<.>test','//*'); extractValue('<.>test','//*') NULL Warnings: -Warning 1524 Incorrect XML value: 'parse error at line 1 pos 2: unknown token unexpected (ident or '/' wanted)' +Warning 1525 Incorrect XML value: 'parse error at line 1 pos 2: unknown token unexpected (ident or '/' wanted)' select extractValue('<->test','//*'); extractValue('<->test','//*') NULL Warnings: -Warning 1524 Incorrect XML value: 'parse error at line 1 pos 2: unknown token unexpected (ident or '/' wanted)' +Warning 1525 Incorrect XML value: 'parse error at line 1 pos 2: unknown token unexpected (ident or '/' wanted)' select extractValue('<:>test','//*'); extractValue('<:>test','//*') test @@ -1022,4 +1022,11 @@ NULL NULL NULL select updatexml(NULL, NULL, NULL); updatexml(NULL, NULL, NULL) NULL +CREATE TABLE t1(a INT NOT NULL); +INSERT INTO t1 VALUES (0), (0); +SELECT 1 FROM t1 ORDER BY(UPDATEXML(a, '1', '1')); +1 +1 +1 +DROP TABLE t1; End of 5.1 tests diff --git a/mysql-test/std_data/corrupt-relay-bin.000624 b/mysql-test/std_data/corrupt-relay-bin.000624 new file mode 100644 index 00000000000..21b4901211c Binary files /dev/null and b/mysql-test/std_data/corrupt-relay-bin.000624 differ diff --git a/mysql-test/suite/binlog/r/binlog_database.result b/mysql-test/suite/binlog/r/binlog_database.result new file mode 100644 index 00000000000..7deffb86244 --- /dev/null +++ b/mysql-test/suite/binlog/r/binlog_database.result @@ -0,0 +1,56 @@ +set binlog_format=statement; +reset master; +create database testing_1; +use testing_1; +create table t1 (a int); +create function sf1 (a int) returns int return a+1; +create trigger tr1 before insert on t1 for each row insert into t2 values (2*new.a); +create procedure sp1 (a int) insert into t1 values(a); +drop database testing_1; +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # create database testing_1 +master-bin.000001 # Query # # use `testing_1`; create table t1 (a int) +master-bin.000001 # Query # # use `testing_1`; CREATE DEFINER=`root`@`localhost` function sf1 (a int) returns int return a+1 +master-bin.000001 # Query # # use `testing_1`; CREATE DEFINER=`root`@`localhost` trigger tr1 before insert on t1 for each row insert into t2 values (2*new.a) +master-bin.000001 # Query # # use `testing_1`; CREATE DEFINER=`root`@`localhost` procedure sp1 (a int) insert into t1 values(a) +master-bin.000001 # Query # # drop database testing_1 +set binlog_format=mixed; +reset master; +create database testing_1; +use testing_1; +create table t1 (a int); +create function sf1 (a int) returns int return a+1; +create trigger tr1 before insert on t1 for each row insert into t2 values (2*new.a); +create procedure sp1 (a int) insert into t1 values(a); +drop database testing_1; +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # create database testing_1 +master-bin.000001 # Query # # use `testing_1`; create table t1 (a int) +master-bin.000001 # Query # # use `testing_1`; CREATE DEFINER=`root`@`localhost` function sf1 (a int) returns int return a+1 +master-bin.000001 # Query # # use `testing_1`; CREATE DEFINER=`root`@`localhost` trigger tr1 before insert on t1 for each row insert into t2 values (2*new.a) +master-bin.000001 # Query # # use `testing_1`; CREATE DEFINER=`root`@`localhost` procedure sp1 (a int) insert into t1 values(a) +master-bin.000001 # Query # # drop database testing_1 +set binlog_format=row; +reset master; +create database testing_1; +use testing_1; +create table t1 (a int); +create function sf1 (a int) returns int return a+1; +create trigger tr1 before insert on t1 for each row insert into t2 values (2*new.a); +create procedure sp1 (a int) insert into t1 values(a); +drop database testing_1; +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # create database testing_1 +master-bin.000001 # Query # # use `testing_1`; create table t1 (a int) +master-bin.000001 # Query # # use `testing_1`; CREATE DEFINER=`root`@`localhost` function sf1 (a int) returns int return a+1 +master-bin.000001 # Query # # use `testing_1`; CREATE DEFINER=`root`@`localhost` trigger tr1 before insert on t1 for each row insert into t2 values (2*new.a) +master-bin.000001 # Query # # use `testing_1`; CREATE DEFINER=`root`@`localhost` procedure sp1 (a int) insert into t1 values(a) +master-bin.000001 # Query # # drop database testing_1 +show databases; +Database +information_schema +mysql +test diff --git a/mysql-test/suite/binlog/r/binlog_killed.result b/mysql-test/suite/binlog/r/binlog_killed.result index ba4f38fb4c1..72fda535b6f 100644 --- a/mysql-test/suite/binlog/r/binlog_killed.result +++ b/mysql-test/suite/binlog/r/binlog_killed.result @@ -9,4 +9,135 @@ insert into t2 values (null, null), (null, get_lock("a", 10)); select @result /* must be zero either way */; @result 0 +select RELEASE_LOCK("a"); +RELEASE_LOCK("a") +1 +delete from t1; +delete from t2; +insert into t1 values (1,1),(2,2); +begin; +update t1 set b=11 where a=2; +begin; +update t1 set b=b+10; +kill query ID; +rollback; +rollback; +select * from t1 order by a /* must be the same as before (1,1),(2,2) */; +a b +1 1 +2 2 +begin; +delete from t1 where a=2; +begin; +delete from t1 where a=2; +kill query ID; +rollback; +rollback; +select * from t1 order by a /* must be the same as before (1,1),(2,2) */; +a b +1 1 +2 2 +drop table if exists t4; +create table t4 (a int, b int) engine=innodb; +insert into t4 values (3, 3); +begin; +insert into t1 values (3, 3); +begin; +insert into t1 select * from t4 for update; +kill query ID; +rollback; +rollback; +select * from t1 /* must be the same as before (1,1),(2,2) */; +a b +1 1 +2 2 +drop table t4; +create table t4 (a int, b int) ENGINE=MyISAM /* for killing update and delete */; +create function bug27563(n int) +RETURNS int(11) +DETERMINISTIC +begin +if @b > 0 then +select get_lock("a", 20) into @a; +else +set @b= 1; +end if; +return n; +end| +delete from t4; +insert into t4 values (1,1), (1,1); +reset master; +select get_lock("a", 20); +get_lock("a", 20) +1 +set @b= 0; +update t4 set b=b + bug27563(b); +select count(*) FROM INFORMATION_SCHEMA.PROCESSLIST where state='User lock'; +count(*) +1 +kill query ID; +ERROR 70100: Query execution was interrupted +select * from t4 order by b /* must be (1,1), (1,2) */; +a b +1 1 +1 2 +select @b /* must be 1 at the end of a stmt calling bug27563() */; +@b +1 +must have the update query event more to FD +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # User var # # @`b`=0 +master-bin.000001 # Query # # use `test`; update t4 set b=b + bug27563(b) +select +(@a:=load_file("MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog")) +is not null; +(@a:=load_file("MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog")) +is not null +1 +select 0 /* must return 0 to mean the killed query is in */; +0 +0 +select RELEASE_LOCK("a"); +RELEASE_LOCK("a") +1 +delete from t4; +insert into t4 values (1,1), (2,2); +reset master; +select get_lock("a", 20); +get_lock("a", 20) +1 +set @b= 0; +delete from t4 where b=bug27563(1) or b=bug27563(2); +select count(*) FROM INFORMATION_SCHEMA.PROCESSLIST where state='User lock'; +count(*) +1 +kill query ID; +ERROR 70100: Query execution was interrupted +select count(*) from t4 /* must be 1 */; +count(*) +1 +select @b /* must be 1 at the end of a stmt calling bug27563() */; +@b +1 +must have the delete query event more to FD +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # User var # # @`b`=0 +master-bin.000001 # Query # # use `test`; delete from t4 where b=bug27563(1) or b=bug27563(2) +select +(@a:=load_file("MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog")) +is not null; +(@a:=load_file("MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog")) +is not null +1 +select 0 /* must return 0 to mean the killed query is in */; +0 +0 +select RELEASE_LOCK("a"); +RELEASE_LOCK("a") +1 +drop table t4; +drop function bug27563; drop table t1,t2,t3; +end of the tests diff --git a/mysql-test/suite/binlog/r/binlog_killed_simulate.result b/mysql-test/suite/binlog/r/binlog_killed_simulate.result new file mode 100644 index 00000000000..f6a5ddade51 --- /dev/null +++ b/mysql-test/suite/binlog/r/binlog_killed_simulate.result @@ -0,0 +1,33 @@ +drop table if exists t1,t2; +create table t1 (a int) engine=MyISAM; +insert into t1 set a=1; +reset master; +update t1 set a=2 /* will be "killed" after work has been done */; +select +(@a:=load_file("MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog")) +is not null; +(@a:=load_file("MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog")) +is not null +1 +select 1 /* must return 1 as query completed before got killed*/; +1 +1 +create table t2 (a int, b int) ENGINE=MyISAM; +reset master; +load data infile '../std_data_ln/rpl_loaddata.dat' into table t2 /* will be "killed" in the middle */; +ERROR 70100: Query execution was interrupted +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Begin_load_query # # ;file_id=1;block_len=12 +master-bin.000001 # Execute_load_query # # use `test`; load data infile '../std_data_ln/rpl_loaddata.dat' into table t2 /* will be "killed" in the middle */ ;file_id=1 +select +(@a:=load_file("MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog")) +is not null; +(@a:=load_file("MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog")) +is not null +1 +select 0 /* must return 0 to mean the killed query is in */; +0 +0 +drop table t1,t2; +end of the tests diff --git a/mysql-test/suite/binlog/r/binlog_row_mix_innodb_myisam.result b/mysql-test/suite/binlog/r/binlog_row_mix_innodb_myisam.result index 6ac942176c7..f69d5717a1f 100644 --- a/mysql-test/suite/binlog/r/binlog_row_mix_innodb_myisam.result +++ b/mysql-test/suite/binlog/r/binlog_row_mix_innodb_myisam.result @@ -413,3 +413,236 @@ select @a like "%#%error_code=0%ROLLBACK/*!*/;%ROLLBACK /* added by mysqlbinlog */;%" @a not like "%#%error_code=%error_code=%" 1 1 drop table t1, t2; +create temporary table tt (a int unique); +create table ti (a int) engine=innodb; +reset master; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 106 +begin; +insert into ti values (1); +insert into ti values (2) ; +insert into tt select * from ti; +rollback; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +select count(*) from tt /* 2 */; +count(*) +2 +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 395 +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; BEGIN +master-bin.000001 # Table_map # # table_id: # (test.ti) +master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map # # table_id: # (test.ti) +master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F +master-bin.000001 # Query # # use `test`; ROLLBACK +select count(*) from ti /* zero */; +count(*) +0 +insert into ti select * from tt; +select * from ti /* that is what slave would miss - bug#28960 */; +a +1 +2 +delete from ti; +delete from tt where a=1; +reset master; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 106 +begin; +insert into ti values (1); +insert into ti values (2) /* to make the dup error in the following */; +insert into tt select * from ti /* one affected and error */; +ERROR 23000: Duplicate entry '2' for key 'a' +rollback; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 106 +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +select count(*) from ti /* zero */; +count(*) +0 +insert into ti select * from tt; +select * from tt /* that is what otherwise slave missed - the bug */; +a +1 +2 +drop table ti; +drop function if exists bug27417; +drop table if exists t1,t2; +CREATE TABLE t1 (a int NOT NULL auto_increment primary key) ENGINE=MyISAM; +CREATE TABLE t2 (a int NOT NULL auto_increment, PRIMARY KEY (a)); +create function bug27417(n int) +RETURNS int(11) +begin +insert into t1 values (null); +return n; +end| +reset master; +insert into t2 values (bug27417(1)); +insert into t2 select bug27417(2); +reset master; +insert into t2 values (bug27417(2)); +ERROR 23000: Duplicate entry '2' for key 'PRIMARY' +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Intvar # # INSERT_ID=3 +master-bin.000001 # Query # # use `test`; insert into t2 values (bug27417(2)) +select count(*) from t1 /* must be 3 */; +count(*) +3 +reset master; +select count(*) from t2; +count(*) +2 +delete from t2 where a=bug27417(3); +select count(*) from t2 /* nothing got deleted */; +count(*) +2 +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Intvar # # INSERT_ID=4 +master-bin.000001 # Query # # use `test`; delete from t2 where a=bug27417(3) +select count(*) from t1 /* must be 5 */; +count(*) +5 +delete t2 from t2 where t2.a=bug27417(100) /* must not affect t2 */; +affected rows: 0 +select count(*) from t1 /* must be 7 */; +count(*) +7 +drop table t1,t2; +CREATE TABLE t1 (a int NOT NULL auto_increment primary key) ENGINE=MyISAM; +CREATE TABLE t2 (a int, PRIMARY KEY (a)) ENGINE=InnoDB; +CREATE TABLE t3 (a int, PRIMARY KEY (a), b int unique) ENGINE=MyISAM; +CREATE TABLE t4 (a int, PRIMARY KEY (a), b int unique) ENGINE=Innodb; +CREATE TABLE t5 (a int, PRIMARY KEY (a)) ENGINE=InnoDB; +insert into t2 values (1); +reset master; +insert into t2 values (bug27417(1)); +ERROR 23000: Duplicate entry '1' for key 'PRIMARY' +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Intvar # # INSERT_ID=1 +master-bin.000001 # Query # # use `test`; insert into t2 values (bug27417(1)) +master-bin.000001 # Query # # use `test`; ROLLBACK +select count(*) from t1 /* must be 1 */; +count(*) +1 +delete from t1; +delete from t2; +insert into t2 values (2); +reset master; +insert into t2 select bug27417(1) union select bug27417(2); +ERROR 23000: Duplicate entry '2' for key 'PRIMARY' +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Intvar # # INSERT_ID=2 +master-bin.000001 # Query # # use `test`; insert into t2 select bug27417(1) union select bug27417(2) +master-bin.000001 # Query # # use `test`; ROLLBACK +select count(*) from t1 /* must be 2 */; +count(*) +2 +delete from t1; +insert into t3 values (1,1),(2,3),(3,4); +reset master; +update t3 set b=b+bug27417(1); +ERROR 23000: Duplicate entry '4' for key 'b' +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Intvar # # INSERT_ID=4 +master-bin.000001 # Query # # use `test`; update t3 set b=b+bug27417(1) +select count(*) from t1 /* must be 2 */; +count(*) +2 +delete from t3; +delete from t4; +insert into t3 values (1,1); +insert into t4 values (1,1),(2,2); +reset master; +UPDATE t4,t3 SET t4.a=t3.a + bug27417(1) /* top level non-ta table */; +ERROR 23000: Duplicate entry '2' for key 'PRIMARY' +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Intvar # # INSERT_ID=6 +master-bin.000001 # Query # # use `test`; UPDATE t4,t3 SET t4.a=t3.a + bug27417(1) /* top level non-ta table */ +master-bin.000001 # Query # # use `test`; ROLLBACK +select count(*) from t1 /* must be 4 */; +count(*) +4 +delete from t1; +delete from t3; +delete from t4; +insert into t3 values (1,1),(2,2); +insert into t4 values (1,1),(2,2); +reset master; +UPDATE t3,t4 SET t3.a=t4.a + bug27417(1); +ERROR 23000: Duplicate entry '2' for key 'PRIMARY' +select count(*) from t1 /* must be 1 */; +count(*) +1 +drop table t4; +delete from t1; +delete from t2; +delete from t3; +insert into t2 values (1); +insert into t3 values (1,1); +create trigger trg_del before delete on t2 for each row +insert into t3 values (bug27417(1), 2); +reset master; +delete from t2; +ERROR 23000: Duplicate entry '1' for key 'PRIMARY' +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Intvar # # INSERT_ID=9 +master-bin.000001 # Query # # use `test`; delete from t2 +master-bin.000001 # Query # # use `test`; ROLLBACK +select count(*) from t1 /* must be 1 */; +count(*) +1 +drop trigger trg_del; +delete from t1; +delete from t2; +delete from t5; +create trigger trg_del_t2 after delete on t2 for each row +insert into t1 values (1); +insert into t2 values (2),(3); +insert into t5 values (1),(2); +reset master; +delete t2.* from t2,t5 where t2.a=t5.a + 1; +ERROR 23000: Duplicate entry '1' for key 'PRIMARY' +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; delete t2.* from t2,t5 where t2.a=t5.a + 1 +master-bin.000001 # Query # # use `test`; ROLLBACK +select count(*) from t1 /* must be 1 */; +count(*) +1 +delete from t1; +create table t4 (a int default 0, b int primary key) engine=innodb; +insert into t4 values (0, 17); +reset master; +load data infile '../std_data_ln/rpl_loaddata.dat' into table t4 (a, @b) set b= @b + bug27417(2); +ERROR 23000: Duplicate entry '17' for key 'PRIMARY' +select * from t4; +a b +0 17 +select count(*) from t1 /* must be 2 */; +count(*) +2 +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Intvar # # INSERT_ID=10 +master-bin.000001 # Begin_load_query # # ;file_id=1;block_len=12 +master-bin.000001 # Intvar # # INSERT_ID=10 +master-bin.000001 # Execute_load_query # # use `test`; load data infile '../std_data_ln/rpl_loaddata.dat' into table t4 (a, @b) set b= @b + bug27417(2) ;file_id=1 +master-bin.000001 # Query # # use `test`; ROLLBACK +drop trigger trg_del_t2; +drop table t1,t2,t3,t4,t5; +drop function bug27417; diff --git a/mysql-test/suite/binlog/r/binlog_stm_blackhole.result b/mysql-test/suite/binlog/r/binlog_stm_blackhole.result index a1c83ffc73d..a79642a9204 100644 --- a/mysql-test/suite/binlog/r/binlog_stm_blackhole.result +++ b/mysql-test/suite/binlog/r/binlog_stm_blackhole.result @@ -124,6 +124,7 @@ master-bin.000001 # Query # # use `test`; replace into t1 select * from t3 drop table t1,t2,t3; CREATE TABLE t1(a INT) ENGINE=BLACKHOLE; INSERT DELAYED INTO t1 VALUES(1); +ERROR HY000: Binary logging not possible. Message: Row-based format required for this statement, but not allowed by this combination of engines DROP TABLE t1; CREATE TABLE t1(a INT, b INT) ENGINE=BLACKHOLE; DELETE FROM t1 WHERE a=10; diff --git a/mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result b/mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result index 5ef36861c30..c15478bc826 100644 --- a/mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result +++ b/mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result @@ -380,7 +380,8 @@ select @a like "%#%error_code=0%ROLLBACK/*!*/;%ROLLBACK /* added by mysqlbinlog */;%" @a not like "%#%error_code=%error_code=%" 1 1 drop table t1, t2; -create table tt (a int unique); +set @@session.binlog_format=statement; +create temporary table tt (a int unique); create table ti (a int) engine=innodb; reset master; show master status; @@ -399,18 +400,18 @@ count(*) show master status; File Position Binlog_Do_DB Binlog_Ignore_DB master-bin.000001 515 -show binlog events from 106; +show binlog events from ; Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 # Query 1 # use `test`; BEGIN -master-bin.000001 # Query 1 # use `test`; insert into ti values (1) -master-bin.000001 # Query 1 # use `test`; insert into ti values (2) -master-bin.000001 # Query 1 # use `test`; insert into tt select * from ti -master-bin.000001 # Query 1 # use `test`; ROLLBACK +master-bin.000001 # Query # # use `test`; BEGIN +master-bin.000001 # Query # # use `test`; insert into ti values (1) +master-bin.000001 # Query # # use `test`; insert into ti values (2) +master-bin.000001 # Query # # use `test`; insert into tt select * from ti +master-bin.000001 # Query # # use `test`; ROLLBACK select count(*) from ti /* zero */; count(*) 0 insert into ti select * from tt; -select * from ti /* that is what slave would miss - a bug */; +select * from ti /* that is what slave would miss - bug#28960 */; a 1 2 @@ -431,13 +432,13 @@ Warning 1196 Some non-transactional changed tables couldn't be rolled back show master status; File Position Binlog_Do_DB Binlog_Ignore_DB master-bin.000001 589 -show binlog events from 106; +show binlog events from ; Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 # Query 1 # use `test`; BEGIN -master-bin.000001 # Query 1 # use `test`; insert into ti values (1) -master-bin.000001 # Query 1 # use `test`; insert into ti values (2) /* to make the dup error in the following */ -master-bin.000001 # Query 1 # use `test`; insert into tt select * from ti /* one affected and error */ -master-bin.000001 # Query 1 # use `test`; ROLLBACK +master-bin.000001 # Query # # use `test`; BEGIN +master-bin.000001 # Query # # use `test`; insert into ti values (1) +master-bin.000001 # Query # # use `test`; insert into ti values (2) /* to make the dup error in the following */ +master-bin.000001 # Query # # use `test`; insert into tt select * from ti /* one affected and error */ +master-bin.000001 # Query # # use `test`; ROLLBACK select count(*) from ti /* zero */; count(*) 0 @@ -446,7 +447,7 @@ select * from tt /* that is what otherwise slave missed - the bug */; a 1 2 -drop table ti,tt; +drop table ti; drop function if exists bug27417; drop table if exists t1,t2; CREATE TABLE t1 (a int NOT NULL auto_increment primary key) ENGINE=MyISAM; @@ -463,6 +464,10 @@ insert into t2 select bug27417(2); reset master; insert into t2 values (bug27417(2)); ERROR 23000: Duplicate entry '2' for key 'PRIMARY' +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Intvar # # INSERT_ID=3 +master-bin.000001 # Query # # use `test`; insert into t2 values (bug27417(2)) select count(*) from t1 /* must be 3 */; count(*) 3 @@ -474,6 +479,10 @@ delete from t2 where a=bug27417(3); select count(*) from t2 /* nothing got deleted */; count(*) 2 +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Intvar # # INSERT_ID=4 +master-bin.000001 # Query # # use `test`; delete from t2 where a=bug27417(3) select count(*) from t1 /* must be 5 */; count(*) 5 @@ -482,6 +491,134 @@ affected rows: 0 select count(*) from t1 /* must be 7 */; count(*) 7 -drop function bug27417; drop table t1,t2; +CREATE TABLE t1 (a int NOT NULL auto_increment primary key) ENGINE=MyISAM; +CREATE TABLE t2 (a int, PRIMARY KEY (a)) ENGINE=InnoDB; +CREATE TABLE t3 (a int, PRIMARY KEY (a), b int unique) ENGINE=MyISAM; +CREATE TABLE t4 (a int, PRIMARY KEY (a), b int unique) ENGINE=Innodb; +CREATE TABLE t5 (a int, PRIMARY KEY (a)) ENGINE=InnoDB; +insert into t2 values (1); +reset master; +insert into t2 values (bug27417(1)); +ERROR 23000: Duplicate entry '1' for key 'PRIMARY' +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Intvar # # INSERT_ID=1 +master-bin.000001 # Query # # use `test`; insert into t2 values (bug27417(1)) +master-bin.000001 # Query # # use `test`; ROLLBACK +select count(*) from t1 /* must be 1 */; +count(*) +1 +delete from t1; +delete from t2; +insert into t2 values (2); +reset master; +insert into t2 select bug27417(1) union select bug27417(2); +ERROR 23000: Duplicate entry '2' for key 'PRIMARY' +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Intvar # # INSERT_ID=2 +master-bin.000001 # Query # # use `test`; insert into t2 select bug27417(1) union select bug27417(2) +master-bin.000001 # Query # # use `test`; ROLLBACK +select count(*) from t1 /* must be 2 */; +count(*) +2 +delete from t1; +insert into t3 values (1,1),(2,3),(3,4); +reset master; +update t3 set b=b+bug27417(1); +ERROR 23000: Duplicate entry '4' for key 'b' +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Intvar # # INSERT_ID=4 +master-bin.000001 # Query # # use `test`; update t3 set b=b+bug27417(1) +select count(*) from t1 /* must be 2 */; +count(*) +2 +delete from t3; +delete from t4; +insert into t3 values (1,1); +insert into t4 values (1,1),(2,2); +reset master; +UPDATE t4,t3 SET t4.a=t3.a + bug27417(1) /* top level non-ta table */; +ERROR 23000: Duplicate entry '2' for key 'PRIMARY' +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Intvar # # INSERT_ID=6 +master-bin.000001 # Query # # use `test`; UPDATE t4,t3 SET t4.a=t3.a + bug27417(1) /* top level non-ta table */ +master-bin.000001 # Query # # use `test`; ROLLBACK +select count(*) from t1 /* must be 4 */; +count(*) +4 +delete from t1; +delete from t3; +delete from t4; +insert into t3 values (1,1),(2,2); +insert into t4 values (1,1),(2,2); +reset master; +UPDATE t3,t4 SET t3.a=t4.a + bug27417(1); +ERROR 23000: Duplicate entry '2' for key 'PRIMARY' +select count(*) from t1 /* must be 1 */; +count(*) +1 +drop table t4; +delete from t1; +delete from t2; +delete from t3; +insert into t2 values (1); +insert into t3 values (1,1); +create trigger trg_del before delete on t2 for each row +insert into t3 values (bug27417(1), 2); +reset master; +delete from t2; +ERROR 23000: Duplicate entry '1' for key 'PRIMARY' +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Intvar # # INSERT_ID=9 +master-bin.000001 # Query # # use `test`; delete from t2 +master-bin.000001 # Query # # use `test`; ROLLBACK +select count(*) from t1 /* must be 1 */; +count(*) +1 +drop trigger trg_del; +delete from t1; +delete from t2; +delete from t5; +create trigger trg_del_t2 after delete on t2 for each row +insert into t1 values (1); +insert into t2 values (2),(3); +insert into t5 values (1),(2); +reset master; +delete t2.* from t2,t5 where t2.a=t5.a + 1; +ERROR 23000: Duplicate entry '1' for key 'PRIMARY' +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; delete t2.* from t2,t5 where t2.a=t5.a + 1 +master-bin.000001 # Query # # use `test`; ROLLBACK +select count(*) from t1 /* must be 1 */; +count(*) +1 +delete from t1; +create table t4 (a int default 0, b int primary key) engine=innodb; +insert into t4 values (0, 17); +reset master; +load data infile '../std_data_ln/rpl_loaddata.dat' into table t4 (a, @b) set b= @b + bug27417(2); +ERROR 23000: Duplicate entry '17' for key 'PRIMARY' +select * from t4; +a b +0 17 +select count(*) from t1 /* must be 2 */; +count(*) +2 +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Intvar # # INSERT_ID=10 +master-bin.000001 # Begin_load_query # # ;file_id=1;block_len=12 +master-bin.000001 # Intvar # # INSERT_ID=10 +master-bin.000001 # Execute_load_query # # use `test`; load data infile '../std_data_ln/rpl_loaddata.dat' into table t4 (a, @b) set b= @b + bug27417(2) ;file_id=1 +master-bin.000001 # Query # # use `test`; ROLLBACK +drop trigger trg_del_t2; +drop table t1,t2,t3,t4,t5; +drop function bug27417; +set @@session.binlog_format=@@global.binlog_format; end of tests diff --git a/mysql-test/suite/binlog/t/binlog_database.test b/mysql-test/suite/binlog/t/binlog_database.test new file mode 100644 index 00000000000..ee236b4e5ea --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_database.test @@ -0,0 +1,12 @@ +# A wrapper to test that dropping a database is binlogged +# correctly. We test all three modes in the same file to avoid +# unecessary server restarts. + +set binlog_format=statement; +source extra/binlog_tests/database.test; +set binlog_format=mixed; +source extra/binlog_tests/database.test; +set binlog_format=row; +source extra/binlog_tests/database.test; + +show databases; diff --git a/mysql-test/suite/binlog/t/binlog_killed.test b/mysql-test/suite/binlog/t/binlog_killed.test index 6c0b4b46a4e..e5f7288b17c 100644 --- a/mysql-test/suite/binlog/t/binlog_killed.test +++ b/mysql-test/suite/binlog/t/binlog_killed.test @@ -55,194 +55,277 @@ enable_result_log; select @result /* must be zero either way */; -# the functions are either *insensitive* to killing or killing can cause -# strange problmes with the error propagation out of SF's stack -# Bug#27563, Bug#27565, BUG#24971 + +--remove_file $MYSQLTEST_VARDIR/tmp/kill_query_calling_sp.binlog +connection con1; +select RELEASE_LOCK("a"); + # -# TODO: use if's block as regression test for the bugs or remove +# bug#27571 asynchronous setting mysql_`query`::error and Query_log_e::error_code # -if (0) -{ + +# checking that killing inside of select loops is safe as before +# killing after the loop can be only simulated - another test + +delete from t1; +delete from t2; +insert into t1 values (1,1),(2,2); + +# +# simple update +# +connection con1; +begin; update t1 set b=11 where a=2; + +connection con2; +let $ID= `select connection_id()`; +begin; +send update t1 set b=b+10; + +connection con1; +--replace_result $ID ID +eval kill query $ID; +rollback; + +# Bug #32148 killi query may be ineffective +# forced to comment out the test's outcome +# and mask out ineffective ER_QUERY_INTERRUPTED +# todo1: revert back upon fixing bug#32148 +# todo2: the tests need refining in that +# killing should wait till the victim requested +# its lock (wait_condition available in 5.1 tests) + +connection con2; +--error 0,ER_QUERY_INTERRUPTED +reap; +rollback; +select * from t1 order by a /* must be the same as before (1,1),(2,2) */; + +# +# multi update +# commented out as Bug #31807 multi-update,delete killing does not report with ER_QUERY_INTERRUPTED +# in the way +# +# connection con1; +# begin; update t1 set b=b+10; + +# connection con2; +# send update t1 as t_1,t1 as t_2 set t_1.b=11 where t_2.a=2; + +# connection con1; +# --replace_result $ID ID +# eval kill query $ID; +# rollback; + +# disable_abort_on_error; + +# connection con2; +# --error HY000,ER_QUERY_INTERRUPTED +# reap; +# select * from t1 /* must be the same as before (1,1),(2,2) */; + +# enable_abort_on_error; +# +# simple delete +# +connection con1; +begin; delete from t1 where a=2; + +connection con2; +let $ID= `select connection_id()`; +begin; +send delete from t1 where a=2; + +connection con1; +--replace_result $ID ID +eval kill query $ID; +rollback; + +connection con2; +--error 0,ER_QUERY_INTERRUPTED +reap; +rollback; +# todo1,2 above +select * from t1 order by a /* must be the same as before (1,1),(2,2) */; + + +# +# multi delete +# the same as for multi-update +# +# connection con1; +# begin; delete from t1 where a=2; + +# connection con2; +# send delete t1 from t1 where t1.a=2; + +# connection con1; +# --replace_result $ID ID +# eval kill query $ID; +# rollback; + +# connection con2; +# --error 0,ER_QUERY_INTERRUPTED +# reap; +# select * from t1 /* must be the same as before (1,1),(2,2) */; +# +# insert select +# +connection con1; +--disable_warnings +drop table if exists t4; +--enable_warnings +create table t4 (a int, b int) engine=innodb; +insert into t4 values (3, 3); +begin; insert into t1 values (3, 3); + +connection con2; +let $ID= `select connection_id()`; +begin; +send insert into t1 select * from t4 for update; + +connection con1; +--replace_result $ID ID +eval kill query $ID; +rollback; + +connection con2; +--error 0,ER_QUERY_INTERRUPTED +reap; +# todo 1,2 above +rollback; +select * from t1 /* must be the same as before (1,1),(2,2) */; + +drop table t4; # cleanup for the sub-case + +### +## non-ta table case: killing must be recorded in binlog +### +create table t4 (a int, b int) ENGINE=MyISAM /* for killing update and delete */; + delimiter |; -create function bug27563() +create function bug27563(n int) RETURNS int(11) DETERMINISTIC begin - select get_lock("a", 10) into @a; - return 1; + if @b > 0 then + select get_lock("a", 20) into @a; + else + set @b= 1; + end if; + return n; end| delimiter ;| -# the function is sensitive to killing requiring innodb though with wrong client error -# TO FIX in BUG#27565; TODO: remove --error 1105 afterwards -delimiter |; -create function bug27565() -RETURNS int(11) -DETERMINISTIC -begin - select a from t1 where a=1 into @a for update; - return 1; -end| -delimiter ;| +# +# update +# +delete from t4; +insert into t4 values (1,1), (1,1); reset master; - - -### ta table case: killing causes rollback - -# A. autocommit ON connection con1; select get_lock("a", 20); connection con2; let $ID= `select connection_id()`; -send insert into t1 values (bug27563(),1); +set @b= 0; +send update t4 set b=b + bug27563(b); connection con1; +let $wait_condition= select count(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST where state='User lock'; +source include/wait_condition.inc; +select count(*) FROM INFORMATION_SCHEMA.PROCESSLIST where state='User lock'; + +--replace_result $ID ID eval kill query $ID; connection con2; -# todo (re-record test): after bugs 27563,27565 got fixed affected rows will report zero ---enable_info -# todo: remove 0 return after fixing Bug#27563 ---error 0,ER_QUERY_INTERRUPTED -reap; ### pb: wrong error ---disable_info -###--replace_column 2 # 5 # -### show binlog events from 98 /* nothing in binlog unless Bug#27563 */; -show master status /* must be only FD event unless Bug#27563 */; -select count(*) from t1 /* must be zero unless Bug#27563 */; - -# M. multi-statement-ta -connection con2; -let $ID= `select connection_id()`; -begin; -send insert into t1 values (bug27563(),1); - -connection con1; -eval kill query $ID; -connection con2; -# todo (re-record test): after bugs 27563,27565 got fixed affected rows will report zero ---enable_info -# todo: remove 0 return after fixing Bug#27563 ---error 0,ER_QUERY_INTERRUPTED +--error ER_QUERY_INTERRUPTED reap; ---disable_info -select count(*) from t1 /* must be zero unless Bug#27563 */; -commit; +select * from t4 order by b /* must be (1,1), (1,2) */; +select @b /* must be 1 at the end of a stmt calling bug27563() */; +--echo must have the update query event more to FD +source include/show_binlog_events.inc; +# a proof the query is binlogged with an error -### non-ta table case: killing must be recorded in binlog - -reset master; - -connection con2; -let $ID= `select connection_id()`; -send insert into t2 values (bug27563(),1); - -connection con1; -eval kill query $ID; - -connection con2; -# todo: remove 0 return after fixing Bug#27563 ---error 0,ER_QUERY_INTERRUPTED -reap; -select count(*) from t2 /* must be one */; -#show binlog events from 98 /* must have the insert on non-ta table */; -show master status /* must have the insert event more to FD */; -# the value of the error flag of KILLED_QUERY is tested further +--exec $MYSQL_BINLOG --start-position=106 $MYSQLTEST_VARDIR/log/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +eval select +(@a:=load_file("$MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog")) +is not null; +--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR +let $error_code= `select @a like "%#%error_code=0%" /* must return 0*/`; +eval select $error_code /* must return 0 to mean the killed query is in */; +# cleanup for the sub-case connection con1; select RELEASE_LOCK("a"); +--remove_file $MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog -### test with effective killing of SF() - -delete from t1; -delete from t2; -insert into t1 values (1,1); -insert into t2 values (1,1); - -# -# Bug#27565 -# test where KILL is propagated as error to the top level -# still another bug with the error message to the user -# todo: fix reexecute the result file after fixing -# -begin; update t1 set b=0 where a=1; - -connection con2; -let $ID= `select connection_id()`; -send update t2 set b=bug27565()-1 where a=1; - -connection con1; -eval kill query $ID; -commit; - -connection con2; -# todo: fix Bug #27565 killed query of SF() is not reported correctly and -# remove 1105 (wrong) -#--error ER_QUERY_INTERRUPTED ---error 1105,ER_QUERY_INTERRUPTED -reap; ### pb: wrong error -select * from t1 /* must be: (1,0) */; -select * from t2 /* must be as before: (1,1) */; - -## bug#22725 with effective and propagating killing # -# top-level ta-table -connection con1; -delete from t3; +# delete +# + +delete from t4; +insert into t4 values (1,1), (2,2); reset master; -begin; update t1 set b=0 where a=1; +connection con1; +select get_lock("a", 20); connection con2; let $ID= `select connection_id()`; -# the query won't perform completely since the function gets interrupted -send insert into t3 values (0,0),(1,bug27565()); +set @b= 0; +send delete from t4 where b=bug27563(1) or b=bug27563(2); connection con1; +let $wait_condition= select count(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST where state='User lock'; +source include/wait_condition.inc; +select count(*) FROM INFORMATION_SCHEMA.PROCESSLIST where state='User lock'; +--replace_result $ID ID eval kill query $ID; -rollback; connection con2; -# todo: fix Bug #27565 killed query of SF() is not reported correctly and -# remove 1105 (wrong) -#--error ER_QUERY_INTERRUPTED ---error 1105,ER_QUERY_INTERRUPTED -reap; ### pb: wrong error -select count(*) from t3 /* must be zero */; -show master status /* nothing in binlog */; +--error ER_QUERY_INTERRUPTED +reap; +select count(*) from t4 /* must be 1 */; +select @b /* must be 1 at the end of a stmt calling bug27563() */; +--echo must have the delete query event more to FD +source include/show_binlog_events.inc; -# top-level non-ta-table +# a proof the query is binlogged with an error + +--exec $MYSQL_BINLOG --start-position=106 $MYSQLTEST_VARDIR/log/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +eval select +(@a:=load_file("$MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog")) +is not null; +--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR +let $error_code= `select @a like "%#%error_code=0%" /* must return 0*/`; +eval select $error_code /* must return 0 to mean the killed query is in */; + +# cleanup for the sub-case connection con1; -delete from t2; -reset master; -begin; update t1 set b=0 where a=1; +select RELEASE_LOCK("a"); +--remove_file $MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog -connection con2; -let $ID= `select connection_id()`; -# the query won't perform completely since the function gets intrurrupted -send insert into t2 values (0,0),(1,bug27565()) /* non-ta t2 */; +drop table t4; -connection con1; -eval kill query $ID; -rollback; +# +# load data - see simulation tests +# -connection con2; -# todo: fix Bug #27565 killed query of SF() is not reported correctly and -# remove 1105 (wrong) -#--error ER_QUERY_INTERRUPTED ---error 1105,ER_QUERY_INTERRUPTED -reap; ### pb: wrong error -select count(*) from t2 /* count must be one */; -show master status /* insert into non-ta must be in binlog */; +# bug#27571 cleanup drop function bug27563; -drop function bug27565; -} -system rm $MYSQLTEST_VARDIR/tmp/kill_query_calling_sp.binlog ; + +# +# common cleanup +# drop table t1,t2,t3; +--echo end of the tests diff --git a/mysql-test/suite/binlog/t/binlog_killed_simulate-master.opt b/mysql-test/suite/binlog/t/binlog_killed_simulate-master.opt new file mode 100644 index 00000000000..90c70ecee29 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_killed_simulate-master.opt @@ -0,0 +1 @@ +--loose-debug=d,simulate_kill_bug27571 diff --git a/mysql-test/suite/binlog/t/binlog_killed_simulate.test b/mysql-test/suite/binlog/t/binlog_killed_simulate.test new file mode 100644 index 00000000000..2121a90dc8c --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_killed_simulate.test @@ -0,0 +1,69 @@ +-- source include/have_debug.inc +-- source include/have_binlog_format_mixed_or_statement.inc +# +# bug#27571 asynchronous setting mysql_$query()'s local error and +# Query_log_event::error_code +# + +--disable_warnings +drop table if exists t1,t2; +--enable_warnings + +# +# Checking that killing upon successful row-loop does not affect binlogging +# + +create table t1 (a int) engine=MyISAM; +insert into t1 set a=1; +reset master; + +update t1 set a=2 /* will be "killed" after work has been done */; + +# a proof the query is binlogged with no error +#todo: introduce a suite private macro that provides numeric values +# for some constants like the offset of the first real event +# that is different between severs versions. +--exec $MYSQL_BINLOG --start-position=106 $MYSQLTEST_VARDIR/log/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +eval select +(@a:=load_file("$MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog")) +is not null; +--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR +let $error_code= `select @a like "%#%error_code=0%" /* must return 1 */`; +eval select $error_code /* must return 1 as query completed before got killed*/; + +# cleanup for the sub-case +system rm $MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog; + + +# +# Checking that killing inside of row-loop for LOAD DATA into +# non-transactional table affects binlogging +# + +create table t2 (a int, b int) ENGINE=MyISAM; +reset master; +--error ER_QUERY_INTERRUPTED +load data infile '../std_data_ln/rpl_loaddata.dat' into table t2 /* will be "killed" in the middle */; + + +# a proof the query is binlogged with an error + +source include/show_binlog_events.inc; + +--exec $MYSQL_BINLOG --start-position=98 $MYSQLTEST_VARDIR/log/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +eval select +(@a:=load_file("$MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog")) +is not null; +--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR +let $error_code= `select @a like "%#%error_code=0%" /* must return 0*/`; +eval select $error_code /* must return 0 to mean the killed query is in */; + +# cleanup for the sub-case +system rm $MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog; + + +drop table t1,t2; + +--echo end of the tests diff --git a/mysql-test/suite/binlog/t/binlog_row_mix_innodb_myisam.test b/mysql-test/suite/binlog/t/binlog_row_mix_innodb_myisam.test index 7b7753a487e..3148cc50fd0 100644 --- a/mysql-test/suite/binlog/t/binlog_row_mix_innodb_myisam.test +++ b/mysql-test/suite/binlog/t/binlog_row_mix_innodb_myisam.test @@ -31,3 +31,5 @@ eval select @a like "%#%error_code=0%ROLLBACK/*!*/;%ROLLBACK /* added by mysqlbinlog */;%", @a not like "%#%error_code=%error_code=%"; drop table t1, t2; + +-- source extra/binlog_tests/mix_innodb_myisam_side_effects.test diff --git a/mysql-test/suite/binlog/t/binlog_stm_mix_innodb_myisam.test b/mysql-test/suite/binlog/t/binlog_stm_mix_innodb_myisam.test index 1815f3deb34..e7149e03b87 100644 --- a/mysql-test/suite/binlog/t/binlog_stm_mix_innodb_myisam.test +++ b/mysql-test/suite/binlog/t/binlog_stm_mix_innodb_myisam.test @@ -24,123 +24,9 @@ eval select drop table t1, t2; -# -# Bug #27417 thd->no_trans_update.stmt lost value inside of SF-exec-stack -# bug #28960 non-trans temp table changes with insert .. select -# not binlogged after rollback -# -# testing appearence of insert into temp_table in binlog. -# There are two branches of execution that require different setup. +set @@session.binlog_format=statement; +-- source extra/binlog_tests/mix_innodb_myisam_side_effects.test +set @@session.binlog_format=@@global.binlog_format; -## send_eof() branch - -# prepare - -create table tt (a int unique); -create table ti (a int) engine=innodb; -reset master; -show master status; - -# action - -begin; -insert into ti values (1); -insert into ti values (2) ; -insert into tt select * from ti; -rollback; - -# check - -select count(*) from tt /* 2 */; -show master status; ---replace_column 2 # 5 # -show binlog events from 106; -select count(*) from ti /* zero */; -insert into ti select * from tt; -select * from ti /* that is what slave would miss - a bug */; - - -## send_error() branch -delete from ti; -delete from tt where a=1; -reset master; -show master status; - -# action - -begin; -insert into ti values (1); -insert into ti values (2) /* to make the dup error in the following */; ---error ER_DUP_ENTRY -insert into tt select * from ti /* one affected and error */; -rollback; - -# check - -show master status; ---replace_column 2 # 5 # -show binlog events from 106; -select count(*) from ti /* zero */; -insert into ti select * from tt; -select * from tt /* that is what otherwise slave missed - the bug */; - -drop table ti,tt; - - -# -# Bug #27417 thd->no_trans_update.stmt lost value inside of SF-exec-stack -# -# Testing asserts: if there is a side effect of modifying non-transactional -# table thd->no_trans_update.stmt must be TRUE; -# the assert is active with debug build -# - ---disable_warnings -drop function if exists bug27417; -drop table if exists t1,t2; ---enable_warnings -# side effect table -CREATE TABLE t1 (a int NOT NULL auto_increment primary key) ENGINE=MyISAM; -# target tables -CREATE TABLE t2 (a int NOT NULL auto_increment, PRIMARY KEY (a)); - -delimiter |; -create function bug27417(n int) -RETURNS int(11) -begin - insert into t1 values (null); - return n; -end| -delimiter ;| - -reset master; - -# execute - -insert into t2 values (bug27417(1)); -insert into t2 select bug27417(2); -reset master; - ---error ER_DUP_ENTRY -insert into t2 values (bug27417(2)); -#TODO: Andrei: enable this test after 23333 is pushed -#show master status; /* only (!) with fixes for #23333 will show there is the query */; -select count(*) from t1 /* must be 3 */; - -reset master; -select count(*) from t2; -delete from t2 where a=bug27417(3); -select count(*) from t2 /* nothing got deleted */; -#TODO: Andrei: enable this test after 23333 is pushed -#show master status; /* the query must be in regardless of #23333 */; -select count(*) from t1 /* must be 5 */; - ---enable_info -delete t2 from t2 where t2.a=bug27417(100) /* must not affect t2 */; ---disable_info -select count(*) from t1 /* must be 7 */; - -drop function bug27417; -drop table t1,t2; --echo end of tests diff --git a/mysql-test/suite/binlog/t/disabled.def b/mysql-test/suite/binlog/t/disabled.def index 888298bbb09..a6e73fa31d8 100644 --- a/mysql-test/suite/binlog/t/disabled.def +++ b/mysql-test/suite/binlog/t/disabled.def @@ -9,3 +9,4 @@ # Do not use any TAB characters for whitespace. # ############################################################################## +binlog_multi_engine : Bug#32663 binlog_multi_engine.test fails randomly diff --git a/mysql-test/suite/funcs_1/datadict/datadict_master.inc b/mysql-test/suite/funcs_1/datadict/datadict_master.inc index ee94f7cb318..73a23d6d377 100644 --- a/mysql-test/suite/funcs_1/datadict/datadict_master.inc +++ b/mysql-test/suite/funcs_1/datadict/datadict_master.inc @@ -199,7 +199,7 @@ select s.catalog_name, s.schema_name, s.default_character_set_name, --source suite/funcs_1/datadict/datadict_bug_12777.inc select * from columns; select * from character_sets; -select sum(id) from collations; +select sum(id) from collations where collation_name <> 'utf8_general_cs'; select collation_name, character_set_name into @x,@y from collation_character_set_applicability limit 1; select @x, @y; @@ -1660,13 +1660,14 @@ connect (u_6_401017, localhost, u_6_401017, , test); use information_schema; -select * from collation_character_set_applicability; +select * from collation_character_set_applicability +where collation_name <> 'utf8_general_cs'; select * from schemata; select table_name from tables; --source suite/funcs_1/datadict/datadict_bug_12777.inc select table_name, column_name, column_type from columns; select character_set_name from character_sets; -select collation_name from collations; +select collation_name from collations where collation_name <> 'utf8_general_cs'; select routine_name, routine_type from routines; select table_name, index_name from statistics; select table_name from views; @@ -1926,7 +1927,7 @@ let $message= Testcase 3.2.3.2:; # the USAGE privilege. ################################################################################ -SELECT * FROM collations; +SELECT * FROM collations where collation_name <> 'utf8_general_cs'; # ------------------------------------------------------------------------------------------------------- let $message= Testcase 3.2.3.3:; @@ -1973,7 +1974,8 @@ let $message= Testcase 3.2.4.2:; # and update with expected results afterwards. ################################################################################ -SELECT * FROM collation_character_set_applicability; +SELECT * FROM collation_character_set_applicability +where collation_name <> 'utf8_general_cs'; # ------------------------------------------------------------------------------------------------------- let $message= Testcase 3.2.4.3:; diff --git a/mysql-test/suite/funcs_1/datadict/datadict_show_schema.inc b/mysql-test/suite/funcs_1/datadict/datadict_show_schema.inc index 260119f030f..35060cefbf8 100644 --- a/mysql-test/suite/funcs_1/datadict/datadict_show_schema.inc +++ b/mysql-test/suite/funcs_1/datadict/datadict_show_schema.inc @@ -35,8 +35,9 @@ eval select table_name, index_schema, index_name, index_type where table_schema like '$dbname%'; --replace_result $SERVER_NAME +--sorted_result eval select * - from information_schema.user_privileges order by grantee, privilege_type; + from information_schema.user_privileges; # where grantee="'u_6_401013'@'%'"; eval select * diff --git a/mysql-test/suite/funcs_1/datadict/datadict_tables.inc b/mysql-test/suite/funcs_1/datadict/datadict_tables.inc index 14e39c083b0..9712f0a9c1c 100644 --- a/mysql-test/suite/funcs_1/datadict/datadict_tables.inc +++ b/mysql-test/suite/funcs_1/datadict/datadict_tables.inc @@ -28,8 +28,8 @@ eval $dd_part1 tables $dd_part2; --source suite/funcs_1/datadict/datadict_bug_12777.inc eval $dd_part1 columns $dd_part2; eval $dd_part1 character_sets $dd_part2; -eval $dd_part1 collations $dd_part2; -eval $dd_part1 collation_character_set_applicability $dd_part2; +eval $dd_part1 collations where collation_name <> 'utf8_general_cs' $dd_part2; +eval $dd_part1 collation_character_set_applicability where collation_name <> 'utf8_general_cs' $dd_part2; --replace_column 16 17 eval $dd_part1 routines $dd_part2; eval $dd_part1 statistics $dd_part2; diff --git a/mysql-test/suite/funcs_1/datadict/processlist_val.inc b/mysql-test/suite/funcs_1/datadict/processlist_val.inc index da2c2950095..62e5d95f875 100644 --- a/mysql-test/suite/funcs_1/datadict/processlist_val.inc +++ b/mysql-test/suite/funcs_1/datadict/processlist_val.inc @@ -94,14 +94,25 @@ connect (ddicttestuser1,localhost,ddicttestuser1,ddictpass,information_schema); --echo ----- switch to connection default (user = root) ----- connection default; # - We have now a second connection. -# - important values in second connection +# First working phase for this connection is "Connect". +# This is a very short phase and the likelihood to meet it is +# - nearly zero on average boxes with low parallel load +# - around some percent on weak or overloaded boxes +# (Bug#32153 Status output differs - scheduling ?) +# Therefore we poll till we reach the long lasting phase with: # - USER = ddicttestuser1 # - HOST = 'localhost' # - DB = 'information_schema' # - Command = 'Sleep' -# - TIME = 0, I hope the testing machines are all time fast enough +# - TIME >= 0 Overloaded boxes can cause that we do not hit TIME = 0. # - State IS NULL # - INFO must be empty +# +let $wait_condition= SELECT COUNT(*) FROM INFORMATION_SCHEMA.PROCESSLIST + WHERE COMMAND = 'Sleep' AND TIME > 0; +--source include/wait_condition.inc +# +# Expect to hit TIME = 1. --replace_column 1 SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST; # Change the SQL command (affects content of INFO) @@ -109,25 +120,19 @@ SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST; SHOW FULL PROCESSLIST; # --echo # Sleep some time -# The value of TIME must increase after some sleeps. -# So poll till TIME changes. -let $run= 10; -while ($run) -{ - dec $run; - if (`SELECT COUNT(*) FROM INFORMATION_SCHEMA.PROCESSLIST - WHERE ID = @my_proclist_id + 1 AND TIME > 0`) - { - let $run= 0; - } - --real_sleep 0.2 -} -# Either we have now reached TIME = 1 or we fail with unexpected result. -# Expect to see now TIME = 1 +# The value of TIME must increase and reach 2 after some sleeps. +let $wait_timeout= 2; +let $wait_condition= SELECT COUNT(*) FROM INFORMATION_SCHEMA.PROCESSLIST + WHERE TIME > 1; +--source include/wait_condition.inc +# +# Expect to hit TIME = 2. --replace_column 1 SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST; --replace_column 1 SHOW FULL PROCESSLIST; +# +# # The second connection must have an ID = my ID + 1; SELECT ID = @my_proclist_id + 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'ddicttestuser1'; @@ -150,6 +155,12 @@ SHOW FULL PROCESSLIST; --echo --echo ----- establish connection con2 (user = ddicttestuser1) ------ connect (con2,localhost,ddicttestuser1,ddictpass,information_schema); +# +# If the testing box is under heavy load we might see connection ddicttestuser1 +# within the short phase INFO = 'SHOW FULL PROCESSLIST' and STATE = 'Writing to net'. +let $wait_condition= SELECT COUNT(*) FROM INFORMATION_SCHEMA.PROCESSLIST + WHERE COMMAND = 'Sleep'; +--source include/wait_condition.inc --replace_column 1 6