diff options
author | unknown <cmiller@zippy.cornsilk.net> | 2007-12-14 13:42:09 -0500 |
---|---|---|
committer | unknown <cmiller@zippy.cornsilk.net> | 2007-12-14 13:42:09 -0500 |
commit | 7fd0ad21a77e64d2ff6351f532962a247674833b (patch) | |
tree | 7f9d91b59c01dc2a804c5498341858c5b29423e3 /client | |
parent | 72d97dfdaed719b3b7ffd8a65f0c9096a479d7b5 (diff) | |
parent | 18f5e87ed930aa66fd7c8ea2b36c9cfc103d8a40 (diff) | |
download | mariadb-git-7fd0ad21a77e64d2ff6351f532962a247674833b.tar.gz |
Merge zippy.cornsilk.net:/home/cmiller/work/mysql/mysql-5.1-forcollapseandmerge
into zippy.cornsilk.net:/home/cmiller/work/mysql/mysql-5.1-maint
CMakeLists.txt:
Auto merged
configure.in:
Auto merged
libmysql/CMakeLists.txt:
Auto merged
libmysqld/lib_sql.cc:
Auto merged
mysql-test/r/information_schema_db.result:
Auto merged
mysql-test/t/information_schema.test:
Auto merged
sql/CMakeLists.txt:
Auto merged
sql/ha_ndbcluster.cc:
Auto merged
sql/item_cmpfunc.cc:
Auto merged
sql/item_func.cc:
Auto merged
sql/lock.cc:
Auto merged
sql/log_event.cc:
Auto merged
sql/mysql_priv.h:
Auto merged
sql/mysqld.cc:
Auto merged
sql/repl_failsafe.cc:
Auto merged
sql/set_var.cc:
Auto merged
sql/set_var.h:
Auto merged
sql/sp_head.cc:
Auto merged
sql/sql_cache.cc:
Auto merged
sql/sql_class.cc:
Auto merged
sql/sql_class.h:
Auto merged
sql/sql_insert.cc:
Auto merged
sql/sql_lex.cc:
Auto merged
sql/sql_lex.h:
Auto merged
sql/sql_prepare.cc:
Auto merged
sql/sql_repl.cc:
Auto merged
sql/sql_select.cc:
Auto merged
sql/sql_show.cc:
Auto merged
sql/sql_table.cc:
Auto merged
sql/sql_view.cc:
Auto merged
sql/sql_yacc.yy:
Auto merged
sql/structs.h:
Auto merged
sql/table.h:
Auto merged
storage/archive/ha_archive.cc:
Auto merged
storage/myisam/ha_myisam.cc:
Auto merged
storage/myisam/mi_open.c:
Auto merged
storage/myisammrg/ha_myisammrg.cc:
Auto merged
support-files/mysql.spec.sh:
Auto merged
client/mysqlcheck.c:
Manual merge.
mysql-test/r/information_schema.result:
Manual merge.
mysql-test/r/mysqlcheck.result:
Manual merge.
mysql-test/t/mysqlcheck.test:
Manual merge.
sql/slave.cc:
Manual merge.
sql/sql_base.cc:
Manual merge.
sql/sql_delete.cc:
Manual merge.
sql/sql_parse.cc:
Manual merge.
sql/sql_update.cc:
Manual merge.
Diffstat (limited to 'client')
-rw-r--r-- | client/mysql.cc | 236 | ||||
-rw-r--r-- | client/mysqlcheck.c | 55 | ||||
-rw-r--r-- | client/mysqldump.c | 12 | ||||
-rw-r--r-- | client/mysqltest.c | 2 |
4 files changed, 218 insertions, 87 deletions
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, (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, (uint) (out - line)); // Add this 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 char *fix_table_name(char *dest, char *src) +static uint fixed_name_length(const char *name) { - char *db_sep; + 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) +{ *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 <octal> <file_name> + chmod <octal> <file_name> Change file permission of <file_name> */ |