diff options
174 files changed, 3606 insertions, 9559 deletions
diff --git a/.bzrignore b/.bzrignore index 0e071d1343e..0ed7e966dcc 100644 --- a/.bzrignore +++ b/.bzrignore @@ -742,6 +742,7 @@ ndb/tools/ndb_drop_table ndb/tools/ndb_select_all ndb/tools/ndb_select_count ndb/tools/ndb_show_tables +ndb/tools/ndb_test_platform ndb/tools/ndb_waiter pull.log regex/re diff --git a/acinclude.m4 b/acinclude.m4 index 671e279a9f3..448bf7a2653 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -1614,9 +1614,14 @@ AC_DEFUN([MYSQL_CHECK_NDB_OPTIONS], [ --with-ndb-docs Include the NDB Cluster ndbapi and mgmapi documentation], [ndb_docs="$withval"], [ndb_docs=no]) + AC_ARG_WITH([ndb-port], + [ + --with-ndb-port Port for NDB Cluster management server], + [ndb_port="$withval"], + [ndb_port="default"]) AC_ARG_WITH([ndb-port-base], [ - --with-ndb-port-base Base port for NDB Cluster], + --with-ndb-port-base Base port for NDB Cluster transporters], [ndb_port_base="$withval"], [ndb_port_base="default"]) diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index 31588d5b013..8015871428e 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -14,28 +14,11 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* - - TODO: print the catalog (some USE catalog.db ????). - - Standalone program to read a MySQL binary log (or relay log); - can read files produced by 3.23, 4.x, 5.0 servers. - - Can read binlogs from 3.23/4.x/5.0 and relay logs from 4.x/5.0. - Should be able to read any file of these categories, even with - --start-position. - An important fact: the Format_desc event of the log is at most the 3rd event - of the log; if it is the 3rd then there is this combination: - Format_desc_of_slave, Rotate_of_master, Format_desc_of_master. -*/ - #define MYSQL_CLIENT #undef MYSQL_SERVER #include "client_priv.h" #include <my_time.h> #include "log_event.h" -/* That one is necessary for defines of OPTION_NO_FOREIGN_KEY_CHECKS etc */ -#include "mysql_priv.h" #define BIN_LOG_HEADER_SIZE 4 #define PROBE_HEADER_LEN (EVENT_LEN_OFFSET+4) @@ -83,14 +66,6 @@ static MYSQL* mysql = NULL; static const char* dirname_for_local_load= 0; static bool stop_passed= 0; -/* - check_header() will set the pointer below. - Why do we need here a pointer on an event instead of an event ? - This is because the event will be created (alloced) in read_log_event() - (which returns a pointer) in check_header(). -*/ -Format_description_log_event* description_event; - static int dump_local_log_entries(const char* logname); static int dump_remote_log_entries(const char* logname); static int dump_log_entries(const char* logname); @@ -229,7 +204,7 @@ int Load_log_processor::load_old_format_file(NET* net, const char*server_fname, for (;;) { - uint packet_len = my_net_read(net); + ulong packet_len = my_net_read(net); if (packet_len == 0) { if (my_net_write(net, "", 0) || net_flush(net)) @@ -251,7 +226,13 @@ int Load_log_processor::load_old_format_file(NET* net, const char*server_fname, return -1; } - if (my_write(file, (byte*) net->read_pos, packet_len,MYF(MY_WME|MY_NABP))) + if (packet_len > UINT_MAX) + { + sql_print_error("Illegal length of packet read from net"); + return -1; + } + if (my_write(file, (byte*) net->read_pos, + (uint) packet_len, MYF(MY_WME|MY_NABP))) return -1; } @@ -324,8 +305,8 @@ int Load_log_processor::process(Append_block_log_event *ae) /* There is no Create_file event (a bad binlog or a big - --start-position). Assuming it's a big --start-position, we just do - nothing and print a warning. + --position). Assuming it's a big --position, we just do nothing and + print a warning. */ fprintf(stderr,"Warning: ignoring Append_block as there is no \ Create_file event for file_id: %u\n",ae->file_id); @@ -335,49 +316,30 @@ Create_file event for file_id: %u\n",ae->file_id); Load_log_processor load_processor; - /* - Process an event - - SYNOPSIS - process_event() - RETURN 0 ok and continue 1 error and terminate -1 ok and terminate - + TODO This function returns 0 even in some error cases. This should be changed. */ - - - -int process_event(LAST_EVENT_INFO *last_event_info, Log_event *ev, - my_off_t pos) +int process_event(char *last_db, Log_event *ev, my_off_t pos, int old_format) { char ll_buff[21]; - Log_event_type ev_type= ev->get_type_code(); DBUG_ENTER("process_event"); - /* - Format events are not concerned by --offset and such, we always need to - read them to be able to process the wanted events. - */ if ((rec_count >= offset) && - ((my_time_t)(ev->when) >= start_datetime) || - (ev_type == FORMAT_DESCRIPTION_EVENT)) + ((my_time_t)(ev->when) >= start_datetime)) { - if (ev_type != FORMAT_DESCRIPTION_EVENT) - { - /* - We have found an event after start_datetime, from now on print - everything (in case the binlog has timestamps increasing and - decreasing, we do this to avoid cutting the middle). - */ - start_datetime= 0; - offset= 0; // print everything and protect against cycling rec_count - } + /* + We have found an event after start_datetime, from now on print + everything (in case the binlog has timestamps increasing and decreasing, + we do this to avoid cutting the middle). + */ + start_datetime= 0; + offset= 0; // print everything and protect against cycling rec_count if (((my_time_t)(ev->when) >= stop_datetime) || (pos >= stop_position_mot)) { @@ -387,7 +349,7 @@ int process_event(LAST_EVENT_INFO *last_event_info, Log_event *ev, if (!short_form) fprintf(result_file, "# at %s\n",llstr(pos,ll_buff)); - switch (ev_type) { + switch (ev->get_type_code()) { case QUERY_EVENT: if (one_database) { @@ -395,7 +357,7 @@ int process_event(LAST_EVENT_INFO *last_event_info, Log_event *ev, if ((log_dbname != NULL) && (strcmp(log_dbname, database))) goto end; } - ev->print(result_file, short_form, last_event_info); + ev->print(result_file, short_form, last_db); break; case CREATE_FILE_EVENT: { @@ -419,9 +381,8 @@ int process_event(LAST_EVENT_INFO *last_event_info, Log_event *ev, filename and use LOCAL), prepared in the 'case EXEC_LOAD_EVENT' below. */ - ce->print(result_file, short_form, last_event_info, TRUE); - // If this binlog is not 3.23 ; why this test?? - if (description_event->binlog_version >= 3) + ce->print(result_file, short_form, last_db, TRUE); + if (!old_format) { if (load_processor.process(ce)) break; // Error @@ -430,23 +391,23 @@ int process_event(LAST_EVENT_INFO *last_event_info, Log_event *ev, break; } case APPEND_BLOCK_EVENT: - ev->print(result_file, short_form, last_event_info); + ev->print(result_file, short_form, last_db); if (load_processor.process((Append_block_log_event*) ev)) break; // Error break; case EXEC_LOAD_EVENT: { - ev->print(result_file, short_form, last_event_info); + ev->print(result_file, short_form, last_db); Execute_load_log_event *exv= (Execute_load_log_event*)ev; Create_file_log_event *ce= load_processor.grab_event(exv->file_id); /* if ce is 0, it probably means that we have not seen the Create_file - event (a bad binlog, or most probably --start-position is after the + event (a bad binlog, or most probably --position is after the Create_file event). Print a warning comment. */ if (ce) { - ce->print(result_file, short_form, last_event_info, TRUE); + ce->print(result_file, short_form, last_db, TRUE); my_free((char*)ce->fname,MYF(MY_WME)); delete ce; } @@ -455,20 +416,8 @@ int process_event(LAST_EVENT_INFO *last_event_info, Log_event *ev, Create_file event for file_id: %u\n",exv->file_id); break; } - case FORMAT_DESCRIPTION_EVENT: - delete description_event; - description_event= (Format_description_log_event*) ev; - ev->print(result_file, short_form, last_event_info); - /* - We don't want this event to be deleted now, so let's hide it (I - (Guilhem) should later see if this triggers a non-serious Valgrind - error). Not serious error, because we will free description_event - later. - */ - ev= 0; - break; default: - ev->print(result_file, short_form, last_event_info); + ev->print(result_file, short_form, last_db); } } @@ -609,7 +558,7 @@ static void die(const char* fmt, ...) static void print_version() { - printf("%s Ver 3.1 for %s at %s\n", my_progname, SYSTEM_TYPE, MACHINE_TYPE); + printf("%s Ver 3.0 for %s at %s\n", my_progname, SYSTEM_TYPE, MACHINE_TYPE); NETWARE_SET_SCREEN_MODE(1); } @@ -752,17 +701,12 @@ static int dump_log_entries(const char* logname) } -/* - This is not as smart as check_header() (used for local log); it will not work - for a binlog which mixes format. TODO: fix this. -*/ -static int check_master_version(MYSQL* mysql, - Format_description_log_event - **description_event) +static int check_master_version(MYSQL* mysql) { MYSQL_RES* res = 0; MYSQL_ROW row; const char* version; + int old_format = 0; if (mysql_query(mysql, "SELECT VERSION()") || !(res = mysql_store_result(mysql))) @@ -787,18 +731,11 @@ static int check_master_version(MYSQL* mysql, switch (*version) { case '3': - *description_event= new Format_description_log_event(1); + old_format = 1; break; case '4': - *description_event= new Format_description_log_event(3); case '5': - /* - The server is soon going to send us its Format_description log - event, unless it is a 5.0 server with 3.23 or 4.0 binlogs. - So we first assume that this is 4.0 (which is enough to read the - Format_desc event if one comes). - */ - *description_event= new Format_description_log_event(3); + old_format = 0; break; default: sql_print_error("Master reported unrecognized MySQL version '%s'", @@ -808,17 +745,18 @@ static int check_master_version(MYSQL* mysql, return 1; } mysql_free_result(res); - return 0; + return old_format; } static int dump_remote_log_entries(const char* logname) - { char buf[128]; - LAST_EVENT_INFO last_event_info; - uint len, logname_len; + char last_db[FN_REFLEN+1] = ""; + ulong len; + uint logname_len; NET* net; + int old_format; int error= 0; my_off_t old_off= start_position_mot; char fname[FN_REFLEN+1]; @@ -831,18 +769,7 @@ static int dump_remote_log_entries(const char* logname) */ mysql= safe_connect(); net= &mysql->net; - - if (check_master_version(mysql, &description_event)) - { - fprintf(stderr, "Could not find server version"); - DBUG_RETURN(1); - } - if (!description_event || !description_event->is_valid()) - { - fprintf(stderr, "Invalid Format_description log event; \ -could be out of memory"); - DBUG_RETURN(1); - } + old_format = check_master_version(mysql); /* COM_BINLOG_DUMP accepts only 4 bytes for the position, so we are forced to @@ -850,7 +777,15 @@ could be out of memory"); */ int4store(buf, (uint32)start_position); int2store(buf + BIN_LOG_HEADER_SIZE, binlog_flags); - logname_len = (uint) strlen(logname); + + size_s tlen = strlen(logname); + if (tlen > UINT_MAX) + { + fprintf(stderr,"Log name too long\n"); + error= 1; + goto err; + } + logname_len = (uint) tlen; int4store(buf + 6, 0); memcpy(buf + 10, logname, logname_len); if (simple_command(mysql, COM_BINLOG_DUMP, buf, logname_len + 10, 1)) @@ -863,8 +798,6 @@ could be out of memory"); for (;;) { const char *error_msg; - Log_event *ev; - len = net_safe_read(mysql); if (len == packet_error) { @@ -877,9 +810,9 @@ could be out of memory"); break; // end of data DBUG_PRINT("info",( "len= %u, net->read_pos[5] = %d\n", len, net->read_pos[5])); - if (!(ev= Log_event::read_log_event((const char*) net->read_pos + 1 , - len - 1, &error_msg, - description_event))) + Log_event *ev = Log_event::read_log_event((const char*) net->read_pos + 1 , + len - 1, &error_msg, old_format); + if (!ev) { fprintf(stderr, "Could not construct log event object\n"); error= 1; @@ -887,27 +820,25 @@ could be out of memory"); } Log_event_type type= ev->get_type_code(); - if (description_event->binlog_version >= 3 || - (type != LOAD_EVENT && type != CREATE_FILE_EVENT)) + if (!old_format || ( type != LOAD_EVENT && type != CREATE_FILE_EVENT)) { - /* - If this is a Rotate event, maybe it's the end of the requested binlog; - in this case we are done (stop transfer). - This is suitable for binlogs, not relay logs (but for now we don't read - relay logs remotely because the server is not able to do that). If one - day we read relay logs remotely, then we will have a problem with the - detection below: relay logs contain Rotate events which are about the - binlogs, so which would trigger the end-detection below. - */ - if (type == ROTATE_EVENT) + if (ev->get_type_code() == ROTATE_EVENT) { Rotate_log_event *rev= (Rotate_log_event *)ev; /* + mysqld is sending us all its binlogs after the requested one, but we + don't want them. If this is a fake Rotate event, and not about our log, we can stop transfer. If this a real Rotate event (so it's not about our log, it's in our log describing the next log), we print it (because it's part of our log) and then we will stop when we receive the fake one soon. + This is suitable for binlogs, not relay logs (but for now we don't + read relay logs remotely because the server is not able to do + that). If one day we read relay logs remotely, then we will have a + problem with the detection below: relay logs contain Rotate events + which are about the binlogs, so which would trigger the end-detection + below. */ if (rev->when == 0) { @@ -930,7 +861,7 @@ could be out of memory"); len= 1; // fake Rotate, so don't increment old_off } } - if ((error= process_event(&last_event_info,ev,old_off))) + if ((error= process_event(last_db,ev,old_off,old_format))) { error= ((error < 0) ? 0 : 1); goto err; @@ -942,135 +873,64 @@ could be out of memory"); const char *old_fname= le->fname; uint old_len= le->fname_len; File file; - + if ((file= load_processor.prepare_new_file_for_old_format(le,fname)) < 0) { error= 1; goto err; } - - if ((error= process_event(&last_event_info,ev,old_off))) + + if ((error= process_event(last_db,ev,old_off,old_format))) { - my_close(file,MYF(MY_WME)); + my_close(file,MYF(MY_WME)); error= ((error < 0) ? 0 : 1); goto err; } - error= load_processor.load_old_format_file(net,old_fname,old_len,file); - my_close(file,MYF(MY_WME)); - if (error) + if (load_processor.load_old_format_file(net,old_fname,old_len,file)) { + my_close(file,MYF(MY_WME)); error= 1; goto err; } + my_close(file,MYF(MY_WME)); } + /* Let's adjust offset for remote log as for local log to produce similar text. */ old_off+= len-1; } - err: mysql_close(mysql); DBUG_RETURN(error); } -static void check_header(IO_CACHE* file, - Format_description_log_event **description_event) +static int check_header(IO_CACHE* file) { byte header[BIN_LOG_HEADER_SIZE]; byte buf[PROBE_HEADER_LEN]; - my_off_t tmp_pos, pos; + int old_format=0; + DBUG_ENTER("check_header"); - *description_event= new Format_description_log_event(3); - pos= my_b_tell(file); + my_off_t pos = my_b_tell(file); my_b_seek(file, (my_off_t)0); if (my_b_read(file, header, sizeof(header))) die("Failed reading header; Probably an empty file"); if (memcmp(header, BINLOG_MAGIC, sizeof(header))) die("File is not a binary log file"); - - /* - Imagine we are running with --start-position=1000. We still need - to know the binlog format's. So we still need to find, if there is - one, the Format_desc event, or to know if this is a 3.23 - binlog. So we need to first read the first events of the log, - those around offset 4. Even if we are reading a 3.23 binlog from - the start (no --start-position): we need to know the header length - (which is 13 in 3.23, 19 in 4.x) to be able to successfully print - the first event (Start_log_event_v3). So even in this case, we - need to "probe" the first bytes of the log *before* we do a real - read_log_event(). Because read_log_event() needs to know the - header's length to work fine. - */ - for(;;) + if (!my_b_read(file, buf, sizeof(buf))) { - tmp_pos= my_b_tell(file); /* should be 4 the first time */ - if (my_b_read(file, buf, sizeof(buf))) + if (buf[4] == START_EVENT) { - if (file->error) - die("\ -Could not read entry at offset %lu : Error in log format or read error", - tmp_pos); - /* - Otherwise this is just EOF : this log currently contains 0-2 - events. Maybe it's going to be filled in the next - milliseconds; then we are going to have a problem if this a - 3.23 log (imagine we are locally reading a 3.23 binlog which - is being written presently): we won't know it in - read_log_event() and will fail(). Similar problems could - happen with hot relay logs if --start-position is used (but a - --start-position which is posterior to the current size of the log). - These are rare problems anyway (reading a hot log + when we - read the first events there are not all there yet + when we - read a bit later there are more events + using a strange - --start-position). - */ - break; - } - else - { - DBUG_PRINT("info",("buf[4]=%d", buf[4])); - /* always test for a Start_v3, even if no --start-position */ - if (buf[4] == START_EVENT_V3) /* This is 3.23 or 4.x */ - { - if (uint4korr(buf + EVENT_LEN_OFFSET) < - (LOG_EVENT_MINIMAL_HEADER_LEN + START_V3_HEADER_LEN)) - { - /* This is 3.23 (format 1) */ - delete *description_event; - *description_event= new Format_description_log_event(1); - } - break; - } - else if (tmp_pos >= start_position) - break; - else if (buf[4] == FORMAT_DESCRIPTION_EVENT) /* This is 5.0 */ - { - my_b_seek(file, tmp_pos); /* seek back to event's start */ - if (!(*description_event= (Format_description_log_event*) - Log_event::read_log_event(file, *description_event))) - /* EOF can't be hit here normally, so it's a real error */ - die("Could not read a Format_description_log_event event \ -at offset %lu ; this could be a log format error or read error", - tmp_pos); - DBUG_PRINT("info",("Setting description_event")); - } - else if (buf[4] == ROTATE_EVENT) - { - my_b_seek(file, tmp_pos); /* seek back to event's start */ - if (!Log_event::read_log_event(file, *description_event)) - /* EOF can't be hit here normally, so it's a real error */ - die("Could not read a Rotate_log_event event \ -at offset %lu ; this could be a log format error or read error", - tmp_pos); - } - else - break; + uint event_len; + event_len = uint4korr(buf + EVENT_LEN_OFFSET); + old_format = (event_len < (LOG_EVENT_HEADER_LEN + START_HEADER_LEN)); } } my_b_seek(file, pos); + DBUG_RETURN(old_format); } @@ -1078,10 +938,13 @@ static int dump_local_log_entries(const char* logname) { File fd = -1; IO_CACHE cache,*file= &cache; - LAST_EVENT_INFO last_event_info; + char last_db[FN_REFLEN+1]; byte tmp_buff[BIN_LOG_HEADER_SIZE]; + bool old_format = 0; int error= 0; + last_db[0]= 0; + if (logname && logname[0] != '-') { if ((fd = my_open(logname, O_RDONLY | O_BINARY, MYF(MY_WME))) < 0) @@ -1090,16 +953,16 @@ static int dump_local_log_entries(const char* logname) MYF(MY_WME | MY_NABP))) { my_close(fd, MYF(MY_WME)); - return 1; + exit(1); } - check_header(file, &description_event); + old_format = check_header(file); } - else // reading from stdin; TODO: check that it works + else { if (init_io_cache(file, fileno(result_file), 0, READ_CACHE, (my_off_t) 0, 0, MYF(MY_WME | MY_NABP | MY_DONT_CHECK_FILESIZE))) return 1; - check_header(file, &description_event); + old_format = check_header(file); if (start_position) { /* skip 'start_position' characters from stdout */ @@ -1109,44 +972,46 @@ static int dump_local_log_entries(const char* logname) { tmp=min(length,sizeof(buff)); if (my_b_read(file, buff, (uint) tmp)) - { - error= 1; - goto end; - } + { + error= 1; + goto end; + } } } file->pos_in_file= start_position_mot; file->seek_not_done=0; } - if (!description_event || !description_event->is_valid()) - die("Invalid Format_description log event; could be out of memory"); - - if (!start_position && my_b_read(file, tmp_buff, BIN_LOG_HEADER_SIZE)) + if (!start_position) { - error= 1; - goto end; + // Skip header + if (my_b_read(file, tmp_buff, BIN_LOG_HEADER_SIZE)) + { + error= 1; + goto end; + } } + for (;;) { char llbuff[21]; my_off_t old_off = my_b_tell(file); - Log_event* ev = Log_event::read_log_event(file, description_event); + Log_event* ev = Log_event::read_log_event(file, old_format); if (!ev) { if (file->error) { fprintf(stderr, - "Could not read entry at offset %s:" - "Error in log format or read error\n", - llstr(old_off,llbuff)); - error= 1; + "Could not read entry at offset %s:" + "Error in log format or read error\n", + llstr(old_off,llbuff)); + error= 1; } // file->error == 0 means EOF, that's OK, we break in this case break; } - if ((error= process_event(&last_event_info,ev,old_off))) + if ((error= process_event(last_db,ev,old_off,false))) { if (error < 0) error= 0; @@ -1158,7 +1023,6 @@ end: if (fd >= 0) my_close(fd, MYF(MY_WME)); end_io_cache(file); - delete description_event; return error; } diff --git a/client/mysqldump.c b/client/mysqldump.c index 2defee27c7e..dbc11f1ab90 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -37,7 +37,7 @@ ** 10 Jun 2003: SET NAMES and --no-set-names by Alexander Barkov */ -#define DUMP_VERSION "10.8" +#define DUMP_VERSION "10.9" #include <my_global.h> #include <my_sys.h> @@ -78,8 +78,8 @@ static my_bool verbose=0,tFlag=0,cFlag=0,dFlag=0,quick= 1, extended_insert= 1, lock_tables=1,ignore_errors=0,flush_logs=0,replace=0, ignore=0,opt_drop=1,opt_keywords=0,opt_lock=1,opt_compress=0, opt_delayed=0,create_options=1,opt_quoted=0,opt_databases=0, - opt_alldbs=0,opt_create_db=0,opt_first_slave=0,opt_set_charset, - opt_autocommit=0,opt_master_data,opt_disable_keys=1,opt_xml=0, + opt_alldbs=0,opt_create_db=0,opt_lock_all_tables=0,opt_set_charset, + opt_autocommit=0,opt_disable_keys=1,opt_xml=0, opt_delete_master_logs=0, tty_password=0, opt_single_transaction=0, opt_comments= 0, opt_compact= 0, opt_hex_blob=0; @@ -93,7 +93,9 @@ static char insert_pat[12 * 1024],*opt_password=0,*current_user=0, *err_ptr= 0; static char compatible_mode_normal_str[255]; static ulong opt_compatible_mode= 0; -static uint opt_mysql_port= 0, err_len= 0; +#define MYSQL_OPT_MASTER_DATA_EFFECTIVE_SQL 1 +#define MYSQL_OPT_MASTER_DATA_COMMENTED_SQL 2 +static uint opt_mysql_port= 0, err_len= 0, opt_master_data; static my_string opt_mysql_unix_port=0; static int first_error=0; static DYNAMIC_STRING extended_row; @@ -106,8 +108,6 @@ static uint opt_protocol= 0; static char *default_charset= (char*) MYSQL_UNIVERSAL_CLIENT_CHARSET; static CHARSET_INFO *charset_info= &my_charset_latin1; const char *default_dbug_option="d:t:o,/tmp/mysqldump.trace"; -/* do we met VIEWs during tables scaning */ -my_bool was_views= 0; const char *compatible_mode_names[]= { @@ -185,8 +185,9 @@ static struct my_option my_long_options[] = (gptr*) &opt_delayed, (gptr*) &opt_delayed, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"delete-master-logs", OPT_DELETE_MASTER_LOGS, - "Delete logs on master after backup. This automatically enables --first-slave.", - 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, + "Delete logs on master after backup. This automatically enables --master-data.", + (gptr*) &opt_delete_master_logs, (gptr*) &opt_delete_master_logs, 0, + GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"disable-keys", 'K', "'/*!40000 ALTER TABLE tb_name DISABLE KEYS */; and '/*!40000 ALTER TABLE tb_name ENABLE KEYS */; will be put in the output.", (gptr*) &opt_disable_keys, (gptr*) &opt_disable_keys, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, @@ -205,13 +206,18 @@ static struct my_option my_long_options[] = (gptr*) &opt_enclosed, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0 ,0, 0}, {"fields-escaped-by", OPT_ESC, "Fields in the i.file are escaped by ...", (gptr*) &escaped, (gptr*) &escaped, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"first-slave", 'x', "Locks all tables across all databases.", - (gptr*) &opt_first_slave, (gptr*) &opt_first_slave, 0, GET_BOOL, NO_ARG, + {"first-slave", 'x', "Deprecated, renamed to --lock-all-tables.", + (gptr*) &opt_lock_all_tables, (gptr*) &opt_lock_all_tables, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"flush-logs", 'F', "Flush logs file in server before starting dump. " - "Note that if you dump many databases at once (using the option " - "--databases= or --all-databases), the logs will be flushed for " - "each database dumped.", + "Note that if you dump many databases at once (using the option " + "--databases= or --all-databases), the logs will be flushed for " + "each database dumped. The exception is when using --lock-all-tables " + "or --master-data: " + "in this case the logs will be flushed only once, corresponding " + "to the moment all tables are locked. So if you want your dump and " + "the log flush to happen at the same exact moment you should use " + "--lock-all-tables or --master-data with --flush-logs", (gptr*) &flush_logs, (gptr*) &flush_logs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"force", 'f', "Continue even if we get an sql-error.", @@ -224,17 +230,40 @@ static struct my_option my_long_options[] = {"lines-terminated-by", OPT_LTB, "Lines in the i.file are terminated by ...", (gptr*) &lines_terminated, (gptr*) &lines_terminated, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"lock-all-tables", 'x', "Locks all tables across all databases. This " + "is achieved by taking a global read lock for the duration of the whole " + "dump. Automatically turns --single-transaction and --lock-tables off.", + (gptr*) &opt_lock_all_tables, (gptr*) &opt_lock_all_tables, 0, GET_BOOL, NO_ARG, + 0, 0, 0, 0, 0, 0}, {"lock-tables", 'l', "Lock all tables for read.", (gptr*) &lock_tables, (gptr*) &lock_tables, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, {"master-data", OPT_MASTER_DATA, - "This causes the master position and filename to be appended to your output. This automatically enables --first-slave.", - 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, + "This causes the binary log position and filename to be appended to the " + "output. If equal to 1, will print it as a CHANGE MASTER command; if equal" + " to 2, that command will be prefixed with a comment symbol. " + "This option will turn --lock-all-tables on, unless " + "--single-transaction is specified too (in which case a " + "global read lock is only taken a short time at the beginning of the dump " + "- don't forget to read about --single-transaction below). In all cases " + "any action on logs will happen at the exact moment of the dump." + "Option automatically turns --lock-tables off.", + (gptr*) &opt_master_data, (gptr*) &opt_master_data, 0, + GET_UINT, REQUIRED_ARG, 0, 0, MYSQL_OPT_MASTER_DATA_COMMENTED_SQL, 0, 0, 0}, {"no-autocommit", OPT_AUTOCOMMIT, "Wrap tables with autocommit/commit statements.", (gptr*) &opt_autocommit, (gptr*) &opt_autocommit, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + /* + Note that the combination --single-transaction --master-data + will give bullet-proof binlog position only if server >=4.1.3. That's the + old "FLUSH TABLES WITH READ LOCK does not block commit" fixed bug. + */ {"single-transaction", OPT_TRANSACTION, - "Dump all tables in single transaction to get consistent snapshot. Mutually exclusive with --lock-tables.", + "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.", (gptr*) &opt_single_transaction, (gptr*) &opt_single_transaction, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"no-create-db", 'n', @@ -338,8 +367,6 @@ static int dump_databases(char **); static int dump_all_databases(); static char *quote_name(const char *name, char *buff, my_bool force); static const char *check_if_ignore_table(const char *table_name); -static my_bool getViewStructure(char *table, char* db); -static my_bool dump_all_views_in_db(char *database); #include <help_start.h> @@ -476,14 +503,6 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), char *argument) { switch (optid) { - case OPT_MASTER_DATA: - opt_master_data=1; - opt_first_slave=1; - break; - case OPT_DELETE_MASTER_LOGS: - opt_delete_master_logs=1; - opt_first_slave=1; - break; case 'p': if (argument) { @@ -531,7 +550,6 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), case (int) OPT_OPTIMIZE: extended_insert= opt_drop= opt_lock= quick= create_options= opt_disable_keys= lock_tables= opt_set_charset= 1; - if (opt_single_transaction) lock_tables=0; break; case (int) OPT_SKIP_OPTIMIZATION: extended_insert= opt_drop= opt_lock= quick= create_options= @@ -627,7 +645,19 @@ static int get_options(int *argc, char ***argv) "%s: You must use option --tab with --fields-...\n", my_progname); return(1); } - if (opt_single_transaction) + + /* Ensure consistency of the set of binlog & locking options */ + if (opt_delete_master_logs && !opt_master_data) + opt_master_data= MYSQL_OPT_MASTER_DATA_COMMENTED_SQL; + if (opt_single_transaction && opt_lock_all_tables) + { + fprintf(stderr, "%s: You can't use --single-transaction and " + "--lock-all-tables at the same time.\n", my_progname); + return(1); + } + if (opt_master_data) + opt_lock_all_tables= !opt_single_transaction; + if (opt_single_transaction || opt_lock_all_tables) lock_tables= 0; if (enclosed && opt_enclosed) { @@ -674,6 +704,36 @@ static void DBerror(MYSQL *mysql, const char *when) } /* DBerror */ +/* + Sends a query to server, optionally reads result, prints error message if + some. + + SYNOPSIS + mysql_query_with_error_report() + mysql_con connection to use + res if non zero, result will be put there with mysql_store_result + query query to send to server + + RETURN VALUES + 0 query sending and (if res!=0) result reading went ok + 1 error +*/ + +static int mysql_query_with_error_report(MYSQL *mysql_con, MYSQL_RES **res, + const char *query) +{ + if (mysql_query(mysql_con, query) || + (res && !((*res)= mysql_store_result(mysql_con)))) + { + my_printf_error(0, "%s: Couldn't execute '%s': %s (%d)", + MYF(0), my_progname, query, + mysql_error(mysql_con), mysql_errno(mysql_con)); + return 1; + } + return 0; +} + + static void safe_exit(int error) { if (!first_error) @@ -721,12 +781,15 @@ static int dbConnect(char *host, char *user,char *passwd) DBerror(&mysql_connection, "when trying to connect"); return 1; } + /* + As we're going to set SQL_MODE, it would be lost on reconnect, so we + cannot reconnect. + */ + sock->reconnect= 0; sprintf(buff, "/*!40100 SET @@SQL_MODE=\"%s\" */", compatible_mode_normal_str); - if (mysql_query(sock, buff)) + if (mysql_query_with_error_report(sock, 0, buff)) { - fprintf(stderr, "%s: Can't set the compatible mode %s (error %s)\n", - my_progname, compatible_mode_normal_str, mysql_error(sock)); mysql_close(sock); safe_exit(EX_MYSQLERR); return 1; @@ -965,20 +1028,17 @@ static uint getTableStructure(char *table, char* db) result_table= quote_name(table, table_buff, 1); opt_quoted_table= quote_name(table, table_buff2, 0); - if (!opt_xml && !mysql_query(sock,insert_pat)) + if (!opt_xml && !mysql_query_with_error_report(sock, 0, insert_pat)) { /* using SHOW CREATE statement */ if (!tFlag) { /* Make an sql-file, if path was given iow. option -T was given */ char buff[20+FN_REFLEN]; - MYSQL_FIELD *field; sprintf(buff,"show create table %s", result_table); - if (mysql_query(sock, buff)) + if (mysql_query_with_error_report(sock, 0, buff)) { - fprintf(stderr, "%s: Can't get CREATE TABLE for table %s (%s)\n", - my_progname, result_table, mysql_error(sock)); safe_exit(EX_MYSQLERR); DBUG_RETURN(0); } @@ -1008,25 +1068,15 @@ static uint getTableStructure(char *table, char* db) check_io(sql_file); } - tableRes= mysql_store_result(sock); - field= mysql_fetch_field_direct(tableRes, 0); - if (strcmp(field->name, "View") == 0) - { - if (verbose) - fprintf(stderr, "-- It's a view, skipped\n"); - was_views= 1; - DBUG_RETURN(0); - } - row= mysql_fetch_row(tableRes); + tableRes=mysql_store_result(sock); + row=mysql_fetch_row(tableRes); fprintf(sql_file, "%s;\n", row[1]); check_io(sql_file); mysql_free_result(tableRes); } sprintf(insert_pat,"show fields from %s", result_table); - if (mysql_query(sock,insert_pat) || !(tableRes=mysql_store_result(sock))) + if (mysql_query_with_error_report(sock, &tableRes, insert_pat)) { - fprintf(stderr, "%s: Can't get info about table: %s\nerror: %s\n", - my_progname, result_table, mysql_error(sock)); if (path) my_fclose(sql_file, MYF(MY_WME)); safe_exit(EX_MYSQLERR); @@ -1066,10 +1116,8 @@ static uint getTableStructure(char *table, char* db) my_progname, mysql_error(sock)); sprintf(insert_pat,"show fields from %s", result_table); - if (mysql_query(sock,insert_pat) || !(tableRes=mysql_store_result(sock))) + if (mysql_query_with_error_report(sock, &tableRes, insert_pat)) { - fprintf(stderr, "%s: Can't get info about table: %s\nerror: %s\n", - my_progname, result_table, mysql_error(sock)); safe_exit(EX_MYSQLERR); DBUG_RETURN(0); } @@ -1163,23 +1211,14 @@ static uint getTableStructure(char *table, char* db) char buff[20+FN_REFLEN]; uint keynr,primary_key; sprintf(buff,"show keys from %s", result_table); - if (mysql_query(sock, buff)) + if (mysql_query_with_error_report(sock, &tableRes, buff)) { - if (mysql_errno(sock) == ER_WRONG_OBJECT) - { - /* it is VIEW */ - fputs("\t\t<options Comment=\"view\" />\n", sql_file); - goto continue_xml; - } - fprintf(stderr, "%s: Can't get keys for table %s (%s)\n", - my_progname, result_table, mysql_error(sock)); if (path) my_fclose(sql_file, MYF(MY_WME)); safe_exit(EX_MYSQLERR); DBUG_RETURN(0); } - tableRes=mysql_store_result(sock); /* Find first which key is primary key */ keynr=0; primary_key=INT_MAX; @@ -1243,7 +1282,7 @@ static uint getTableStructure(char *table, char* db) char show_name_buff[FN_REFLEN]; sprintf(buff,"show table status like %s", quote_for_like(table, show_name_buff)); - if (mysql_query(sock, buff)) + if (mysql_query_with_error_report(sock, &tableRes, buff)) { if (mysql_errno(sock) != ER_PARSE_ERROR) { /* If old MySQL version */ @@ -1253,8 +1292,7 @@ static uint getTableStructure(char *table, char* db) result_table,mysql_error(sock)); } } - else if (!(tableRes=mysql_store_result(sock)) || - !(row=mysql_fetch_row(tableRes))) + else if (!(row=mysql_fetch_row(tableRes))) { fprintf(stderr, "Error: Couldn't read status information for table %s (%s)\n", @@ -1278,7 +1316,6 @@ static uint getTableStructure(char *table, char* db) } mysql_free_result(tableRes); /* Is always safe to free */ } -continue_xml: if (!opt_xml) fputs(";\n", sql_file); else @@ -1459,22 +1496,14 @@ static void dumpTable(uint numFields, char *table) fputs("\n", md_result_file); check_io(md_result_file); } - if (mysql_query(sock, query)) - { + if (mysql_query_with_error_report(sock, 0, query)) DBerror(sock, "when retrieving data from server"); - error= EX_CONSCHECK; - goto err; - } if (quick) res=mysql_use_result(sock); else res=mysql_store_result(sock); if (!res) - { DBerror(sock, "when retrieving data from server"); - error= EX_CONSCHECK; - goto err; - } if (verbose) fprintf(stderr, "-- Retrieving rows...\n"); if (mysql_num_fields(res) != numFields) @@ -1809,33 +1838,13 @@ static int dump_all_databases() MYSQL_RES *tableres; int result=0; - if (mysql_query(sock, "SHOW DATABASES") || - !(tableres = mysql_store_result(sock))) - { - my_printf_error(0, "Error: Couldn't execute 'SHOW DATABASES': %s", - MYF(0), mysql_error(sock)); + if (mysql_query_with_error_report(sock, &tableres, "SHOW DATABASES")) return 1; - } while ((row = mysql_fetch_row(tableres))) { if (dump_all_tables_in_db(row[0])) result=1; } - if (was_views) - { - if (mysql_query(sock, "SHOW DATABASES") || - !(tableres = mysql_store_result(sock))) - { - my_printf_error(0, "Error: Couldn't execute 'SHOW DATABASES': %s", - MYF(0), mysql_error(sock)); - return 1; - } - while ((row = mysql_fetch_row(tableres))) - { - if (dump_all_views_in_db(row[0])) - result=1; - } - } return result; } /* dump_all_databases */ @@ -1844,20 +1853,11 @@ static int dump_all_databases() static int dump_databases(char **db_names) { int result=0; - char **db; - for (db= db_names ; *db ; db++) + for ( ; *db_names ; db_names++) { - if (dump_all_tables_in_db(*db)) + if (dump_all_tables_in_db(*db_names)) result=1; } - if (!result && was_views) - { - for (db= db_names ; *db ; db++) - { - if (dump_all_views_in_db(*db)) - result=1; - } - } return result; } /* dump_databases */ @@ -1892,7 +1892,7 @@ static int init_dumping(char *database) sprintf(qbuf,"SHOW CREATE DATABASE WITH IF NOT EXISTS %s", qdatabase); - if (mysql_query(sock, qbuf) || !(dbinfo = mysql_store_result(sock))) + if (mysql_query_with_error_report(sock, &dbinfo, qbuf)) { /* Old server version, dump generic CREATE DATABASE */ fprintf(md_result_file, @@ -1961,68 +1961,15 @@ static int dump_all_tables_in_db(char *database) check_io(md_result_file); } if (lock_tables) - mysql_query(sock,"UNLOCK TABLES"); + mysql_query_with_error_report(sock, 0, "UNLOCK TABLES"); return 0; } /* dump_all_tables_in_db */ -/* - dump structure of views of database - - SYNOPSIS - dump_all_views_in_db() - database database name - RETURN - 0 OK - 1 ERROR -*/ - -static my_bool dump_all_views_in_db(char *database) -{ - char *table; - uint numrows; - char table_buff[NAME_LEN*2+3]; - - if (init_dumping(database)) - return 1; - if (opt_xml) - print_xml_tag1(md_result_file, "", "database name=", database, "\n"); - if (lock_tables) - { - DYNAMIC_STRING query; - init_dynamic_string(&query, "LOCK TABLES ", 256, 1024); - for (numrows= 0 ; (table= getTableName(1)); numrows++) - { - dynstr_append(&query, quote_name(table, table_buff, 1)); - dynstr_append(&query, " READ /*!32311 LOCAL */,"); - } - if (numrows && mysql_real_query(sock, query.str, query.length-1)) - DBerror(sock, "when using LOCK TABLES"); - /* We shall continue here, if --force was given */ - dynstr_free(&query); - } - if (flush_logs) - { - if (mysql_refresh(sock, REFRESH_LOG)) - DBerror(sock, "when doing refresh"); - /* We shall continue here, if --force was given */ - } - while ((table= getTableName(0))) - getViewStructure(table, database); - if (opt_xml) - { - fputs("</database>\n", md_result_file); - check_io(md_result_file); - } - if (lock_tables) - mysql_query(sock,"UNLOCK TABLES"); - return 0; -} /* dump_all_tables_in_db */ static int dump_selected_tables(char *db, char **table_names, int tables) { uint numrows; - int i; char table_buff[NAME_LEN*+3]; if (init_dumping(db)) @@ -2030,6 +1977,7 @@ static int dump_selected_tables(char *db, char **table_names, int tables) if (lock_tables) { DYNAMIC_STRING query; + int i; init_dynamic_string(&query, "LOCK TABLES ", 256, 1024); for (i=0 ; i < tables ; i++) @@ -2050,16 +1998,11 @@ static int dump_selected_tables(char *db, char **table_names, int tables) } if (opt_xml) print_xml_tag1(md_result_file, "", "database name=", db, "\n"); - for (i=0 ; i < tables ; i++) + for (; tables > 0 ; tables-- , table_names++) { - numrows = getTableStructure(table_names[i], db); + numrows = getTableStructure(*table_names, db); if (!dFlag && numrows > 0) - dumpTable(numrows, table_names[i]); - } - if (was_views) - { - for (i=0 ; i < tables ; i++) - getViewStructure(table_names[i], db); + dumpTable(numrows, *table_names); } if (opt_xml) { @@ -2067,11 +2010,76 @@ static int dump_selected_tables(char *db, char **table_names, int tables) check_io(md_result_file); } if (lock_tables) - mysql_query(sock,"UNLOCK TABLES"); + mysql_query_with_error_report(sock, 0, "UNLOCK TABLES"); return 0; } /* dump_selected_tables */ +static int do_show_master_status(MYSQL *mysql_con) +{ + MYSQL_ROW row; + MYSQL_RES *master; + const char *comment_prefix= + (opt_master_data == MYSQL_OPT_MASTER_DATA_COMMENTED_SQL) ? "-- " : ""; + if (mysql_query_with_error_report(mysql_con, &master, "SHOW MASTER STATUS")) + { + my_printf_error(0, "Error: Couldn't execute 'SHOW MASTER STATUS': %s", + MYF(0), mysql_error(mysql_con)); + return 1; + } + else + { + row = mysql_fetch_row(master); + if (row && row[0] && row[1]) + { + if (opt_comments) + fprintf(md_result_file, + "\n--\n-- Position to start replication or point-in-time " + "recovery from\n--\n\n"); + fprintf(md_result_file, + "%sCHANGE MASTER TO MASTER_LOG_FILE='%s', MASTER_LOG_POS=%s;\n", + comment_prefix, row[0], row[1]); + check_io(md_result_file); + } + mysql_free_result(master); + } + return 0; +} + + +static int do_flush_tables_read_lock(MYSQL *mysql_con) +{ + return + mysql_query_with_error_report(mysql_con, 0, "FLUSH TABLES WITH READ LOCK"); +} + + +static int do_unlock_tables(MYSQL *mysql_con) +{ + return mysql_query_with_error_report(mysql_con, 0, "UNLOCK TABLES"); +} + + +static int do_reset_master(MYSQL *mysql_con) +{ + return mysql_query_with_error_report(mysql_con, 0, "RESET MASTER"); +} + + +static int start_transaction(MYSQL *mysql_con, my_bool consistent_read_now) +{ + /* + We use BEGIN for old servers. --single-transaction --master-data will fail + on old servers, but that's ok as it was already silently broken (it didn't + do a consistent read, so better tell people frankly, with the error). + */ + return (mysql_query_with_error_report(mysql_con, 0, + consistent_read_now ? + "START TRANSACTION " + "WITH CONSISTENT SNAPSHOT" : + "BEGIN")); +} + static ulong find_set(TYPELIB *lib, const char *x, uint length, char **err_pos, uint *err_len) @@ -2169,7 +2177,7 @@ static const char *check_if_ignore_table(const char *table_name) sprintf(buff,"show table status like %s", quote_for_like(table_name, show_name_buff)); - if (mysql_query(sock, buff)) + if (mysql_query_with_error_report(sock, &res, buff)) { if (mysql_errno(sock) != ER_PARSE_ERROR) { /* If old MySQL version */ @@ -2180,8 +2188,7 @@ static const char *check_if_ignore_table(const char *table_name) return 0; /* assume table is ok */ } } - if (!(res= mysql_store_result(sock)) || - !(row= mysql_fetch_row(res))) + if (!(row= mysql_fetch_row(res))) { fprintf(stderr, "Error: Couldn't read status information for table %s (%s)\n", @@ -2190,117 +2197,16 @@ static const char *check_if_ignore_table(const char *table_name) mysql_free_result(res); return 0; /* assume table is ok */ } - if (!(row[1])) - result= "VIEW"; - else - { - if (strcmp(row[1], (result= "MRG_MyISAM")) && - strcmp(row[1], (result= "MRG_ISAM"))) - result= 0; - } + if (strcmp(row[1], (result= "MRG_MyISAM")) && + strcmp(row[1], (result= "MRG_ISAM"))) + result= 0; mysql_free_result(res); return result; } -/* - Getting VIEW structure - - SYNOPSIS - getViewStructure() - table view name - db db name - - RETURN - 0 OK - 1 ERROR -*/ - -static my_bool getViewStructure(char *table, char* db) -{ - MYSQL_RES *tableRes; - MYSQL_ROW row; - MYSQL_FIELD *field; - char *result_table, *opt_quoted_table; - char table_buff[NAME_LEN*2+3]; - char table_buff2[NAME_LEN*2+3]; - char buff[20+FN_REFLEN]; - FILE *sql_file = md_result_file; - DBUG_ENTER("getViewStructure"); - - if (tFlag) - DBUG_RETURN(0); - - if (verbose) - fprintf(stderr, "-- Retrieving view structure for table %s...\n", table); - - sprintf(insert_pat,"SET OPTION SQL_QUOTE_SHOW_CREATE=%d", - (opt_quoted || opt_keywords)); - result_table= quote_name(table, table_buff, 1); - opt_quoted_table= quote_name(table, table_buff2, 0); - - sprintf(buff,"show create table %s", result_table); - if (mysql_query(sock, buff)) - { - fprintf(stderr, "%s: Can't get CREATE TABLE for view %s (%s)\n", - my_progname, result_table, mysql_error(sock)); - safe_exit(EX_MYSQLERR); - DBUG_RETURN(0); - } - - if (path) - { - char filename[FN_REFLEN], tmp_path[FN_REFLEN]; - convert_dirname(tmp_path,path,NullS); - sql_file= my_fopen(fn_format(filename, table, tmp_path, ".sql", 4), - O_WRONLY, MYF(MY_WME)); - if (!sql_file) /* If file couldn't be opened */ - { - safe_exit(EX_MYSQLERR); - DBUG_RETURN(1); - } - write_header(sql_file, db); - } - tableRes= mysql_store_result(sock); - field= mysql_fetch_field_direct(tableRes, 0); - if (strcmp(field->name, "View") != 0) - { - if (verbose) - fprintf(stderr, "-- It's base table, skipped\n"); - DBUG_RETURN(0); - } - - if (!opt_xml && opt_comments) - { - fprintf(sql_file, "\n--\n-- View structure for view %s\n--\n\n", - result_table); - check_io(sql_file); - } - if (opt_drop) - { - fprintf(sql_file, "DROP VIEW IF EXISTS %s;\n", opt_quoted_table); - check_io(sql_file); - } - - row= mysql_fetch_row(tableRes); - fprintf(sql_file, "%s;\n", row[1]); - check_io(sql_file); - mysql_free_result(tableRes); - - if (sql_file != md_result_file) - { - fputs("\n", sql_file); - write_footer(sql_file); - my_fclose(sql_file, MYF(MY_WME)); - } - DBUG_RETURN(0); -} - - int main(int argc, char **argv) { - MYSQL_ROW row; - MYSQL_RES *master; compatible_mode_normal_str[0]= 0; MY_INIT(argv[0]); @@ -2314,28 +2220,24 @@ int main(int argc, char **argv) if (!path) write_header(md_result_file, *argv); - if (opt_first_slave) - { - lock_tables=0; /* No other locks needed */ - if (mysql_query(sock, "FLUSH TABLES WITH READ LOCK")) - { - my_printf_error(0, "Error: Couldn't execute 'FLUSH TABLES WITH READ LOCK': %s", - MYF(0), mysql_error(sock)); - my_end(0); - return(first_error); - } - } - else if (opt_single_transaction) + if ((opt_lock_all_tables || opt_master_data) && + do_flush_tables_read_lock(sock)) + goto err; + if (opt_single_transaction && start_transaction(sock, test(opt_master_data))) + goto err; + if (opt_delete_master_logs && do_reset_master(sock)) + goto err; + if (opt_lock_all_tables || opt_master_data) { - /* There is no sense to start transaction if all tables are locked */ - if (mysql_query(sock, "BEGIN")) - { - my_printf_error(0, "Error: Couldn't execute 'BEGIN': %s", - MYF(0), mysql_error(sock)); - my_end(0); - return(first_error); - } + if (flush_logs && mysql_refresh(sock, REFRESH_LOG)) + goto err; + flush_logs= 0; /* not anymore; that would not be sensible */ } + if (opt_master_data && do_show_master_status(sock)) + goto err; + if (opt_single_transaction && do_unlock_tables(sock)) // unlock but no commit! + goto err; + if (opt_alldbs) dump_all_databases(); else if (argc > 1 && !opt_databases) @@ -2348,57 +2250,16 @@ int main(int argc, char **argv) /* One or more databases, all tables */ dump_databases(argv); } - - if (opt_first_slave) - { - if (opt_delete_master_logs && mysql_query(sock, "FLUSH MASTER")) - { - my_printf_error(0, "Error: Couldn't execute 'FLUSH MASTER': %s", - MYF(0), mysql_error(sock)); - } - if (opt_master_data) - { - if (mysql_query(sock, "SHOW MASTER STATUS") || - !(master = mysql_store_result(sock))) - my_printf_error(0, "Error: Couldn't execute 'SHOW MASTER STATUS': %s", - MYF(0), mysql_error(sock)); - else - { - row = mysql_fetch_row(master); - if (row && row[0] && row[1]) - { - if (opt_comments) - fprintf(md_result_file, - "\n--\n-- Position to start replication from\n--\n\n"); - fprintf(md_result_file, - "CHANGE MASTER TO MASTER_LOG_FILE='%s', \ -MASTER_LOG_POS=%s ;\n",row[0],row[1]); - check_io(md_result_file); - } - mysql_free_result(master); - } - } - if (mysql_query(sock, "UNLOCK TABLES")) - my_printf_error(0, "Error: Couldn't execute 'UNLOCK TABLES': %s", - MYF(0), mysql_error(sock)); - } - else if (opt_single_transaction) /* Just to make it beautiful enough */ #ifdef HAVE_SMEM my_free(shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR)); #endif - { - /* - In case we were locking all tables, we did not start transaction - so there is no need to commit it. - */ - - /* This should just free locks as we did not change anything */ - if (mysql_query(sock, "COMMIT")) - { - my_printf_error(0, "Error: Couldn't execute 'COMMIT': %s", - MYF(0), mysql_error(sock)); - } - } + /* + No reason to explicitely COMMIT the transaction, neither to explicitely + UNLOCK TABLES: these will be automatically be done by the server when we + disconnect now. Saves some code here, some network trips, adds nothing to + server. + */ +err: dbDisconnect(current_host); if (!path) write_footer(md_result_file); diff --git a/configure.in b/configure.in index d1f683fcfec..41eb171557c 100644 --- a/configure.in +++ b/configure.in @@ -3065,9 +3065,15 @@ AC_SUBST([NDB_DEFS]) AC_SUBST([ndb_cxxflags_fix]) +if test X"$ndb_port" = Xdefault +then + ndb_port="1186" +fi +AC_SUBST([ndb_port]) + if test X"$ndb_port_base" = Xdefault then - ndb_port_base="2200" + ndb_port_base="2202" fi AC_SUBST([ndb_port_base]) @@ -3106,7 +3112,6 @@ AC_CONFIG_FILES(ndb/Makefile ndb/include/Makefile dnl ndb/src/common/logger/Makefile dnl ndb/src/common/transporter/Makefile dnl ndb/src/common/mgmcommon/Makefile dnl - ndb/src/common/editline/Makefile dnl ndb/src/kernel/Makefile dnl ndb/src/kernel/error/Makefile dnl ndb/src/kernel/blocks/Makefile dnl diff --git a/dbug/dbug.c b/dbug/dbug.c index 1796d883c5e..02175f8b091 100644 --- a/dbug/dbug.c +++ b/dbug/dbug.c @@ -227,14 +227,15 @@ static my_bool init_done = FALSE; /* Set to TRUE when initialization done */ static struct state *stack=0; typedef struct st_code_state { - int lineno; /* Current debugger output line number */ - int level; /* Current function nesting level */ const char *func; /* Name of current user function */ const char *file; /* Name of current user file */ char **framep; /* Pointer to current frame */ - int jmplevel; /* Remember nesting level at setjmp () */ const char *jmpfunc; /* Remember current function for setjmp */ const char *jmpfile; /* Remember current file for setjmp */ + int lineno; /* Current debugger output line number */ + int level; /* Current function nesting level */ + int disable_output; /* Set to it if output is disabled */ + int jmplevel; /* Remember nesting level at setjmp () */ /* * The following variables are used to hold the state information @@ -247,8 +248,8 @@ typedef struct st_code_state { */ uint u_line; /* User source code line number */ - const char *u_keyword; /* Keyword for current macro */ int locked; /* If locked with _db_lock_file */ + const char *u_keyword; /* Keyword for current macro */ } CODE_STATE; /* Parse a debug command string */ @@ -370,8 +371,10 @@ static CODE_STATE *code_state(void) #define code_state() (&static_code_state) #define pthread_mutex_lock(A) {} #define pthread_mutex_unlock(A) {} -static CODE_STATE static_code_state = { 0,0,"?func","?file",NULL,0,NULL, - NULL,0,"?",0}; +static CODE_STATE static_code_state= +{ + "?func", "?file", NULL, NullS, NullS, 0,0,0,0,0,0, NullS +}; #endif @@ -728,9 +731,12 @@ char ***_sframep_ __attribute__((unused))) if (DoProfile ()) { long stackused; - if (*state->framep == NULL) { + if (*state->framep == NULL) + { stackused = 0; - } else { + } + else + { stackused = ((long)(*state->framep)) - ((long)(state->framep)); stackused = stackused > 0 ? stackused : -stackused; } @@ -744,7 +750,7 @@ char ***_sframep_ __attribute__((unused))) (void) fflush (_db_pfp_); } #endif - if (DoTrace (state)) + if (DoTrace(state)) { if (!state->locked) pthread_mutex_lock(&THR_LOCK_dbug); @@ -754,7 +760,7 @@ char ***_sframep_ __attribute__((unused))) dbug_flush (state); /* This does a unlock */ } #ifdef SAFEMALLOC - if (stack -> flags & SANITY_CHECK_ON) + if (stack->flags & SANITY_CHECK_ON && !state->disable_output) if (_sanity(_file_,_line_)) /* Check of safemalloc */ stack -> flags &= ~SANITY_CHECK_ON; #endif @@ -809,9 +815,11 @@ uint *_slevel_) else { #ifdef SAFEMALLOC - if (stack -> flags & SANITY_CHECK_ON) + if (stack->flags & SANITY_CHECK_ON && !state->disable_output) + { if (_sanity(*_sfile_,_line_)) stack->flags &= ~SANITY_CHECK_ON; + } #endif #ifndef THREAD if (DoProfile ()) @@ -954,7 +962,6 @@ uint length) int pos; char dbuff[90]; CODE_STATE *state; - /* Sasha: pre-my_thread_init() safety */ if (!(state=code_state())) return; @@ -994,6 +1001,25 @@ uint length) } } + +/* + Enable/Disable output for this thread + + SYNOPSIS + _db_output_() + flag 1 = enable output, 0 = disable_output + +*/ + +void _db_output_(uint flag) +{ + CODE_STATE *state; + if (!(state=code_state())) + return; + state->disable_output= !flag; +} + + /* * FUNCTION * @@ -1159,7 +1185,7 @@ static BOOLEAN DoTrace (CODE_STATE *state) { reg2 BOOLEAN trace=FALSE; - if (TRACING && + if (TRACING && !state->disable_output && state->level <= stack -> maxdepth && InList (stack -> functions, state->func) && InList (stack -> processes, _db_process_)) @@ -1195,7 +1221,7 @@ static BOOLEAN DoProfile () state=code_state(); profile = FALSE; - if (PROFILING && + if (PROFILING && !state->disable_output && state->level <= stack -> maxdepth && InList (stack -> p_functions, state->func) && InList (stack -> processes, _db_process_)) @@ -1242,7 +1268,7 @@ const char *keyword) if (!(state=code_state())) return FALSE; result = FALSE; - if (DEBUGGING && + if (DEBUGGING && !state->disable_output && state->level <= stack -> maxdepth && InList (stack -> functions, state->func) && InList (stack -> keywords, keyword) && diff --git a/include/my_dbug.h b/include/my_dbug.h index 9174a8b1ef9..711ece4335c 100644 --- a/include/my_dbug.h +++ b/include/my_dbug.h @@ -38,6 +38,7 @@ extern void _db_pargs_(uint _line_,const char *keyword); extern void _db_doprnt_ _VARARGS((const char *format,...)); extern void _db_dump_(uint _line_,const char *keyword,const char *memory, uint length); +extern void _db_output_(); extern void _db_lock_file(); extern void _db_unlock_file(); @@ -66,6 +67,7 @@ extern void _db_unlock_file(); #define DEBUGGER_ON _no_db_=0 #define DBUG_LOCK_FILE { _db_lock_file(); } #define DBUG_UNLOCK_FILE { _db_unlock_file(); } +#define DBUG_OUTPUT(A) { _db_output_(A); } #define DBUG_ASSERT(A) assert(A) #else /* No debugger */ @@ -86,6 +88,7 @@ extern void _db_unlock_file(); #define DEBUGGER_ON #define DBUG_LOCK_FILE #define DBUG_UNLOCK_FILE +#define DBUG_OUTPUT(A) #define DBUG_ASSERT(A) {} #endif #ifdef __cplusplus diff --git a/include/my_global.h b/include/my_global.h index 0ace3123fae..369ba838698 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -370,6 +370,12 @@ int __void__; #define LINT_INIT(var) #endif +#if defined(_lint) || defined(FORCE_INIT_OF_VARS) || defined(HAVE_purify) +#define PURIFY_OR_LINT_INIT(var) var=0 +#else +#define PURIFY_OR_LINT_INIT(var) +#endif + /* Define some useful general macros */ #if defined(__cplusplus) && defined(__GNUC__) #define max(a, b) ((a) >? (b)) diff --git a/include/my_sys.h b/include/my_sys.h index e99b2d343ff..f95329950eb 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -221,6 +221,7 @@ extern ulong my_cache_w_requests, my_cache_write, my_cache_r_requests, my_cache_read; extern ulong my_blocks_used, my_blocks_changed; extern ulong my_file_opened,my_stream_opened, my_tmp_file_created; +extern uint mysys_usage_id; extern my_bool my_init_done; /* Point to current my_message() */ diff --git a/include/mysql.h b/include/mysql.h index 0a7ab09c57b..0edd3873192 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -490,6 +490,8 @@ MYSQL_RES * STDCALL mysql_list_fields(MYSQL *mysql, const char *table, const char *wild); unsigned long STDCALL mysql_escape_string(char *to,const char *from, unsigned long from_length); +unsigned long STDCALL mysql_hex_string(char *to,const char *from, + unsigned long from_length); unsigned long STDCALL mysql_real_escape_string(MYSQL *mysql, char *to,const char *from, unsigned long length); diff --git a/innobase/include/dict0dict.ic b/innobase/include/dict0dict.ic index 0f7cc8973db..85e4aaf1a05 100644 --- a/innobase/include/dict0dict.ic +++ b/innobase/include/dict0dict.ic @@ -342,13 +342,16 @@ dict_index_rec_get_sys_col( ut_ad(len == 7); return(trx_read_roll_ptr(field)); - } else if ((type == DATA_ROW_ID) || (type == DATA_MIX_ID)) { + } else if (type == DATA_TRX_ID) { + + return(trx_read_trx_id(field)); + } else if (type == DATA_MIX_ID) { return(mach_dulint_read_compressed(field)); } else { - ut_ad(type == DATA_TRX_ID); + ut_a(type == DATA_ROW_ID); - return(trx_read_trx_id(field)); + return(mach_read_from_6(field)); } } diff --git a/mysql-test/Makefile.am b/mysql-test/Makefile.am index ad02d304d1b..fcf352f46e6 100644 --- a/mysql-test/Makefile.am +++ b/mysql-test/Makefile.am @@ -37,7 +37,7 @@ test_DATA = std_data/client-key.pem std_data/client-cert.pem std_data/cacert.pem CLEANFILES = $(test_SCRIPTS) $(test_DATA) INCLUDES = -I$(srcdir)/../include -I../include -I.. -bin_PROGRAMS = mysql_test_run_new +EXTRA_PROGRAMS = mysql_test_run_new noinst_HEADERS = my_manage.h mysql_test_run_new_SOURCES= mysql_test_run_new.c my_manage.c diff --git a/mysql-test/init_db.sql b/mysql-test/init_db.sql index 4613e5c0274..63483af00d6 100644 --- a/mysql-test/init_db.sql +++ b/mysql-test/init_db.sql @@ -3,24 +3,56 @@ CREATE DATABASE test; USE mysql; -CREATE TABLE db (Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Select_priv enum('N','Y') DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') DEFAULT 'N' NOT NULL, References_priv enum('N','Y') DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL, PRIMARY KEY Host (Host,Db,User), KEY User (User)) comment='Database privileges'; +CREATE TABLE db (Host char(60) binary DEFAULT '' NOT NULL,Db char(64) binary DEFAULT '' NOT NULL,User char(16) binary DEFAULT '' NOT NULL,Select_priv enum('N','Y') DEFAULT 'N' NOT NULL,Insert_priv enum('N','Y') DEFAULT 'N' NOT NULL,Update_priv enum('N','Y') DEFAULT 'N' NOT NULL,Delete_priv enum('N','Y') DEFAULT 'N' NOT NULL,Create_priv enum('N','Y') DEFAULT 'N' NOT NULL,Drop_priv enum('N','Y') DEFAULT 'N' NOT NULL,Grant_priv enum('N','Y') DEFAULT 'N' NOT NULL,References_priv enum('N','Y') DEFAULT 'N' NOT NULL,Index_priv enum('N','Y') DEFAULT 'N' NOT NULL,Alter_priv enum('N','Y') DEFAULT 'N' NOT NULL,Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL,Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL,PRIMARY KEY Host (Host,Db,User),KEY User (User)) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Database privileges'; + INSERT INTO db VALUES ('%','test','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y'); INSERT INTO db VALUES ('%','test\_%','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y'); - -CREATE TABLE host (Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, Select_priv enum('N','Y') DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') DEFAULT 'N' NOT NULL, References_priv enum('N','Y') DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL, PRIMARY KEY Host (Host,Db)) comment='Host privileges; Merged with database privileges'; -CREATE TABLE user (Host char(60) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Password char(45) binary DEFAULT '' NOT NULL, Select_priv enum('N','Y') DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') DEFAULT 'N' NOT NULL, Reload_priv enum('N','Y') DEFAULT 'N' NOT NULL, Shutdown_priv enum('N','Y') DEFAULT 'N' NOT NULL, Process_priv enum('N','Y') DEFAULT 'N' NOT NULL, File_priv enum('N','Y') DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') DEFAULT 'N' NOT NULL, References_priv enum('N','Y') DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') DEFAULT 'N' NOT NULL, Show_db_priv enum('N','Y') DEFAULT 'N' NOT NULL, Super_priv enum('N','Y') DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') DEFAULT 'N' NOT NULL, Repl_slave_priv enum('N','Y') DEFAULT 'N' NOT NULL, Repl_client_priv enum('N','Y') DEFAULT 'N' NOT NULL, ssl_type enum('','ANY','X509', 'SPECIFIED') DEFAULT '' NOT NULL, ssl_cipher BLOB NOT NULL, x509_issuer BLOB NOT NULL, x509_subject BLOB NOT NULL, max_questions int(11) unsigned DEFAULT 0 NOT NULL, max_updates int(11) unsigned DEFAULT 0 NOT NULL, max_connections int(11) unsigned DEFAULT 0 NOT NULL, PRIMARY KEY Host (Host,User)) comment='Users and global privileges'; -INSERT INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); -INSERT INTO user VALUES ('','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); +CREATE TABLE host (Host char(60) binary DEFAULT '' NOT NULL,Db char(64) binary DEFAULT '' NOT NULL,Select_priv enum('N','Y') DEFAULT 'N' NOT NULL,Insert_priv enum('N','Y') DEFAULT 'N' NOT NULL,Update_priv enum('N','Y') DEFAULT 'N' NOT NULL,Delete_priv enum('N','Y') DEFAULT 'N' NOT NULL,Create_priv enum('N','Y') DEFAULT 'N' NOT NULL,Drop_priv enum('N','Y') DEFAULT 'N' NOT NULL,Grant_priv enum('N','Y') DEFAULT 'N' NOT NULL,References_priv enum('N','Y') DEFAULT 'N' NOT NULL,Index_priv enum('N','Y') DEFAULT 'N' NOT NULL,Alter_priv enum('N','Y') DEFAULT 'N' NOT NULL,Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL,Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL,PRIMARY KEY Host (Host,Db)) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Host privileges; Merged with database privileges'; -INSERT INTO user (host,user) values ('localhost',''); -INSERT INTO user (host,user) values ('',''); +CREATE TABLE user (Host char(60) binary DEFAULT '' NOT NULL,User char(16) binary DEFAULT '' NOT NULL,Password char(41) binary DEFAULT '' NOT NULL,Select_priv enum('N','Y') DEFAULT 'N' NOT NULL,Insert_priv enum('N','Y') DEFAULT 'N' NOT NULL,Update_priv enum('N','Y') DEFAULT 'N' NOT NULL,Delete_priv enum('N','Y') DEFAULT 'N' NOT NULL,Create_priv enum('N','Y') DEFAULT 'N' NOT NULL,Drop_priv enum('N','Y') DEFAULT 'N' NOT NULL,Reload_priv enum('N','Y') DEFAULT 'N' NOT NULL,Shutdown_priv enum('N','Y') DEFAULT 'N' NOT NULL,Process_priv enum('N','Y') DEFAULT 'N' NOT NULL,File_priv enum('N','Y') DEFAULT 'N' NOT NULL,Grant_priv enum('N','Y') DEFAULT 'N' NOT NULL,References_priv enum('N','Y') DEFAULT 'N' NOT NULL,Index_priv enum('N','Y') DEFAULT 'N' NOT NULL,Alter_priv enum('N','Y') DEFAULT 'N' NOT NULL,Show_db_priv enum('N','Y') DEFAULT 'N' NOT NULL,Super_priv enum('N','Y') DEFAULT 'N' NOT NULL,Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL,Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL,Execute_priv enum('N','Y') DEFAULT 'N' NOT NULL,Repl_slave_priv enum('N','Y') DEFAULT 'N' NOT NULL,Repl_client_priv enum('N','Y') DEFAULT 'N' NOT NULL,ssl_type enum('','ANY','X509', 'SPECIFIED') DEFAULT '' NOT NULL,ssl_cipher BLOB NOT NULL,x509_issuer BLOB NOT NULL,x509_subject BLOB NOT NULL,max_questions int(11) unsigned DEFAULT 0 NOT NULL,max_updates int(11) unsigned DEFAULT 0 NOT NULL,max_connections int(11) unsigned DEFAULT 0 NOT NULL,PRIMARY KEY Host (Host,User)) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Users and global privileges'; -CREATE TABLE func (name char(64) binary DEFAULT '' NOT NULL, ret tinyint(1) DEFAULT '0' NOT NULL, dl char(128) DEFAULT '' NOT NULL, type enum ('function','aggregate') NOT NULL, PRIMARY KEY (name)) comment='User defined functions'; +INSERT INTO user VALUES ('%','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); +INSERT INTO user VALUES ('localhost','','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); +INSERT INTO user VALUES ('%','','','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','','','','',0,0,0); -CREATE TABLE tables_priv (Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Table_name char(60) binary DEFAULT '' NOT NULL, Grantor char(77) DEFAULT '' NOT NULL, Timestamp timestamp(14), Table_priv set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter') DEFAULT '' NOT NULL, Column_priv set('Select','Insert','Update','References') DEFAULT '' NOT NULL, PRIMARY KEY (Host,Db,User,Table_name), KEY Grantor (Grantor)) comment='Table privileges'; +CREATE TABLE func (name char(64) binary DEFAULT '' NOT NULL,ret tinyint(1) DEFAULT '0' NOT NULL,dl char(128) DEFAULT '' NOT NULL,type enum ('function','aggregate') NOT NULL,PRIMARY KEY (name)) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='User defined functions'; + +CREATE TABLE tables_priv (Host char(60) binary DEFAULT '' NOT NULL,Db char(64) binary DEFAULT '' NOT NULL,User char(16) binary DEFAULT '' NOT NULL,Table_name char(64) binary DEFAULT '' NOT NULL,Grantor char(77) DEFAULT '' NOT NULL,Timestamp timestamp(14),Table_priv set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter') DEFAULT '' NOT NULL,Column_priv set('Select','Insert','Update','References') DEFAULT '' NOT NULL,PRIMARY KEY (Host,Db,User,Table_name),KEY Grantor (Grantor)) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Table privileges'; + +CREATE TABLE columns_priv (Host char(60) binary DEFAULT '' NOT NULL,Db char(64) binary DEFAULT '' NOT NULL,User char(16) binary DEFAULT '' NOT NULL,Table_name char(64) binary DEFAULT '' NOT NULL,Column_name char(64) binary DEFAULT '' NOT NULL,Timestamp timestamp(14),Column_priv set('Select','Insert','Update','References') DEFAULT '' NOT NULL,PRIMARY KEY (Host,Db,User,Table_name,Column_name)) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Column privileges'; + +CREATE TABLE help_topic (help_topic_id int unsigned not null,name varchar(64) not null,help_category_id smallint unsigned not null,description text not null,example text not null,url varchar(128) not null,primary key (help_topic_id),unique index (name)) engine=MyISAM CHARACTER SET utf8 comment='help topics'; + +CREATE TABLE help_category (help_category_id smallint unsigned not null,name varchar(64) not null,parent_category_id smallint unsigned null,url varchar(128) not null,primary key (help_category_id),unique index (name)) engine=MyISAM CHARACTER SET utf8 comment='help categories'; + +CREATE TABLE help_keyword (help_keyword_id int unsigned not null,name varchar(64) not null,primary key (help_keyword_id),unique index (name)) engine=MyISAM CHARACTER SET utf8 comment='help keywords'; + +CREATE TABLE help_relation (help_topic_id int unsigned not null references help_topic,help_keyword_id int unsigned not null references help_keyword,primary key (help_keyword_id, help_topic_id)) engine=MyISAM CHARACTER SET utf8 comment='keyword-topic relation'; + +CREATE TABLE time_zone_name (Name char(64) NOT NULL,Time_zone_id int unsigned NOT NULL,PRIMARY KEY Name (Name)) engine=MyISAM CHARACTER SET utf8 comment='Time zone names'; + +INSERT INTO time_zone_name (Name, Time_Zone_id) VALUES ('MET', 1), ('UTC', 2), ('Universal', 2), ('Europe/Moscow',3), ('leap/Europe/Moscow',4), ('Japan', 5); + + +CREATE TABLE time_zone (Time_zone_id int unsigned NOT NULL auto_increment,Use_leap_seconds enum('Y','N') DEFAULT 'N' NOT NULL,PRIMARY KEY TzId (Time_zone_id)) engine=MyISAM CHARACTER SET utf8 comment='Time zones'; + +INSERT INTO time_zone (Time_zone_id, Use_leap_seconds) VALUES (1,'N'), (2,'N'), (3,'N'), (4,'Y'), (5,'N'); + + +CREATE TABLE time_zone_transition (Time_zone_id int unsigned NOT NULL,Transition_time bigint signed NOT NULL,Transition_type_id int unsigned NOT NULL,PRIMARY KEY TzIdTranTime (Time_zone_id, Transition_time)) engine=MyISAM CHARACTER SET utf8 comment='Time zone transitions'; + +INSERT INTO time_zone_transition (Time_zone_id, Transition_time, Transition_type_id) VALUES (1, -1693706400, 0) ,(1, -1680483600, 1),(1, -1663455600, 2) ,(1, -1650150000, 3),(1, -1632006000, 2) ,(1, -1618700400, 3),(1, -938905200, 2) ,(1, -857257200, 3),(1, -844556400, 2) ,(1, -828226800, 3),(1, -812502000, 2) ,(1, -796777200, 3),(1, 228877200, 2) ,(1, 243997200, 3),(1, 260326800, 2) ,(1, 276051600, 3),(1, 291776400, 2) ,(1, 307501200, 3),(1, 323830800, 2) ,(1, 338950800, 3),(1, 354675600, 2) ,(1, 370400400, 3),(1, 386125200, 2) ,(1, 401850000, 3),(1, 417574800, 2) ,(1, 433299600, 3),(1, 449024400, 2) ,(1, 465354000, 3),(1, 481078800, 2) ,(1, 496803600, 3),(1, 512528400, 2) ,(1, 528253200, 3),(1, 543978000, 2) ,(1, 559702800, 3),(1, 575427600, 2) ,(1, 591152400, 3),(1, 606877200, 2) ,(1, 622602000, 3),(1, 638326800, 2) ,(1, 654656400, 3),(1, 670381200, 2) ,(1, 686106000, 3),(1, 701830800, 2) ,(1, 717555600, 3),(1, 733280400, 2) ,(1, 749005200, 3),(1, 764730000, 2) ,(1, 780454800, 3),(1, 796179600, 2) ,(1, 811904400, 3),(1, 828234000, 2) ,(1, 846378000, 3),(1, 859683600, 2) ,(1, 877827600, 3),(1, 891133200, 2) ,(1, 909277200, 3),(1, 922582800, 2) ,(1, 941331600, 3),(1, 954032400, 2) ,(1, 972781200, 3),(1, 985482000, 2) ,(1, 1004230800, 3),(1, 1017536400, 2) ,(1, 1035680400, 3),(1, 1048986000, 2) ,(1, 1067130000, 3),(1, 1080435600, 2) ,(1, 1099184400, 3),(1, 1111885200, 2) ,(1, 1130634000, 3),(1, 1143334800, 2) ,(1, 1162083600, 3),(1, 1174784400, 2) ,(1, 1193533200, 3),(1, 1206838800, 2) ,(1, 1224982800, 3),(1, 1238288400, 2) ,(1, 1256432400, 3),(1, 1269738000, 2) ,(1, 1288486800, 3),(1, 1301187600, 2) ,(1, 1319936400, 3),(1, 1332637200, 2) ,(1, 1351386000, 3),(1, 1364691600, 2) ,(1, 1382835600, 3),(1, 1396141200, 2) ,(1, 1414285200, 3),(1, 1427590800, 2) ,(1, 1445734800, 3),(1, 1459040400, 2) ,(1, 1477789200, 3),(1, 1490490000, 2) ,(1, 1509238800, 3),(1, 1521939600, 2) ,(1, 1540688400, 3),(1, 1553994000, 2) ,(1, 1572138000, 3),(1, 1585443600, 2) ,(1, 1603587600, 3),(1, 1616893200, 2) ,(1, 1635642000, 3),(1, 1648342800, 2) ,(1, 1667091600, 3),(1, 1679792400, 2) ,(1, 1698541200, 3),(1, 1711846800, 2) ,(1, 1729990800, 3),(1, 1743296400, 2) ,(1, 1761440400, 3),(1, 1774746000, 2) ,(1, 1792890000, 3),(1, 1806195600, 2) ,(1, 1824944400, 3),(1, 1837645200, 2) ,(1, 1856394000, 3),(1, 1869094800, 2) ,(1, 1887843600, 3),(1, 1901149200, 2) ,(1, 1919293200, 3),(1, 1932598800, 2) ,(1, 1950742800, 3),(1, 1964048400, 2) ,(1, 1982797200, 3),(1, 1995498000, 2) ,(1, 2014246800, 3),(1, 2026947600, 2) ,(1, 2045696400, 3),(1, 2058397200, 2) ,(1, 2077146000, 3),(1, 2090451600, 2) ,(1, 2108595600, 3),(1, 2121901200, 2) ,(1, 2140045200, 3),(3, -1688265000, 2) ,(3, -1656819048, 1),(3, -1641353448, 2) ,(3, -1627965048, 3),(3, -1618716648, 1) ,(3, -1596429048, 3),(3, -1593829848, 5) ,(3, -1589860800, 4),(3, -1542427200, 5) ,(3, -1539493200, 6),(3, -1525323600, 5) ,(3, -1522728000, 4),(3, -1491188400, 7) ,(3, -1247536800, 4),(3, 354920400, 5) ,(3, 370728000, 4),(3, 386456400, 5) ,(3, 402264000, 4),(3, 417992400, 5) ,(3, 433800000, 4),(3, 449614800, 5) ,(3, 465346800, 8),(3, 481071600, 9) ,(3, 496796400, 8),(3, 512521200, 9) ,(3, 528246000, 8),(3, 543970800, 9) ,(3, 559695600, 8),(3, 575420400, 9) ,(3, 591145200, 8),(3, 606870000, 9) ,(3, 622594800, 8),(3, 638319600, 9) ,(3, 654649200, 8),(3, 670374000, 10) ,(3, 686102400, 11),(3, 695779200, 8) ,(3, 701812800, 5),(3, 717534000, 4) ,(3, 733273200, 9),(3, 748998000, 8) ,(3, 764722800, 9),(3, 780447600, 8) ,(3, 796172400, 9),(3, 811897200, 8) ,(3, 828226800, 9),(3, 846370800, 8) ,(3, 859676400, 9),(3, 877820400, 8) ,(3, 891126000, 9),(3, 909270000, 8) ,(3, 922575600, 9),(3, 941324400, 8) ,(3, 954025200, 9),(3, 972774000, 8) ,(3, 985474800, 9),(3, 1004223600, 8) ,(3, 1017529200, 9),(3, 1035673200, 8) ,(3, 1048978800, 9),(3, 1067122800, 8) ,(3, 1080428400, 9),(3, 1099177200, 8) ,(3, 1111878000, 9),(3, 1130626800, 8) ,(3, 1143327600, 9),(3, 1162076400, 8) ,(3, 1174777200, 9),(3, 1193526000, 8) ,(3, 1206831600, 9),(3, 1224975600, 8) ,(3, 1238281200, 9),(3, 1256425200, 8) ,(3, 1269730800, 9),(3, 1288479600, 8) ,(3, 1301180400, 9),(3, 1319929200, 8) ,(3, 1332630000, 9),(3, 1351378800, 8) ,(3, 1364684400, 9),(3, 1382828400, 8) ,(3, 1396134000, 9),(3, 1414278000, 8) ,(3, 1427583600, 9),(3, 1445727600, 8) ,(3, 1459033200, 9),(3, 1477782000, 8) ,(3, 1490482800, 9),(3, 1509231600, 8) ,(3, 1521932400, 9),(3, 1540681200, 8) ,(3, 1553986800, 9),(3, 1572130800, 8) ,(3, 1585436400, 9),(3, 1603580400, 8) ,(3, 1616886000, 9),(3, 1635634800, 8) ,(3, 1648335600, 9),(3, 1667084400, 8) ,(3, 1679785200, 9),(3, 1698534000, 8) ,(3, 1711839600, 9),(3, 1729983600, 8) ,(3, 1743289200, 9),(3, 1761433200, 8) ,(3, 1774738800, 9),(3, 1792882800, 8) ,(3, 1806188400, 9),(3, 1824937200, 8) ,(3, 1837638000, 9),(3, 1856386800, 8) ,(3, 1869087600, 9),(3, 1887836400, 8) ,(3, 1901142000, 9),(3, 1919286000, 8) ,(3, 1932591600, 9),(3, 1950735600, 8) ,(3, 1964041200, 9),(3, 1982790000, 8) ,(3, 1995490800, 9),(3, 2014239600, 8) ,(3, 2026940400, 9),(3, 2045689200, 8) ,(3, 2058390000, 9),(3, 2077138800, 8) ,(3, 2090444400, 9),(3, 2108588400, 8) ,(3, 2121894000, 9),(3, 2140038000, 8),(4, -1688265000, 2) ,(4, -1656819048, 1),(4, -1641353448, 2) ,(4, -1627965048, 3),(4, -1618716648, 1) ,(4, -1596429048, 3),(4, -1593829848, 5) ,(4, -1589860800, 4),(4, -1542427200, 5) ,(4, -1539493200, 6),(4, -1525323600, 5) ,(4, -1522728000, 4),(4, -1491188400, 7) ,(4, -1247536800, 4),(4, 354920409, 5) ,(4, 370728010, 4),(4, 386456410, 5) ,(4, 402264011, 4),(4, 417992411, 5) ,(4, 433800012, 4),(4, 449614812, 5) ,(4, 465346812, 8),(4, 481071612, 9) ,(4, 496796413, 8),(4, 512521213, 9) ,(4, 528246013, 8),(4, 543970813, 9) ,(4, 559695613, 8),(4, 575420414, 9) ,(4, 591145214, 8),(4, 606870014, 9) ,(4, 622594814, 8),(4, 638319615, 9) ,(4, 654649215, 8),(4, 670374016, 10) ,(4, 686102416, 11),(4, 695779216, 8) ,(4, 701812816, 5),(4, 717534017, 4) ,(4, 733273217, 9),(4, 748998018, 8) ,(4, 764722818, 9),(4, 780447619, 8) ,(4, 796172419, 9),(4, 811897219, 8) ,(4, 828226820, 9),(4, 846370820, 8) ,(4, 859676420, 9),(4, 877820421, 8) ,(4, 891126021, 9),(4, 909270021, 8) ,(4, 922575622, 9),(4, 941324422, 8) ,(4, 954025222, 9),(4, 972774022, 8) ,(4, 985474822, 9),(4, 1004223622, 8) ,(4, 1017529222, 9),(4, 1035673222, 8) ,(4, 1048978822, 9),(4, 1067122822, 8) ,(4, 1080428422, 9),(4, 1099177222, 8) ,(4, 1111878022, 9),(4, 1130626822, 8) ,(4, 1143327622, 9),(4, 1162076422, 8) ,(4, 1174777222, 9),(4, 1193526022, 8) ,(4, 1206831622, 9),(4, 1224975622, 8) ,(4, 1238281222, 9),(4, 1256425222, 8) ,(4, 1269730822, 9),(4, 1288479622, 8) ,(4, 1301180422, 9),(4, 1319929222, 8) ,(4, 1332630022, 9),(4, 1351378822, 8) ,(4, 1364684422, 9),(4, 1382828422, 8) ,(4, 1396134022, 9),(4, 1414278022, 8) ,(4, 1427583622, 9),(4, 1445727622, 8) ,(4, 1459033222, 9),(4, 1477782022, 8) ,(4, 1490482822, 9),(4, 1509231622, 8) ,(4, 1521932422, 9),(4, 1540681222, 8) ,(4, 1553986822, 9),(4, 1572130822, 8) ,(4, 1585436422, 9),(4, 1603580422, 8) ,(4, 1616886022, 9),(4, 1635634822, 8) ,(4, 1648335622, 9),(4, 1667084422, 8) ,(4, 1679785222, 9),(4, 1698534022, 8) ,(4, 1711839622, 9),(4, 1729983622, 8) ,(4, 1743289222, 9),(4, 1761433222, 8) ,(4, 1774738822, 9),(4, 1792882822, 8) ,(4, 1806188422, 9),(4, 1824937222, 8) ,(4, 1837638022, 9),(4, 1856386822, 8) ,(4, 1869087622, 9),(4, 1887836422, 8) ,(4, 1901142022, 9),(4, 1919286022, 8) ,(4, 1932591622, 9),(4, 1950735622, 8) ,(4, 1964041222, 9),(4, 1982790022, 8) ,(4, 1995490822, 9),(4, 2014239622, 8) ,(4, 2026940422, 9),(4, 2045689222, 8) ,(4, 2058390022, 9),(4, 2077138822, 8) ,(4, 2090444422, 9),(4, 2108588422, 8) ,(4, 2121894022, 9),(4, 2140038022, 8); + + +CREATE TABLE time_zone_transition_type (Time_zone_id int unsigned NOT NULL,Transition_type_id int unsigned NOT NULL,Offset int signed DEFAULT 0 NOT NULL,Is_DST tinyint unsigned DEFAULT 0 NOT NULL,Abbreviation char(8) DEFAULT '' NOT NULL,PRIMARY KEY TzIdTrTId (Time_zone_id, Transition_type_id)) engine=MyISAM CHARACTER SET utf8 comment='Time zone transition types'; + +INSERT INTO time_zone_transition_type (Time_zone_id,Transition_type_id, Offset, Is_DST, Abbreviation) VALUES (1, 0, 7200, 1, 'MEST') ,(1, 1, 3600, 0, 'MET') ,(1, 2, 7200, 1, 'MEST') ,(1, 3, 3600, 0, 'MET') ,(2, 0, 0, 0, 'UTC') ,(3, 0, 9000, 0, 'MMT') ,(3, 1, 12648, 1, 'MST') ,(3, 2, 9048, 0, 'MMT') ,(3, 3, 16248, 1, 'MDST') ,(3, 4, 10800, 0, 'MSK') ,(3, 5, 14400, 1, 'MSD') ,(3, 6, 18000, 1, 'MSD') ,(3, 7, 7200, 0, 'EET') ,(3, 8, 10800, 0, 'MSK') ,(3, 9, 14400, 1, 'MSD') ,(3, 10, 10800, 1, 'EEST') ,(3, 11, 7200, 0, 'EET') ,(4, 0, 9000, 0, 'MMT') ,(4, 1, 12648, 1, 'MST') ,(4, 2, 9048, 0, 'MMT') ,(4, 3, 16248, 1, 'MDST') ,(4, 4, 10800, 0, 'MSK') ,(4, 5, 14400, 1, 'MSD') ,(4, 6, 18000, 1, 'MSD') ,(4, 7, 7200, 0, 'EET') ,(4, 8, 10800, 0, 'MSK') ,(4, 9, 14400, 1, 'MSD') ,(4, 10, 10800, 1, 'EEST') ,(4, 11, 7200, 0, 'EET') ,(5, 0, 32400, 0, 'CJT') ,(5, 1, 32400, 0, 'JST'); + +CREATE TABLE time_zone_leap_second (Transition_time bigint signed NOT NULL,Correction int signed NOT NULL,PRIMARY KEY TranTime (Transition_time)) engine=MyISAM CHARACTER SET utf8 comment='Leap seconds information for time zones'; + +INSERT INTO time_zone_leap_second (Transition_time, Correction) VALUES (78796800, 1) ,(94694401, 2) ,(126230402, 3) ,(157766403, 4) ,(189302404, 5) ,(220924805, 6) ,(252460806, 7) ,(283996807, 8) ,(315532808, 9) ,(362793609, 10) ,(394329610, 11) ,(425865611, 12) ,(489024012, 13) ,(567993613, 14) ,(631152014, 15) ,(662688015, 16) ,(709948816, 17) ,(741484817, 18) ,(773020818, 19) ,(820454419, 20) ,(867715220, 21) ,(915148821, 22); -CREATE TABLE columns_priv (Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Table_name char(64) binary DEFAULT '' NOT NULL, Column_name char(64) binary DEFAULT '' NOT NULL, Timestamp timestamp(14), Column_priv set('Select','Insert','Update','References') DEFAULT '' NOT NULL, PRIMARY KEY (Host,Db,User,Table_name,Column_name)) comment='Column privileges'; diff --git a/mysql-test/my_manage.c b/mysql-test/my_manage.c index ba5c674d105..cc27558f131 100644 --- a/mysql-test/my_manage.c +++ b/mysql-test/my_manage.c @@ -30,7 +30,8 @@ #ifndef __WIN__ #include <sys/wait.h> #include <unistd.h> -#include <fnmatch.h> +#include <signal.h> +#include <fnmatch.h> /* FIXME HAVE_FNMATCH_H or something */ #else #include <direct.h> #include <stdlib.h> @@ -100,7 +101,7 @@ void init_args(arg_list_t *al) void add_arg(arg_list_t *al, const char *format, ...) { va_list ap; - char temp[PATH_MAX]; + char temp[FN_REFLEN]; ASSERT(al != NULL); @@ -230,10 +231,10 @@ int wait_for_server_start(char *bin_dir __attribute__((unused)), { arg_list_t al; int err= 0, i; - char trash[PATH_MAX]; + char trash[FN_REFLEN]; /* mysqladmin file */ - snprintf(trash, PATH_MAX, "%s/trash.out",tmp_dir); + snprintf(trash, FN_REFLEN, "%s/trash.out",tmp_dir); /* args */ init_args(&al); @@ -490,9 +491,9 @@ int stop_server(char *bin_dir __attribute__((unused)), char *mysqladmin_file, { arg_list_t al; int err= 0; - char trash[PATH_MAX]; + char trash[FN_REFLEN]; - snprintf(trash, PATH_MAX, "%s/trash.out",tmp_dir); + snprintf(trash, FN_REFLEN, "%s/trash.out",tmp_dir); /* args */ init_args(&al); @@ -548,7 +549,7 @@ int stop_server(char *bin_dir __attribute__((unused)), char *mysqladmin_file, #ifndef __WIN__ pid_t get_server_pid(char *pid_file) { - char buf[PATH_MAX]; + char buf[FN_REFLEN]; int fd, err; char *p; pid_t id= 0; @@ -556,7 +557,7 @@ pid_t get_server_pid(char *pid_file) /* discover id */ fd= open(pid_file, O_RDONLY); - err= read(fd, buf, PATH_MAX); + err= read(fd, buf, FN_REFLEN); close(fd); @@ -619,7 +620,7 @@ void del_tree(char *dir) #ifndef __WIN__ DIR *parent= opendir(dir); struct dirent *entry; - char temp[PATH_MAX]; + char temp[FN_REFLEN]; if (parent == NULL) { @@ -629,22 +630,36 @@ void del_tree(char *dir) while ((entry= readdir(parent)) != NULL) { /* create long name */ - snprintf(temp, PATH_MAX, "%s/%s", dir, entry->d_name); + snprintf(temp, FN_REFLEN, "%s/%s", dir, entry->d_name); if (entry->d_name[0] == '.') { /* Skip */ } else - if (S_ISDIR(entry->d_type)) { - /* delete subdirectory */ - del_tree(temp); - } - else - { - /* remove file */ - remove(temp); +/* FIXME missing test in acinclude.m4 */ +#ifndef STRUCT_DIRENT_HAS_D_TYPE + struct stat st; + + if (lstat(entry->d_name, &st) == -1) + { + /* FIXME error */ + return; + } + if (S_ISDIR(st.st_mode)) +#else + if (S_ISDIR(entry->d_type)) +#endif + { + /* delete subdirectory */ + del_tree(temp); + } + else + { + /* remove file */ + remove(temp); + } } } /* remove directory */ @@ -652,10 +667,10 @@ void del_tree(char *dir) #else struct _finddata_t parent; intptr_t handle; - char temp[PATH_MAX]; - char mask[PATH_MAX]; + char temp[FN_REFLEN]; + char mask[FN_REFLEN]; - snprintf(mask,MAX_PATH,"%s/*.*",dir); + snprintf(mask,FN_REFLEN,"%s/*.*",dir); if ((handle=_findfirst(mask,&parent)) == -1L) { @@ -665,7 +680,7 @@ void del_tree(char *dir) do { /* create long name */ - snprintf(temp, PATH_MAX, "%s/%s", dir, parent.name); + snprintf(temp, FN_REFLEN, "%s/%s", dir, parent.name); if (parent.name[0] == '.') { /* Skip */ @@ -700,11 +715,11 @@ int removef(const char *format, ...) { #ifdef __NETWARE__ va_list ap; - char path[PATH_MAX]; + char path[FN_REFLEN]; va_start(ap, format); - vsnprintf(path, PATH_MAX, format, ap); + vsnprintf(path, FN_REFLEN, format, ap); va_end(ap); return remove(path); @@ -712,15 +727,15 @@ int removef(const char *format, ...) #eldef __WIN__ { va_list ap; - char path[PATH_MAX]; + char path[FN_REFLEN]; struct _finddata_t parent; intptr_t handle; - char temp[PATH_MAX]; + char temp[FN_REFLEN]; char *p; va_start(ap, format); - vsnprintf(path, PATH_MAX, format, ap); + vsnprintf(path, FN_REFLEN, format, ap); va_end(ap); @@ -739,7 +754,7 @@ int removef(const char *format, ...) { if (! (parent.attrib & _A_SUBDIR)) { - snprintf(temp, PATH_MAX, "%s/%s", path, parent.name); + snprintf(temp, FN_REFLEN, "%s/%s", path, parent.name); remove(temp); } }while (_findnext(handle,&parent) == 0); @@ -749,14 +764,14 @@ int removef(const char *format, ...) #else DIR *parent; struct dirent *entry; - char temp[PATH_MAX]; + char temp[FN_REFLEN]; va_list ap; - char path[PATH_MAX]; + char path[FN_REFLEN]; char *p; /* Get path with mask */ va_start(ap, format); - vsnprintf(path, PATH_MAX, format, ap); + vsnprintf(path, FN_REFLEN, format, ap); va_end(ap); @@ -775,10 +790,21 @@ int removef(const char *format, ...) while ((entry= readdir(parent)) != NULL) { /* entry is not directory and entry matches with mask */ +#ifndef STRUCT_DIRENT_HAS_D_TYPE + struct stat st; + + if (lstat(entry->d_name, &st) == -1) + { + return 1; + } + + if (!S_ISDIR(st.st_mode) && !fnmatch(p, entry->d_name,0)) +#else if (!S_ISDIR(entry->d_type) && !fnmatch(p, entry->d_name,0)) +#endif { /* create long name */ - snprintf(temp, PATH_MAX, "%s/%s", path, entry->d_name); + snprintf(temp, FN_REFLEN, "%s/%s", path, entry->d_name); /* Delete only files */ remove(temp); } @@ -795,7 +821,7 @@ int removef(const char *format, ...) void get_basedir(char *argv0, char *basedir) { - char temp[PATH_MAX]; + char temp[FN_REFLEN]; char *p; int position; diff --git a/mysql-test/my_manage.h b/mysql-test/my_manage.h index a61c693c22c..7e371d36ab1 100644 --- a/mysql-test/my_manage.h +++ b/mysql-test/my_manage.h @@ -52,8 +52,6 @@ int my_vsnprintf_(char *to, size_t n, const char* value, ...); #define TRY_MAX 5 #ifdef __WIN__ -#define PATH_MAX _MAX_PATH -#define NAME_MAX _MAX_FNAME #define kill(A,B) TerminateProcess((HANDLE)A,0) #define NOT_NEED_PID 0 #define MASTER_PID 1 diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh index 0d467e0a734..d273775725d 100644 --- a/mysql-test/mysql-test-run.sh +++ b/mysql-test/mysql-test-run.sh @@ -227,7 +227,7 @@ DO_CLIENT_GDB="" SLEEP_TIME_AFTER_RESTART=1 SLEEP_TIME_FOR_DELETE=10 SLEEP_TIME_FOR_FIRST_MASTER=400 # Enough time to create innodb tables -SLEEP_TIME_FOR_SECOND_MASTER=30 +SLEEP_TIME_FOR_SECOND_MASTER=400 SLEEP_TIME_FOR_FIRST_SLAVE=400 SLEEP_TIME_FOR_SECOND_SLAVE=30 CHARACTER_SET=latin1 @@ -457,6 +457,9 @@ SMALL_SERVER="--key_buffer_size=1M --sort_buffer=256K --max_heap_table_size=1M" export MASTER_MYPORT MASTER_MYPORT1 SLAVE_MYPORT MYSQL_TCP_PORT MASTER_MYSOCK MASTER_MYSOCK1 +NDBCLUSTER_BASE_PORT=`expr $NDBCLUSTER_PORT + 2` +NDBCLUSTER_OPTS="--port=$NDBCLUSTER_PORT --port-base=$NDBCLUSTER_BASE_PORT --data-dir=$MYSQL_TEST_DIR/var" + if [ x$SOURCE_DIST = x1 ] ; then MY_BASEDIR=$MYSQL_TEST_DIR else @@ -941,11 +944,11 @@ start_ndbcluster() echo "Starting ndbcluster" if [ "$DO_BENCH" = 1 ] then - NDBCLUSTER_OPTS="" + NDBCLUSTER_EXTRA_OPTS="" else - NDBCLUSTER_OPTS="--small" + NDBCLUSTER_EXTRA_OPTS="--small" fi - ./ndb/ndbcluster --port-base=$NDBCLUSTER_PORT $NDBCLUSTER_OPTS --diskless --initial --data-dir=$MYSQL_TEST_DIR/var || exit 1 + ./ndb/ndbcluster $NDBCLUSTER_OPTS $NDBCLUSTER_EXTRA_OPTS --diskless --initial || exit 1 NDB_CONNECTSTRING="host=localhost:$NDBCLUSTER_PORT" else NDB_CONNECTSTRING="$USE_RUNNING_NDBCLUSTER" @@ -963,7 +966,7 @@ stop_ndbcluster() if [ -z "$USE_RUNNING_NDBCLUSTER" ] then # Kill any running ndbcluster stuff - ./ndb/ndbcluster --data-dir=$MYSQL_TEST_DIR/var --port-base=$NDBCLUSTER_PORT --stop + ./ndb/ndbcluster $NDBCLUSTER_OPTS --stop fi fi } diff --git a/mysql-test/mysql_test_run_new.c b/mysql-test/mysql_test_run_new.c index 1e8a1dded51..d8bf731b398 100644 --- a/mysql-test/mysql_test_run_new.c +++ b/mysql-test/mysql_test_run_new.c @@ -73,25 +73,25 @@ const char *TEST_IGNORE= "[ignore]"; ******************************************************************************/ #ifdef __NETWARE__ -static char base_dir[PATH_MAX]= "sys:/mysql"; +static char base_dir[FN_REFLEN]= "sys:/mysql"; #else -static char base_dir[PATH_MAX]= ".."; +static char base_dir[FN_REFLEN]= ".."; #endif -static char db[PATH_MAX]= "test"; -static char user[PATH_MAX]= "root"; -static char password[PATH_MAX]= ""; +static char db[FN_LEN]= "test"; +static char user[FN_LEN]= "root"; +static char password[FN_LEN]= ""; int master_port= 9306; int slave_port= 9307; #if !defined(__NETWARE__) && !defined(__WIN__) -static char master_socket[PATH_MAX]= "./var/tmp/master.sock"; -static char slave_socket[PATH_MAX]= "./var/tmp/slave.sock"; +static char master_socket[FN_REFLEN]= "./var/tmp/master.sock"; +static char slave_socket[FN_REFLEN]= "./var/tmp/slave.sock"; #endif /* comma delimited list of tests to skip or empty string */ #ifndef __WIN__ -static char skip_test[PATH_MAX]= " lowercase_table3 , system_mysql_db_fix "; +static char skip_test[FN_REFLEN]= " lowercase_table3 , system_mysql_db_fix "; #else /* The most ignore testes contain the calls of system command @@ -110,7 +110,7 @@ static char skip_test[PATH_MAX]= " lowercase_table3 , system_mysql_db_fix "; mysqldump contains a command system rpl000001 makes non-exit loop...temporary skiped */ -static char skip_test[PATH_MAX]= +static char skip_test[FN_REFLEN]= " lowercase_table3 ," " system_mysql_db_fix ," " sp ," @@ -123,44 +123,44 @@ static char skip_test[PATH_MAX]= " mysqldump ," " rpl000001 "; #endif -static char ignore_test[PATH_MAX]= ""; - -static char bin_dir[PATH_MAX]; -static char mysql_test_dir[PATH_MAX]; -static char test_dir[PATH_MAX]; -static char mysql_tmp_dir[PATH_MAX]; -static char result_dir[PATH_MAX]; -static char master_dir[PATH_MAX]; -static char slave_dir[PATH_MAX]; -static char lang_dir[PATH_MAX]; -static char char_dir[PATH_MAX]; - -static char mysqladmin_file[PATH_MAX]; -static char mysqld_file[PATH_MAX]; -static char mysqltest_file[PATH_MAX]; +static char ignore_test[FN_REFLEN]= ""; + +static char bin_dir[FN_REFLEN]; +static char mysql_test_dir[FN_REFLEN]; +static char test_dir[FN_REFLEN]; +static char mysql_tmp_dir[FN_REFLEN]; +static char result_dir[FN_REFLEN]; +static char master_dir[FN_REFLEN]; +static char slave_dir[FN_REFLEN]; +static char lang_dir[FN_REFLEN]; +static char char_dir[FN_REFLEN]; + +static char mysqladmin_file[FN_REFLEN]; +static char mysqld_file[FN_REFLEN]; +static char mysqltest_file[FN_REFLEN]; #ifndef __WIN__ -static char master_pid[PATH_MAX]; -static char slave_pid[PATH_MAX]; -static char sh_file[PATH_MAX]= "/bin/sh"; +static char master_pid[FN_REFLEN]; +static char slave_pid[FN_REFLEN]; +static char sh_file[FN_REFLEN]= "/bin/sh"; #else static HANDLE master_pid; static HANDLE slave_pid; #endif -static char master_opt[PATH_MAX]= ""; -static char slave_opt[PATH_MAX]= ""; +static char master_opt[FN_REFLEN]= ""; +static char slave_opt[FN_REFLEN]= ""; -static char slave_master_info[PATH_MAX]= ""; +static char slave_master_info[FN_REFLEN]= ""; -static char master_init_script[PATH_MAX]= ""; -static char slave_init_script[PATH_MAX]= ""; +static char master_init_script[FN_REFLEN]= ""; +static char slave_init_script[FN_REFLEN]= ""; /* OpenSSL */ -static char ca_cert[PATH_MAX]; -static char server_cert[PATH_MAX]; -static char server_key[PATH_MAX]; -static char client_cert[PATH_MAX]; -static char client_key[PATH_MAX]; +static char ca_cert[FN_REFLEN]; +static char server_cert[FN_REFLEN]; +static char server_key[FN_REFLEN]; +static char client_cert[FN_REFLEN]; +static char client_key[FN_REFLEN]; int total_skip= 0; int total_pass= 0; @@ -254,18 +254,18 @@ void install_db(char *datadir) { arg_list_t al; int err; - char input[PATH_MAX]; - char output[PATH_MAX]; - char error[PATH_MAX]; + char input[FN_REFLEN]; + char output[FN_REFLEN]; + char error[FN_REFLEN]; /* input file */ #ifdef __NETWARE__ - snprintf(input, PATH_MAX, "%s/bin/init_db.sql", base_dir); + snprintf(input, FN_REFLEN, "%s/bin/init_db.sql", base_dir); #else - snprintf(input, PATH_MAX, "%s/mysql-test/init_db.sql", base_dir); + snprintf(input, FN_REFLEN, "%s/mysql-test/init_db.sql", base_dir); #endif - snprintf(output, PATH_MAX, "%s/install.out", datadir); - snprintf(error, PATH_MAX, "%s/install.err", datadir); + snprintf(output, FN_REFLEN, "%s/install.out", datadir); + snprintf(error, FN_REFLEN, "%s/install.err", datadir); /* args */ init_args(&al); @@ -302,10 +302,10 @@ void install_db(char *datadir) void mysql_install_db() { - char temp[PATH_MAX]; + char temp[FN_REFLEN]; /* var directory */ - snprintf(temp, PATH_MAX, "%s/var", mysql_test_dir); + snprintf(temp, FN_REFLEN, "%s/var", mysql_test_dir); /* clean up old direcotry */ del_tree(temp); @@ -315,41 +315,41 @@ void mysql_install_db() mkdir(temp, S_IRWXU); /* create subdirectories */ mlog("Creating test-suite folders...\n"); - snprintf(temp, PATH_MAX, "%s/var/run", mysql_test_dir); + snprintf(temp, FN_REFLEN, "%s/var/run", mysql_test_dir); mkdir(temp, S_IRWXU); - snprintf(temp, PATH_MAX, "%s/var/tmp", mysql_test_dir); + snprintf(temp, FN_REFLEN, "%s/var/tmp", mysql_test_dir); mkdir(temp, S_IRWXU); - snprintf(temp, PATH_MAX, "%s/var/master-data", mysql_test_dir); + snprintf(temp, FN_REFLEN, "%s/var/master-data", mysql_test_dir); mkdir(temp, S_IRWXU); - snprintf(temp, PATH_MAX, "%s/var/master-data/mysql", mysql_test_dir); + snprintf(temp, FN_REFLEN, "%s/var/master-data/mysql", mysql_test_dir); mkdir(temp, S_IRWXU); - snprintf(temp, PATH_MAX, "%s/var/master-data/test", mysql_test_dir); + snprintf(temp, FN_REFLEN, "%s/var/master-data/test", mysql_test_dir); mkdir(temp, S_IRWXU); - snprintf(temp, PATH_MAX, "%s/var/slave-data", mysql_test_dir); + snprintf(temp, FN_REFLEN, "%s/var/slave-data", mysql_test_dir); mkdir(temp, S_IRWXU); - snprintf(temp, PATH_MAX, "%s/var/slave-data/mysql", mysql_test_dir); + snprintf(temp, FN_REFLEN, "%s/var/slave-data/mysql", mysql_test_dir); mkdir(temp, S_IRWXU); - snprintf(temp, PATH_MAX, "%s/var/slave-data/test", mysql_test_dir); + snprintf(temp, FN_REFLEN, "%s/var/slave-data/test", mysql_test_dir); mkdir(temp, S_IRWXU); #else mkdir(temp); /* create subdirectories */ mlog("Creating test-suite folders...\n"); - snprintf(temp, PATH_MAX, "%s/var/run", mysql_test_dir); + snprintf(temp, FN_REFLEN, "%s/var/run", mysql_test_dir); mkdir(temp); - snprintf(temp, PATH_MAX, "%s/var/tmp", mysql_test_dir); + snprintf(temp, FN_REFLEN, "%s/var/tmp", mysql_test_dir); mkdir(temp); - snprintf(temp, PATH_MAX, "%s/var/master-data", mysql_test_dir); + snprintf(temp, FN_REFLEN, "%s/var/master-data", mysql_test_dir); mkdir(temp); - snprintf(temp, PATH_MAX, "%s/var/master-data/mysql", mysql_test_dir); + snprintf(temp, FN_REFLEN, "%s/var/master-data/mysql", mysql_test_dir); mkdir(temp); - snprintf(temp, PATH_MAX, "%s/var/master-data/test", mysql_test_dir); + snprintf(temp, FN_REFLEN, "%s/var/master-data/test", mysql_test_dir); mkdir(temp); - snprintf(temp, PATH_MAX, "%s/var/slave-data", mysql_test_dir); + snprintf(temp, FN_REFLEN, "%s/var/slave-data", mysql_test_dir); mkdir(temp); - snprintf(temp, PATH_MAX, "%s/var/slave-data/mysql", mysql_test_dir); + snprintf(temp, FN_REFLEN, "%s/var/slave-data/mysql", mysql_test_dir); mkdir(temp); - snprintf(temp, PATH_MAX, "%s/var/slave-data/test", mysql_test_dir); + snprintf(temp, FN_REFLEN, "%s/var/slave-data/test", mysql_test_dir); mkdir(temp); #endif @@ -372,10 +372,10 @@ void start_master() { arg_list_t al; int err; - char master_out[PATH_MAX]; - char master_err[PATH_MAX]; -/* char temp[PATH_MAX]; */ - char temp2[PATH_MAX]; + char master_out[FN_REFLEN]; + char master_err[FN_REFLEN]; +/* char temp[FN_REFLEN]; */ + char temp2[FN_REFLEN]; /* remove old berkeley db log files that can confuse the server */ removef("%s/log.*", master_dir); @@ -405,7 +405,7 @@ void start_master() FILE *fp; /* create an empty index file */ - snprintf(temp, PATH_MAX, "%s/test/t1.MYI", master_dir); + snprintf(temp, FN_REFLEN, "%s/test/t1.MYI", master_dir); fp= fopen(temp, "wb+"); fputs("1", fp); @@ -418,19 +418,19 @@ void start_master() } /* redirection files */ - snprintf(master_out, PATH_MAX, "%s/var/run/master%u.out", + snprintf(master_out, FN_REFLEN, "%s/var/run/master%u.out", mysql_test_dir, restarts); - snprintf(master_err, PATH_MAX, "%s/var/run/master%u.err", + snprintf(master_err, FN_REFLEN, "%s/var/run/master%u.err", mysql_test_dir, restarts); #ifndef __WIN__ - snprintf(temp2,PATH_MAX,"%s/var",mysql_test_dir); + snprintf(temp2,FN_REFLEN,"%s/var",mysql_test_dir); mkdir(temp2,S_IRWXU); - snprintf(temp2,PATH_MAX,"%s/var/log",mysql_test_dir); + snprintf(temp2,FN_REFLEN,"%s/var/log",mysql_test_dir); mkdir(temp2,S_IRWXU); #else - snprintf(temp2,PATH_MAX,"%s/var",mysql_test_dir); + snprintf(temp2,FN_REFLEN,"%s/var",mysql_test_dir); mkdir(temp2); - snprintf(temp2,PATH_MAX,"%s/var/log",mysql_test_dir); + snprintf(temp2,FN_REFLEN,"%s/var/log",mysql_test_dir); mkdir(temp2); #endif /* args */ @@ -539,8 +539,8 @@ void start_slave() { arg_list_t al; int err; - char slave_out[PATH_MAX]; - char slave_err[PATH_MAX]; + char slave_out[FN_REFLEN]; + char slave_err[FN_REFLEN]; /* skip? */ if (skip_slave) return; @@ -568,7 +568,7 @@ void start_slave() if (strinstr(slave_init_script, "rpl000016-slave.sh") != 0) { /* create empty master.info file */ - snprintf(temp, PATH_MAX, "%s/master.info", slave_dir); + snprintf(temp, FN_REFLEN, "%s/master.info", slave_dir); close(open(temp, O_WRONLY | O_CREAT,S_IRWXU|S_IRWXG|S_IRWXO)); } else if (strinstr(slave_init_script, "rpl000017-slave.sh") != 0) @@ -576,7 +576,7 @@ void start_slave() FILE *fp; /* create a master.info file */ - snprintf(temp, PATH_MAX, "%s/master.info", slave_dir); + snprintf(temp, FN_REFLEN, "%s/master.info", slave_dir); fp= fopen(temp, "wb+"); fputs("master-bin.000001\n", fp); @@ -593,7 +593,7 @@ void start_slave() else if (strinstr(slave_init_script, "rpl_rotate_logs-slave.sh") != 0) { /* create empty master.info file */ - snprintf(temp, PATH_MAX, "%s/master.info", slave_dir); + snprintf(temp, FN_REFLEN, "%s/master.info", slave_dir); close(open(temp, O_WRONLY | O_CREAT,S_IRWXU|S_IRWXG|S_IRWXO)); } #elif !defined(__WIN__) @@ -602,9 +602,9 @@ void start_slave() } /* redirection files */ - snprintf(slave_out, PATH_MAX, "%s/var/run/slave%u.out", + snprintf(slave_out, FN_REFLEN, "%s/var/run/slave%u.out", mysql_test_dir, restarts); - snprintf(slave_err, PATH_MAX, "%s/var/run/slave%u.err", + snprintf(slave_err, FN_REFLEN, "%s/var/run/slave%u.err", mysql_test_dir, restarts); /* args */ @@ -859,14 +859,14 @@ int read_option(char *opt_file, char *opt) { int fd, err; char *p; - char buf[PATH_MAX]; + char buf[FN_REFLEN]; /* copy current option */ - strncpy(buf, opt, PATH_MAX); + strncpy(buf, opt, FN_REFLEN); /* open options file */ fd= open(opt_file, O_RDONLY); - err= read(fd, opt, PATH_MAX); + err= read(fd, opt, FN_REFLEN); close(fd); if (err > 0) @@ -890,7 +890,7 @@ int read_option(char *opt_file, char *opt) /* check for $MYSQL_TEST_DIR */ if ((p= strstr(opt, "$MYSQL_TEST_DIR")) != NULL) { - char temp[PATH_MAX]; + char temp[FN_REFLEN]; *p= 0; @@ -925,7 +925,7 @@ int read_option(char *opt_file, char *opt) void run_test(char *test) { - char temp[PATH_MAX]; + char temp[FN_REFLEN]; const char *rstr; int skip= FALSE, ignore=FALSE; int restart= FALSE; @@ -933,13 +933,13 @@ void run_test(char *test) struct stat info; /* skip tests in the skip list */ - snprintf(temp, PATH_MAX, " %s ", test); + snprintf(temp, FN_REFLEN, " %s ", test); skip= (strinstr(skip_test, temp) != 0); if (skip == FALSE) ignore= (strinstr(ignore_test, temp) != 0); - snprintf(master_init_script, PATH_MAX, "%s/%s-master.sh", test_dir, test); - snprintf(slave_init_script, PATH_MAX, "%s/%s-slave.sh", test_dir, test); + snprintf(master_init_script, FN_REFLEN, "%s/%s-master.sh", test_dir, test); + snprintf(slave_init_script, FN_REFLEN, "%s/%s-slave.sh", test_dir, test); #ifdef __WIN__ if (! stat(master_init_script, &info)) skip= TRUE; @@ -957,14 +957,14 @@ void run_test(char *test) } else if (!skip) /* skip test? */ { - char test_file[PATH_MAX]; - char master_opt_file[PATH_MAX]; - char slave_opt_file[PATH_MAX]; - char slave_master_info_file[PATH_MAX]; - char result_file[PATH_MAX]; - char reject_file[PATH_MAX]; - char out_file[PATH_MAX]; - char err_file[PATH_MAX]; + char test_file[FN_REFLEN]; + char master_opt_file[FN_REFLEN]; + char slave_opt_file[FN_REFLEN]; + char slave_master_info_file[FN_REFLEN]; + char result_file[FN_REFLEN]; + char reject_file[FN_REFLEN]; + char out_file[FN_REFLEN]; + char err_file[FN_REFLEN]; int err; arg_list_t al; #ifdef __WIN__ @@ -981,20 +981,20 @@ void run_test(char *test) if (flag != skip_slave) restart= TRUE; /* create files */ - snprintf(master_opt_file, PATH_MAX, "%s/%s-master.opt", test_dir, test); - snprintf(slave_opt_file, PATH_MAX, "%s/%s-slave.opt", test_dir, test); - snprintf(slave_master_info_file, PATH_MAX, "%s/%s.slave-mi", + snprintf(master_opt_file, FN_REFLEN, "%s/%s-master.opt", test_dir, test); + snprintf(slave_opt_file, FN_REFLEN, "%s/%s-slave.opt", test_dir, test); + snprintf(slave_master_info_file, FN_REFLEN, "%s/%s.slave-mi", test_dir, test); - snprintf(reject_file, PATH_MAX, "%s/%s%s", + snprintf(reject_file, FN_REFLEN, "%s/%s%s", result_dir, test, REJECT_SUFFIX); - snprintf(out_file, PATH_MAX, "%s/%s%s", result_dir, test, OUT_SUFFIX); - snprintf(err_file, PATH_MAX, "%s/%s%s", result_dir, test, ERR_SUFFIX); + snprintf(out_file, FN_REFLEN, "%s/%s%s", result_dir, test, OUT_SUFFIX); + snprintf(err_file, FN_REFLEN, "%s/%s%s", result_dir, test, ERR_SUFFIX); /* netware specific files */ - snprintf(test_file, PATH_MAX, "%s/%s%s", test_dir, test, NW_TEST_SUFFIX); + snprintf(test_file, FN_REFLEN, "%s/%s%s", test_dir, test, NW_TEST_SUFFIX); if (stat(test_file, &info)) { - snprintf(test_file, PATH_MAX, "%s/%s%s", test_dir, test, TEST_SUFFIX); + snprintf(test_file, FN_REFLEN, "%s/%s%s", test_dir, test, TEST_SUFFIX); if (access(test_file,0)) { printf("Invalid test name %s, %s file not found\n",test,test_file); @@ -1002,11 +1002,11 @@ void run_test(char *test) } } - snprintf(result_file, PATH_MAX, "%s/%s%s", + snprintf(result_file, FN_REFLEN, "%s/%s%s", result_dir, test, NW_RESULT_SUFFIX); if (stat(result_file, &info)) { - snprintf(result_file, PATH_MAX, "%s/%s%s", + snprintf(result_file, FN_REFLEN, "%s/%s%s", result_dir, test, RESULT_SUFFIX); } @@ -1248,8 +1248,8 @@ void die(const char *msg) void setup(char *file __attribute__((unused))) { - char temp[PATH_MAX]; - char file_path[PATH_MAX*2]; + char temp[FN_REFLEN]; + char file_path[FN_REFLEN*2]; char *p; int position; @@ -1257,14 +1257,14 @@ void setup(char *file __attribute__((unused))) #ifdef __WIN__ _putenv( "TZ=GMT-3" ); #else - setenv("TZ", "GMT-3", TRUE); + putenv((char *)"TZ=GMT-3"); #endif /* find base dir */ #ifdef __NETWARE__ strcpy(temp, strlwr(file)); while ((p= strchr(temp, '\\')) != NULL) *p= '/'; #else - getcwd(temp, PATH_MAX); + getcwd(temp, FN_REFLEN); position= strlen(temp); temp[position]= '/'; temp[position+1]= 0; @@ -1284,100 +1284,100 @@ void setup(char *file __attribute__((unused))) #ifdef __NETWARE__ /* setup paths */ - snprintf(bin_dir, PATH_MAX, "%s/bin", base_dir); - snprintf(mysql_test_dir, PATH_MAX, "%s/mysql-test", base_dir); - snprintf(test_dir, PATH_MAX, "%s/t", mysql_test_dir); - snprintf(mysql_tmp_dir, PATH_MAX, "%s/var/tmp", mysql_test_dir); - snprintf(result_dir, PATH_MAX, "%s/r", mysql_test_dir); - snprintf(master_dir, PATH_MAX, "%s/var/master-data", mysql_test_dir); - snprintf(slave_dir, PATH_MAX, "%s/var/slave-data", mysql_test_dir); - snprintf(lang_dir, PATH_MAX, "%s/share/english", base_dir); - snprintf(char_dir, PATH_MAX, "%s/share/charsets", base_dir); + snprintf(bin_dir, FN_REFLEN, "%s/bin", base_dir); + snprintf(mysql_test_dir, FN_REFLEN, "%s/mysql-test", base_dir); + snprintf(test_dir, FN_REFLEN, "%s/t", mysql_test_dir); + snprintf(mysql_tmp_dir, FN_REFLEN, "%s/var/tmp", mysql_test_dir); + snprintf(result_dir, FN_REFLEN, "%s/r", mysql_test_dir); + snprintf(master_dir, FN_REFLEN, "%s/var/master-data", mysql_test_dir); + snprintf(slave_dir, FN_REFLEN, "%s/var/slave-data", mysql_test_dir); + snprintf(lang_dir, FN_REFLEN, "%s/share/english", base_dir); + snprintf(char_dir, FN_REFLEN, "%s/share/charsets", base_dir); #ifdef HAVE_OPENSSL use_openssl= TRUE; #endif /* HAVE_OPENSSL */ /* OpenSSL paths */ - snprintf(ca_cert, PATH_MAX, "%s/SSL/cacert.pem", base_dir); - snprintf(server_cert, PATH_MAX, "%s/SSL/server-cert.pem", base_dir); - snprintf(server_key, PATH_MAX, "%s/SSL/server-key.pem", base_dir); - snprintf(client_cert, PATH_MAX, "%s/SSL/client-cert.pem", base_dir); - snprintf(client_key, PATH_MAX, "%s/SSL/client-key.pem", base_dir); + snprintf(ca_cert, FN_REFLEN, "%s/SSL/cacert.pem", base_dir); + snprintf(server_cert, FN_REFLEN, "%s/SSL/server-cert.pem", base_dir); + snprintf(server_key, FN_REFLEN, "%s/SSL/server-key.pem", base_dir); + snprintf(client_cert, FN_REFLEN, "%s/SSL/client-cert.pem", base_dir); + snprintf(client_key, FN_REFLEN, "%s/SSL/client-key.pem", base_dir); /* setup files */ - snprintf(mysqld_file, PATH_MAX, "%s/mysqld", bin_dir); - snprintf(mysqltest_file, PATH_MAX, "%s/mysqltest", bin_dir); - snprintf(mysqladmin_file, PATH_MAX, "%s/mysqladmin", bin_dir); - snprintf(master_pid, PATH_MAX, "%s/var/run/master.pid", mysql_test_dir); - snprintf(slave_pid, PATH_MAX, "%s/var/run/slave.pid", mysql_test_dir); + snprintf(mysqld_file, FN_REFLEN, "%s/mysqld", bin_dir); + snprintf(mysqltest_file, FN_REFLEN, "%s/mysqltest", bin_dir); + snprintf(mysqladmin_file, FN_REFLEN, "%s/mysqladmin", bin_dir); + snprintf(master_pid, FN_REFLEN, "%s/var/run/master.pid", mysql_test_dir); + snprintf(slave_pid, FN_REFLEN, "%s/var/run/slave.pid", mysql_test_dir); #elif __WIN__ /* setup paths */ #ifdef _DEBUG - snprintf(bin_dir, PATH_MAX, "%s/client_debug", base_dir); + snprintf(bin_dir, FN_REFLEN, "%s/client_debug", base_dir); #else - snprintf(bin_dir, PATH_MAX, "%s/client_release", base_dir); + snprintf(bin_dir, FN_REFLEN, "%s/client_release", base_dir); #endif - snprintf(mysql_test_dir, PATH_MAX, "%s/mysql-test", base_dir); - snprintf(test_dir, PATH_MAX, "%s/t", mysql_test_dir); - snprintf(mysql_tmp_dir, PATH_MAX, "%s/var/tmp", mysql_test_dir); - snprintf(result_dir, PATH_MAX, "%s/r", mysql_test_dir); - snprintf(master_dir, PATH_MAX, "%s/var/master-data", mysql_test_dir); - snprintf(slave_dir, PATH_MAX, "%s/var/slave-data", mysql_test_dir); - snprintf(lang_dir, PATH_MAX, "%s/share/english", base_dir); - snprintf(char_dir, PATH_MAX, "%s/share/charsets", base_dir); + snprintf(mysql_test_dir, FN_REFLEN, "%s/mysql-test", base_dir); + snprintf(test_dir, FN_REFLEN, "%s/t", mysql_test_dir); + snprintf(mysql_tmp_dir, FN_REFLEN, "%s/var/tmp", mysql_test_dir); + snprintf(result_dir, FN_REFLEN, "%s/r", mysql_test_dir); + snprintf(master_dir, FN_REFLEN, "%s/var/master-data", mysql_test_dir); + snprintf(slave_dir, FN_REFLEN, "%s/var/slave-data", mysql_test_dir); + snprintf(lang_dir, FN_REFLEN, "%s/share/english", base_dir); + snprintf(char_dir, FN_REFLEN, "%s/share/charsets", base_dir); #ifdef HAVE_OPENSSL use_openssl= TRUE; #endif /* HAVE_OPENSSL */ /* OpenSSL paths */ - snprintf(ca_cert, PATH_MAX, "%s/SSL/cacert.pem", base_dir); - snprintf(server_cert, PATH_MAX, "%s/SSL/server-cert.pem", base_dir); - snprintf(server_key, PATH_MAX, "%s/SSL/server-key.pem", base_dir); - snprintf(client_cert, PATH_MAX, "%s/SSL/client-cert.pem", base_dir); - snprintf(client_key, PATH_MAX, "%s/SSL/client-key.pem", base_dir); + snprintf(ca_cert, FN_REFLEN, "%s/SSL/cacert.pem", base_dir); + snprintf(server_cert, FN_REFLEN, "%s/SSL/server-cert.pem", base_dir); + snprintf(server_key, FN_REFLEN, "%s/SSL/server-key.pem", base_dir); + snprintf(client_cert, FN_REFLEN, "%s/SSL/client-cert.pem", base_dir); + snprintf(client_key, FN_REFLEN, "%s/SSL/client-key.pem", base_dir); /* setup files */ - snprintf(mysqld_file, PATH_MAX, "%s/mysqld.exe", bin_dir); - snprintf(mysqltest_file, PATH_MAX, "%s/mysqltest.exe", bin_dir); - snprintf(mysqladmin_file, PATH_MAX, "%s/mysqladmin.exe", bin_dir); + snprintf(mysqld_file, FN_REFLEN, "%s/mysqld.exe", bin_dir); + snprintf(mysqltest_file, FN_REFLEN, "%s/mysqltest.exe", bin_dir); + snprintf(mysqladmin_file, FN_REFLEN, "%s/mysqladmin.exe", bin_dir); #else /* setup paths */ - snprintf(bin_dir, PATH_MAX, "%s/client", base_dir); - snprintf(mysql_test_dir, PATH_MAX, "%s/mysql-test", base_dir); - snprintf(test_dir, PATH_MAX, "%s/t", mysql_test_dir); - snprintf(mysql_tmp_dir, PATH_MAX, "%s/var/tmp", mysql_test_dir); - snprintf(result_dir, PATH_MAX, "%s/r", mysql_test_dir); - snprintf(master_dir, PATH_MAX, "%s/var/master-data", mysql_test_dir); - snprintf(slave_dir, PATH_MAX, "%s/var/slave-data", mysql_test_dir); - snprintf(lang_dir, PATH_MAX, "%s/sql/share/english", base_dir); - snprintf(char_dir, PATH_MAX, "%s/sql/share/charsets", base_dir); + snprintf(bin_dir, FN_REFLEN, "%s/client", base_dir); + snprintf(mysql_test_dir, FN_REFLEN, "%s/mysql-test", base_dir); + snprintf(test_dir, FN_REFLEN, "%s/t", mysql_test_dir); + snprintf(mysql_tmp_dir, FN_REFLEN, "%s/var/tmp", mysql_test_dir); + snprintf(result_dir, FN_REFLEN, "%s/r", mysql_test_dir); + snprintf(master_dir, FN_REFLEN, "%s/var/master-data", mysql_test_dir); + snprintf(slave_dir, FN_REFLEN, "%s/var/slave-data", mysql_test_dir); + snprintf(lang_dir, FN_REFLEN, "%s/sql/share/english", base_dir); + snprintf(char_dir, FN_REFLEN, "%s/sql/share/charsets", base_dir); #ifdef HAVE_OPENSSL use_openssl= TRUE; #endif /* HAVE_OPENSSL */ /* OpenSSL paths */ - snprintf(ca_cert, PATH_MAX, "%s/SSL/cacert.pem", base_dir); - snprintf(server_cert, PATH_MAX, "%s/SSL/server-cert.pem", base_dir); - snprintf(server_key, PATH_MAX, "%s/SSL/server-key.pem", base_dir); - snprintf(client_cert, PATH_MAX, "%s/SSL/client-cert.pem", base_dir); - snprintf(client_key, PATH_MAX, "%s/SSL/client-key.pem", base_dir); + snprintf(ca_cert, FN_REFLEN, "%s/SSL/cacert.pem", base_dir); + snprintf(server_cert, FN_REFLEN, "%s/SSL/server-cert.pem", base_dir); + snprintf(server_key, FN_REFLEN, "%s/SSL/server-key.pem", base_dir); + snprintf(client_cert, FN_REFLEN, "%s/SSL/client-cert.pem", base_dir); + snprintf(client_key, FN_REFLEN, "%s/SSL/client-key.pem", base_dir); /* setup files */ - snprintf(mysqld_file, PATH_MAX, "%s/sql/mysqld", base_dir); - snprintf(mysqltest_file, PATH_MAX, "%s/mysqltest", bin_dir); - snprintf(mysqladmin_file, PATH_MAX, "%s/mysqladmin", bin_dir); - snprintf(master_pid, PATH_MAX, "%s/var/run/master.pid", mysql_test_dir); - snprintf(slave_pid, PATH_MAX, "%s/var/run/slave.pid", mysql_test_dir); + snprintf(mysqld_file, FN_REFLEN, "%s/sql/mysqld", base_dir); + snprintf(mysqltest_file, FN_REFLEN, "%s/mysqltest", bin_dir); + snprintf(mysqladmin_file, FN_REFLEN, "%s/mysqladmin", bin_dir); + snprintf(master_pid, FN_REFLEN, "%s/var/run/master.pid", mysql_test_dir); + snprintf(slave_pid, FN_REFLEN, "%s/var/run/slave.pid", mysql_test_dir); - snprintf(master_socket,PATH_MAX, "%s/var/tmp/master.sock", mysql_test_dir); - snprintf(slave_socket,PATH_MAX, "%s/var/tmp/slave.sock", mysql_test_dir); + snprintf(master_socket,FN_REFLEN, "%s/var/tmp/master.sock", mysql_test_dir); + snprintf(slave_socket,FN_REFLEN, "%s/var/tmp/slave.sock", mysql_test_dir); #endif /* create log file */ - snprintf(temp, PATH_MAX, "%s/mysql-test-run.log", mysql_test_dir); + snprintf(temp, FN_REFLEN, "%s/mysql-test-run.log", mysql_test_dir); if ((log_fd= fopen(temp, "w+")) == NULL) { log_errno("Unable to create log file."); @@ -1386,46 +1386,47 @@ void setup(char *file __attribute__((unused))) /* prepare skip test list */ while ((p= strchr(skip_test, ',')) != NULL) *p= ' '; strcpy(temp, strlwr(skip_test)); - snprintf(skip_test, PATH_MAX, " %s ", temp); + snprintf(skip_test, FN_REFLEN, " %s ", temp); /* environment */ #ifdef __NETWARE__ setenv("MYSQL_TEST_DIR", mysql_test_dir, 1); - snprintf(file_path, PATH_MAX*2, + snprintf(file_path, FN_REFLEN*2, "%s/client/mysqldump --no-defaults -u root --port=%u", bin_dir, master_port); setenv("MYSQL_DUMP", file_path, 1); - snprintf(file_path, PATH_MAX*2, + snprintf(file_path, FN_REFLEN*2, "%s/client/mysqlbinlog --no-defaults --local-load=%s", bin_dir, mysql_tmp_dir); setenv("MYSQL_BINLOG", file_path, 1); #elif __WIN__ - snprintf(file_path,MAX_PATH,"MYSQL_TEST_DIR=%s",mysql_test_dir); + snprintf(file_path,FN_REFLEN,"MYSQL_TEST_DIR=%s",mysql_test_dir); _putenv(file_path); - snprintf(file_path, PATH_MAX*2, + snprintf(file_path, FN_REFLEN*2, "MYSQL_DUMP=%s/mysqldump.exe --no-defaults -u root --port=%u", bin_dir, master_port); _putenv(file_path); - snprintf(file_path, PATH_MAX*2, + snprintf(file_path, FN_REFLEN*2, "MYSQL_BINLOG=%s/mysqlbinlog.exe --no-defaults --local-load=%s", bin_dir, mysql_tmp_dir); _putenv(file_path); #else - setenv("MYSQL_TEST_DIR", mysql_test_dir, 1); - snprintf(file_path, PATH_MAX*2, - "%s/mysqldump --no-defaults -u root --port=%u --socket=%s", + snprintf(file_path,FN_REFLEN,"MYSQL_TEST_DIR=%s",mysql_test_dir); + putenv(file_path); + snprintf(file_path, FN_REFLEN*2, + "MYSQL_DUMP=%s/mysqldump --no-defaults -u root --port=%u --socket=%s", bin_dir, master_port, master_socket); - setenv("MYSQL_DUMP", file_path, 1); - snprintf(file_path, PATH_MAX*2, - "%s/mysqlbinlog --no-defaults --local-load=%s", + putenv(file_path); + snprintf(file_path, FN_REFLEN*2, + "MYSQL_BINLOG=%s/mysqlbinlog --no-defaults --local-load=%s", bin_dir, mysql_tmp_dir); - setenv("MYSQL_BINLOG", file_path, 1); + putenv(file_path); #endif #ifndef __WIN__ - setenv("MASTER_MYPORT", "9306", 1); - setenv("SLAVE_MYPORT", "9307", 1); - setenv("MYSQL_TCP_PORT", "3306", 1); + putenv((char *)"MASTER_MYPORT=9306"); + putenv((char *)"SLAVE_MYPORT=9307"); + putenv((char *)"MYSQL_TCP_PORT=3306"); #else _putenv("MASTER_MYPORT=9306"); _putenv("SLAVE_MYPORT=9307"); @@ -1461,7 +1462,7 @@ int main(int argc, char **argv) temp= strdup(strchr(argv[1],'=') + 1); for (token=str_tok(temp, ","); token != NULL; token=str_tok(NULL, ",")) { - if (strlen(ignore_test) + strlen(token) + 2 <= PATH_MAX-1) + if (strlen(ignore_test) + strlen(token) + 2 <= FN_REFLEN-1) sprintf(ignore_test+strlen(ignore_test), " %s ", token); else { @@ -1507,38 +1508,35 @@ int main(int argc, char **argv) { /* run all tests */ #ifndef __WIN__ - struct dirent **namelist; - int i,n; - char test[NAME_MAX]; - char *p; + struct dirent *entry; + DIR *parent; + char test[FN_LEN]; int position; - n= scandir(test_dir, &namelist, 0, alphasort); - if (n < 0) + /* FIXME are we sure the list is sorted if using readdir()? */ + if ((parent= opendir(test_dir)) == NULL) /* Not thread safe */ die("Unable to open tests directory."); else { - for (i= 0; i < n; i++) + while ((entry= readdir(parent)) != NULL) /* Not thread safe */ { - strcpy(test, strlwr(namelist[i]->d_name)); + strcpy(test, strlwr(entry->d_name)); /* find the test suffix */ if ((position= strinstr(test, TEST_SUFFIX)) != 0) { - p= test + position - 1; /* null terminate at the suffix */ - *p= 0; + *(test + position - 1)= '\0'; /* run test */ run_test(test); } - free(namelist[n]); } - free(namelist); + closedir(parent); } #else struct _finddata_t dir; intptr_t handle; - char test[NAME_MAX]; - char mask[PATH_MAX]; + char test[FN_LEN]; + char mask[FN_REFLEN]; char *p; int position; char **names= 0; @@ -1549,7 +1547,7 @@ int main(int argc, char **argv) /* single test */ single_test= FALSE; - snprintf(mask,MAX_PATH,"%s/*.test",test_dir); + snprintf(mask,FN_REFLEN,"%s/*.test",test_dir); if ((handle=_findfirst(mask,&dir)) == -1L) { @@ -1574,7 +1572,7 @@ int main(int argc, char **argv) *p= 0; /* insert test */ - *names= malloc(PATH_MAX); + *names= malloc(FN_REFLEN); strcpy(*names,test); names++; name_index++; diff --git a/mysql-test/ndb/Makefile.am b/mysql-test/ndb/Makefile.am index 3ed222344a6..502ccee099e 100644 --- a/mysql-test/ndb/Makefile.am +++ b/mysql-test/ndb/Makefile.am @@ -13,6 +13,8 @@ SUFFIXES = .sh .sh: @RM@ -f $@ $@-t @SED@ \ + -e 's!@''ndb_port''@!$(ndb_port)!g' \ + -e 's!@''ndb_port_base''@!$(ndb_port_base)!g' \ -e 's!@''ndbbindir''@!$(ndbbindir)!g' \ -e 's!@''ndbtoolsdir''@!$(ndbtoolsdir)!g' \ $< > $@-t diff --git a/mysql-test/ndb/ndbcluster.sh b/mysql-test/ndb/ndbcluster.sh index 9c6b6093b93..60188705857 100644 --- a/mysql-test/ndb/ndbcluster.sh +++ b/mysql-test/ndb/ndbcluster.sh @@ -5,7 +5,8 @@ # This scripts starts the table handler ndbcluster # configurable parameters, make sure to change in mysqlcluterd as well -port_base="2200" +port=@ndb_port@ +port_base=@ndb_port_base@ fsdir=`pwd` # end configurable parameters @@ -22,6 +23,7 @@ if [ -d ../sql ] ; then exec_ndb=$ndbtop/src/kernel/ndbd exec_mgmtsrvr=$ndbtop/src/mgmsrv/ndb_mgmd exec_waiter=$ndbtop/tools/ndb_waiter + exec_test=$ndbtop/tools/ndb_test_platform exec_mgmtclient=$ndbtop/src/mgmclient/ndb_mgm else BINARY_DIST=1 @@ -34,9 +36,15 @@ else exec_mgmtsrvr=$BASEDIR/bin/ndb_mgmd fi exec_waiter=$BASEDIR/bin/ndb_waiter + exec_test=$BASEDIR/bin/ndb_test_platform exec_mgmtclient=$BASEDIR/bin/ndb_mgm fi +if $exec_test ; then :; else + echo "ndb not correctly compiled to support this platform" + exit 1 +fi + pidfile=ndbcluster.pid cfgfile=Ndb.cfg stop_ndb= @@ -77,6 +85,9 @@ while test $# -gt 0; do --data-dir=*) fsdir=`echo "$1" | sed -e "s;--data-dir=;;"` ;; + --port=*) + port=`echo "$1" | sed -e "s;--port=;;"` + ;; --port-base=*) port_base=`echo "$1" | sed -e "s;--port-base=;;"` ;; @@ -87,7 +98,7 @@ while test $# -gt 0; do shift done -fs_ndb="$fsdir/ndbcluster-$port_base" +fs_ndb="$fsdir/ndbcluster-$port" NDB_HOME= if [ ! -x "$fsdir" ]; then @@ -113,7 +124,7 @@ exec_ndb="$exec_ndb --no-defaults" exec_waiter="$exec_waiter --no-defaults" ndb_host="localhost" -ndb_mgmd_port=$port_base +ndb_mgmd_port=$port NDB_CONNECTSTRING="host=$ndb_host:$ndb_mgmd_port" export NDB_CONNECTSTRING @@ -151,10 +162,6 @@ if [ -d "$fs_ndb" ]; then :; else exit 1 fi -# set som help variables - -port_transporter=`expr $ndb_mgmd_port + 2` - # Start management server as deamon # Edit file system path and ports in config file @@ -169,7 +176,7 @@ sed \ -e s,"CHOOSE_HOSTNAME_".*,"$ndb_host",g \ -e s,"CHOOSE_FILESYSTEM","$fs_ndb",g \ -e s,"CHOOSE_PORT_MGM","$ndb_mgmd_port",g \ - -e s,"CHOOSE_PORT_TRANSPORTER","$port_transporter",g \ + -e s,"CHOOSE_PORT_TRANSPORTER","$port_base",g \ < ndb/ndb_config_2_node.ini \ > "$fs_ndb/config.ini" fi diff --git a/mysql-test/r/alter_table.result b/mysql-test/r/alter_table.result index f26ca4a5425..e0d484312e7 100644 --- a/mysql-test/r/alter_table.result +++ b/mysql-test/r/alter_table.result @@ -483,3 +483,13 @@ ERROR 42000: Incorrect table name 't1\\' rename table t1 to `t1\\`; ERROR 42000: Incorrect table name 't1\\' drop table t1; +create table t1 (a text) character set koi8r; +insert into t1 values (_koi8r'ÔÅÓÔ'); +select hex(a) from t1; +hex(a) +D4C5D3D4 +alter table t1 convert to character set cp1251; +select hex(a) from t1; +hex(a) +F2E5F1F2 +drop table t1; diff --git a/mysql-test/r/consistent_snapshot.result b/mysql-test/r/consistent_snapshot.result new file mode 100644 index 00000000000..90606abbe4e --- /dev/null +++ b/mysql-test/r/consistent_snapshot.result @@ -0,0 +1,15 @@ +drop table if exists t1; +create table t1 (a int) engine=innodb; +start transaction with consistent snapshot; +insert into t1 values(1); +select * from t1; +a +commit; +delete from t1; +start transaction; +insert into t1 values(1); +select * from t1; +a +1 +commit; +drop table t1; diff --git a/mysql-test/r/ctype_ujis.result b/mysql-test/r/ctype_ujis.result index 7c3ae52cbc9..d02ac0062f8 100644 --- a/mysql-test/r/ctype_ujis.result +++ b/mysql-test/r/ctype_ujis.result @@ -126,3 +126,43 @@ Field Type Null Key Default Extra a char(1) b enum('¤¢','¤¤') YES NULL DROP TABLE t1; +CREATE TABLE t1 +( +a INTEGER NOT NULL, +b VARCHAR(50) NOT NULL DEFAULT '', +PRIMARY KEY (a), +KEY b (b(10)) +) TYPE=InnoDB CHARACTER SET 'ujis' COLLATE 'ujis_japanese_ci'; +INSERT INTO t1 (a, b) VALUES (0, 'aaabbbcccddd'); +INSERT INTO t1 (a, b) VALUES (1, 'eeefffggghhh'); +INSERT INTO t1 (a, b) VALUES (2, 'iiijjjkkkl'); +SELECT t1.* FROM t1 WHERE b='aaabbbcccddd' ORDER BY a; +a b +0 aaabbbcccddd +SELECT t1.* FROM t1 WHERE b='eeefffggghhh' ORDER BY a; +a b +1 eeefffggghhh +SELECT t1.* FROM t1 WHERE b='iiijjjkkkl' ORDER BY a; +a b +2 iiijjjkkkl +DROP TABLE t1; +CREATE TABLE t1 +( +a INTEGER NOT NULL, +b VARCHAR(50) NOT NULL DEFAULT '', +PRIMARY KEY (a), +KEY b (b(10)) +) TYPE=MyISAM CHARACTER SET 'ujis' COLLATE 'ujis_japanese_ci'; +INSERT INTO t1 (a, b) VALUES (0, 'aaabbbcccddd'); +INSERT INTO t1 (a, b) VALUES (1, 'eeefffggghhh'); +INSERT INTO t1 (a, b) VALUES (2, 'iiijjjkkkl'); +SELECT t1.* FROM t1 WHERE b='aaabbbcccddd' ORDER BY a; +a b +0 aaabbbcccddd +SELECT t1.* FROM t1 WHERE b='eeefffggghhh' ORDER BY a; +a b +1 eeefffggghhh +SELECT t1.* FROM t1 WHERE b='iiijjjkkkl' ORDER BY a; +a b +2 iiijjjkkkl +DROP TABLE t1; diff --git a/mysql-test/r/metadata.result b/mysql-test/r/metadata.result index ced3ca61f80..2321a8998ac 100644 --- a/mysql-test/r/metadata.result +++ b/mysql-test/r/metadata.result @@ -5,7 +5,7 @@ def 1 8 1 1 N 32769 0 8 def 1.0 5 3 3 N 32769 1 8 def -1 8 1 2 N 32769 0 8 def hello 254 5 5 N 1 31 8 -def NULL 6 0 0 Y 32768 0 8 +def NULL 6 0 0 Y 32896 0 63 1 1.0 -1 hello NULL 1 1.0 -1 hello NULL create table t1 (a tinyint, b smallint, c mediumint, d int, e bigint, f float(3,2), g double(4,3), h decimal(5,4), i year, j date, k timestamp, l datetime, m enum('a','b'), n set('a','b'), o char(10)); diff --git a/mysql-test/r/ndb_autodiscover.result b/mysql-test/r/ndb_autodiscover.result index 4925aac8ac1..82ff4072378 100644 --- a/mysql-test/r/ndb_autodiscover.result +++ b/mysql-test/r/ndb_autodiscover.result @@ -1,4 +1,4 @@ -drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9,t10; flush status; create table t1( id int not null primary key, @@ -363,3 +363,8 @@ a int NOT NULL PRIMARY KEY, b int ) engine=ndb; insert t9 values(1, 2), (2,3), (3, 4), (4, 5); +create table t10 ( +a int not null primary key, +b blob +) engine=ndb; +insert into t10 values (1, 'kalle'); diff --git a/mysql-test/r/ndb_autodiscover2.result b/mysql-test/r/ndb_autodiscover2.result index 08803d997a5..91f018b5d02 100644 --- a/mysql-test/r/ndb_autodiscover2.result +++ b/mysql-test/r/ndb_autodiscover2.result @@ -8,3 +8,6 @@ show status like 'handler_discover%'; Variable_name Value Handler_discover 1 drop table t9; +select * from t10; +ERROR HY000: Got error 4263 'Invalid blob attributes or invalid blob parts table' from ndbcluster +drop table t10; diff --git a/mysql-test/r/ndb_basic.result b/mysql-test/r/ndb_basic.result index ba8ee820ad9..6ec5338acbe 100644 --- a/mysql-test/r/ndb_basic.result +++ b/mysql-test/r/ndb_basic.result @@ -400,6 +400,13 @@ b attr1 9413 9412 drop table test.t1, t2; drop database mysqltest; +drop database if exists ndbtest1; +create database ndbtest1; +use ndbtest1; +create table t1(id int) engine=ndbcluster; +drop database ndbtest1; +drop database ndbtest1; +ERROR HY000: Can't drop database 'ndbtest1'; database doesn't exist use test; create table t1 (a int primary key, b char(0)); insert into t1 values (1,""); diff --git a/mysql-test/r/ndb_index_ordered.result b/mysql-test/r/ndb_index_ordered.result index 2dc260ec43d..50f904af750 100644 --- a/mysql-test/r/ndb_index_ordered.result +++ b/mysql-test/r/ndb_index_ordered.result @@ -1,4 +1,4 @@ -drop table if exists t1; +drop table if exists t1, test1, test2; CREATE TABLE t1 ( a int unsigned NOT NULL PRIMARY KEY, b int unsigned not null, @@ -275,3 +275,38 @@ a b c 1 1 1 4 4 NULL drop table t1; +CREATE TABLE test1 ( +SubscrID int(11) NOT NULL auto_increment, +UsrID int(11) NOT NULL default '0', +PRIMARY KEY (SubscrID), +KEY idx_usrid (UsrID) +) ENGINE=ndbcluster DEFAULT CHARSET=latin1; +INSERT INTO test1 VALUES (2,224),(3,224),(1,224); +CREATE TABLE test2 ( +SbclID int(11) NOT NULL auto_increment, +SbcrID int(11) NOT NULL default '0', +PRIMARY KEY (SbclID), +KEY idx_sbcrid (SbcrID) +) ENGINE=ndbcluster DEFAULT CHARSET=latin1; +INSERT INTO test2 VALUES (3,2),(1,1),(2,1),(4,2); +select * from test1 order by 1; +SubscrID UsrID +1 224 +2 224 +3 224 +select * from test2 order by 1; +SbclID SbcrID +1 1 +2 1 +3 2 +4 2 +SELECT s.SubscrID,l.SbclID FROM test1 s left JOIN test2 l ON +l.SbcrID=s.SubscrID WHERE s.UsrID=224 order by 1, 2; +SubscrID SbclID +1 1 +1 2 +2 3 +2 4 +3 NULL +drop table test1; +drop table test2; diff --git a/mysql-test/r/null.result b/mysql-test/r/null.result index f39bd0c6f6c..68fb9c3a34b 100644 --- a/mysql-test/r/null.result +++ b/mysql-test/r/null.result @@ -184,3 +184,97 @@ select count(*) from t1 where i=2 or i is null; count(*) 9 drop table t1; +set names latin2; +create table t1 select +null as c00, +if(1, null, 'string') as c01, +if(0, null, 'string') as c02, +ifnull(null, 'string') as c03, +ifnull('string', null) as c04, +case when 0 then null else 'string' end as c05, +case when 1 then null else 'string' end as c06, +coalesce(null, 'string') as c07, +coalesce('string', null) as c08, +least('string',null) as c09, +least(null, 'string') as c10, +greatest('string',null) as c11, +greatest(null, 'string') as c12, +nullif('string', null) as c13, +nullif(null, 'string') as c14, +trim('string' from null) as c15, +trim(null from 'string') as c16, +substring_index('string', null, 1) as c17, +substring_index(null, 'string', 1) as c18, +elt(1, null, 'string') as c19, +elt(1, 'string', null) as c20, +concat('string', null) as c21, +concat(null, 'string') as c22, +concat_ws('sep', 'string', null) as c23, +concat_ws('sep', null, 'string') as c24, +concat_ws(null, 'string', 'string') as c25, +make_set(3, 'string', null) as c26, +make_set(3, null, 'string') as c27, +export_set(3, null, 'off', 'sep') as c29, +export_set(3, 'on', null, 'sep') as c30, +export_set(3, 'on', 'off', null) as c31, +replace(null, 'from', 'to') as c32, +replace('str', null, 'to') as c33, +replace('str', 'from', null) as c34, +insert('str', 1, 2, null) as c35, +insert(null, 1, 2, 'str') as c36, +lpad('str', 10, null) as c37, +rpad(null, 10, 'str') as c38; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c00` binary(0) default NULL, + `c01` varchar(6) character set latin2 default NULL, + `c02` varchar(6) character set latin2 default NULL, + `c03` varchar(6) character set latin2 NOT NULL default '', + `c04` varchar(6) character set latin2 default NULL, + `c05` varchar(6) character set latin2 default NULL, + `c06` varchar(6) character set latin2 default NULL, + `c07` varchar(6) character set latin2 default NULL, + `c08` varchar(6) character set latin2 default NULL, + `c09` varchar(6) character set latin2 NOT NULL default '', + `c10` varchar(6) character set latin2 NOT NULL default '', + `c11` varchar(6) character set latin2 NOT NULL default '', + `c12` varchar(6) character set latin2 NOT NULL default '', + `c13` varchar(6) character set latin2 default NULL, + `c14` char(0) character set latin2 default NULL, + `c15` char(0) character set latin2 default NULL, + `c16` varchar(6) character set latin2 default NULL, + `c17` varchar(6) character set latin2 default NULL, + `c18` char(0) character set latin2 default NULL, + `c19` varchar(6) character set latin2 default NULL, + `c20` varchar(6) character set latin2 default NULL, + `c21` varchar(6) character set latin2 default NULL, + `c22` varchar(6) character set latin2 default NULL, + `c23` varchar(9) character set latin2 default NULL, + `c24` varchar(9) character set latin2 default NULL, + `c25` varchar(12) character set latin2 default NULL, + `c26` varchar(7) character set latin2 default NULL, + `c27` varchar(7) character set latin2 default NULL, + `c29` longtext character set latin2, + `c30` longtext character set latin2, + `c31` varchar(192) character set latin2 default NULL, + `c32` char(0) character set latin2 default NULL, + `c33` char(3) character set latin2 default NULL, + `c34` char(3) character set latin2 default NULL, + `c35` char(3) character set latin2 default NULL, + `c36` char(3) character set latin2 default NULL, + `c37` varchar(10) character set latin2 default NULL, + `c38` varchar(10) character set latin2 default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +drop table t1; +select +case 'str' when 'STR' then 'str' when null then 'null' end as c01, +case 'str' when null then 'null' when 'STR' then 'str' end as c02, +field(null, 'str1', 'str2') as c03, +field('str1','STR1', null) as c04, +field('str1', null, 'STR1') as c05, +'string' in ('STRING', null) as c08, +'string' in (null, 'STRING') as c09; +c01 c02 c03 c04 c05 c08 c09 +str str 0 1 2 1 1 +set names latin1; diff --git a/mysql-test/r/ps_2myisam.result b/mysql-test/r/ps_2myisam.result index 6773370fbc5..c64f513f0aa 100644 --- a/mysql-test/r/ps_2myisam.result +++ b/mysql-test/r/ps_2myisam.result @@ -1789,7 +1789,7 @@ t5 CREATE TABLE `t5` ( `param10` bigint(20) default NULL, `const11` int(4) default NULL, `param11` bigint(20) default NULL, - `const12` char(0) default NULL, + `const12` binary(0) default NULL, `param12` bigint(20) default NULL, `param13` double default NULL, `param14` longtext, @@ -1819,7 +1819,7 @@ def test t5 t5 const10 const10 3 10 9 N 32769 0 63 def test t5 t5 param10 param10 8 20 9 Y 32768 0 63 def test t5 t5 const11 const11 3 4 4 Y 32768 0 63 def test t5 t5 param11 param11 8 20 4 Y 32768 0 63 -def test t5 t5 const12 const12 254 0 0 Y 0 0 8 +def test t5 t5 const12 const12 254 0 0 Y 128 0 63 def test t5 t5 param12 param12 8 20 0 Y 32768 0 63 def test t5 t5 param13 param13 5 20 0 Y 32768 31 63 def test t5 t5 param14 param14 252 16777215 0 Y 16 0 8 diff --git a/mysql-test/r/ps_3innodb.result b/mysql-test/r/ps_3innodb.result index 09f19c3763c..adcf6064835 100644 --- a/mysql-test/r/ps_3innodb.result +++ b/mysql-test/r/ps_3innodb.result @@ -1772,7 +1772,7 @@ t5 CREATE TABLE `t5` ( `param10` bigint(20) default NULL, `const11` int(4) default NULL, `param11` bigint(20) default NULL, - `const12` char(0) default NULL, + `const12` binary(0) default NULL, `param12` bigint(20) default NULL, `param13` double default NULL, `param14` longtext, @@ -1802,7 +1802,7 @@ def test t5 t5 const10 const10 3 10 9 N 32769 0 63 def test t5 t5 param10 param10 8 20 9 Y 32768 0 63 def test t5 t5 const11 const11 3 4 4 Y 32768 0 63 def test t5 t5 param11 param11 8 20 4 Y 32768 0 63 -def test t5 t5 const12 const12 254 0 0 Y 0 0 8 +def test t5 t5 const12 const12 254 0 0 Y 128 0 63 def test t5 t5 param12 param12 8 20 0 Y 32768 0 63 def test t5 t5 param13 param13 5 20 0 Y 32768 31 63 def test t5 t5 param14 param14 252 16777215 0 Y 16 0 8 diff --git a/mysql-test/r/ps_4heap.result b/mysql-test/r/ps_4heap.result index 427fee8e757..cd36af07300 100644 --- a/mysql-test/r/ps_4heap.result +++ b/mysql-test/r/ps_4heap.result @@ -1773,7 +1773,7 @@ t5 CREATE TABLE `t5` ( `param10` bigint(20) default NULL, `const11` int(4) default NULL, `param11` bigint(20) default NULL, - `const12` char(0) default NULL, + `const12` binary(0) default NULL, `param12` bigint(20) default NULL, `param13` double default NULL, `param14` longtext, @@ -1803,7 +1803,7 @@ def test t5 t5 const10 const10 3 10 9 N 32769 0 63 def test t5 t5 param10 param10 8 20 9 Y 32768 0 63 def test t5 t5 const11 const11 3 4 4 Y 32768 0 63 def test t5 t5 param11 param11 8 20 4 Y 32768 0 63 -def test t5 t5 const12 const12 254 0 0 Y 0 0 8 +def test t5 t5 const12 const12 254 0 0 Y 128 0 63 def test t5 t5 param12 param12 8 20 0 Y 32768 0 63 def test t5 t5 param13 param13 5 20 0 Y 32768 31 63 def test t5 t5 param14 param14 252 16777215 0 Y 16 0 8 diff --git a/mysql-test/r/ps_5merge.result b/mysql-test/r/ps_5merge.result index 51d842ae000..3af0bfc7884 100644 --- a/mysql-test/r/ps_5merge.result +++ b/mysql-test/r/ps_5merge.result @@ -1712,7 +1712,7 @@ t5 CREATE TABLE `t5` ( `param10` bigint(20) default NULL, `const11` int(4) default NULL, `param11` bigint(20) default NULL, - `const12` char(0) default NULL, + `const12` binary(0) default NULL, `param12` bigint(20) default NULL, `param13` double default NULL, `param14` longtext, @@ -1742,7 +1742,7 @@ def test t5 t5 const10 const10 3 10 9 N 32769 0 63 def test t5 t5 param10 param10 8 20 9 Y 32768 0 63 def test t5 t5 const11 const11 3 4 4 Y 32768 0 63 def test t5 t5 param11 param11 8 20 4 Y 32768 0 63 -def test t5 t5 const12 const12 254 0 0 Y 0 0 8 +def test t5 t5 const12 const12 254 0 0 Y 128 0 63 def test t5 t5 param12 param12 8 20 0 Y 32768 0 63 def test t5 t5 param13 param13 5 20 0 Y 32768 31 63 def test t5 t5 param14 param14 252 16777215 0 Y 16 0 8 @@ -4721,7 +4721,7 @@ t5 CREATE TABLE `t5` ( `param10` bigint(20) default NULL, `const11` int(4) default NULL, `param11` bigint(20) default NULL, - `const12` char(0) default NULL, + `const12` binary(0) default NULL, `param12` bigint(20) default NULL, `param13` double default NULL, `param14` longtext, @@ -4751,7 +4751,7 @@ def test t5 t5 const10 const10 3 10 9 N 32769 0 63 def test t5 t5 param10 param10 8 20 9 Y 32768 0 63 def test t5 t5 const11 const11 3 4 4 Y 32768 0 63 def test t5 t5 param11 param11 8 20 4 Y 32768 0 63 -def test t5 t5 const12 const12 254 0 0 Y 0 0 8 +def test t5 t5 const12 const12 254 0 0 Y 128 0 63 def test t5 t5 param12 param12 8 20 0 Y 32768 0 63 def test t5 t5 param13 param13 5 20 0 Y 32768 31 63 def test t5 t5 param14 param14 252 16777215 0 Y 16 0 8 diff --git a/mysql-test/r/ps_6bdb.result b/mysql-test/r/ps_6bdb.result index 85cb8af652e..93f766c61e0 100644 --- a/mysql-test/r/ps_6bdb.result +++ b/mysql-test/r/ps_6bdb.result @@ -1772,7 +1772,7 @@ t5 CREATE TABLE `t5` ( `param10` bigint(20) default NULL, `const11` int(4) default NULL, `param11` bigint(20) default NULL, - `const12` char(0) default NULL, + `const12` binary(0) default NULL, `param12` bigint(20) default NULL, `param13` double default NULL, `param14` longtext, @@ -1802,7 +1802,7 @@ def test t5 t5 const10 const10 3 10 9 N 32769 0 63 def test t5 t5 param10 param10 8 20 9 Y 32768 0 63 def test t5 t5 const11 const11 3 4 4 Y 32768 0 63 def test t5 t5 param11 param11 8 20 4 Y 32768 0 63 -def test t5 t5 const12 const12 254 0 0 Y 0 0 8 +def test t5 t5 const12 const12 254 0 0 Y 128 0 63 def test t5 t5 param12 param12 8 20 0 Y 32768 0 63 def test t5 t5 param13 param13 5 20 0 Y 32768 31 63 def test t5 t5 param14 param14 252 16777215 0 Y 16 0 8 diff --git a/mysql-test/r/ps_7ndb.result b/mysql-test/r/ps_7ndb.result index e90eff5d1cd..70118509d0b 100644 --- a/mysql-test/r/ps_7ndb.result +++ b/mysql-test/r/ps_7ndb.result @@ -1749,7 +1749,7 @@ t5 CREATE TABLE `t5` ( `param10` bigint(20) default NULL, `const11` int(4) default NULL, `param11` bigint(20) default NULL, - `const12` char(0) default NULL, + `const12` binary(0) default NULL, `param12` bigint(20) default NULL, `param13` double default NULL, `param14` longtext, @@ -1779,7 +1779,7 @@ def test t5 t5 const10 const10 3 10 9 N 32769 0 63 def test t5 t5 param10 param10 8 20 9 Y 32768 0 63 def test t5 t5 const11 const11 3 4 4 Y 32768 0 63 def test t5 t5 param11 param11 8 20 4 Y 32768 0 63 -def test t5 t5 const12 const12 254 0 0 Y 0 0 8 +def test t5 t5 const12 const12 254 0 0 Y 128 0 63 def test t5 t5 param12 param12 8 20 0 Y 32768 0 63 def test t5 t5 param13 param13 5 20 0 Y 32768 31 63 def test t5 t5 param14 param14 252 16777215 0 Y 16 0 8 diff --git a/mysql-test/r/rpl_rewrite_db.result b/mysql-test/r/rpl_rewrite_db.result new file mode 100644 index 00000000000..2804b98dea1 --- /dev/null +++ b/mysql-test/r/rpl_rewrite_db.result @@ -0,0 +1,22 @@ +stop slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +start slave; +drop database if exists mysqltest1; +create database mysqltest1; +use mysqltest1; +create table t1 (a int); +insert into t1 values(9); +select * from mysqltest1.t1; +a +9 +show databases like 'mysqltest1'; +Database (mysqltest1) +mysqltest1 +select * from test.t1; +a +9 +drop table t1; +drop database mysqltest1; diff --git a/mysql-test/t/alter_table.test b/mysql-test/t/alter_table.test index e46027ae8d9..66a4adc90fe 100644 --- a/mysql-test/t/alter_table.test +++ b/mysql-test/t/alter_table.test @@ -324,3 +324,15 @@ alter table t1 rename to `t1\\`; rename table t1 to `t1\\`; drop table t1; +# +# Bug #6479 ALTER TABLE ... changing charset fails for TEXT columns +# +# The column's character set was changed but the actual data was not +# modified. In other words, the values were reinterpreted +# as UTF8 instead of being converted. +create table t1 (a text) character set koi8r; +insert into t1 values (_koi8r'ÔÅÓÔ'); +select hex(a) from t1; +alter table t1 convert to character set cp1251; +select hex(a) from t1; +drop table t1; diff --git a/mysql-test/t/consistent_snapshot.test b/mysql-test/t/consistent_snapshot.test new file mode 100644 index 00000000000..7afdae36325 --- /dev/null +++ b/mysql-test/t/consistent_snapshot.test @@ -0,0 +1,41 @@ +-- source include/have_innodb.inc + +--disable_warnings +drop table if exists t1; +--enable_warnings + +connect (con1,localhost,root,,); +connect (con2,localhost,root,,); + +### Test 1: +### - While a consistent snapshot transaction is executed, +### no external inserts should be visible to the transaction. + +connection con1; +create table t1 (a int) engine=innodb; +start transaction with consistent snapshot; + +connection con2; +insert into t1 values(1); + +connection con1; +select * from t1; # if consistent snapshot was set as expected, we +# should see nothing. +commit; + +### Test 2: +### - For any non-consistent snapshot transaction, external +### committed inserts should be visible to the transaction. + +delete from t1; +start transaction; # Now we omit WITH CONSISTENT SNAPSHOT + +connection con2; +insert into t1 values(1); + +connection con1; +select * from t1; # if consistent snapshot was not set, as expected, we +# should see 1. +commit; + +drop table t1; diff --git a/mysql-test/t/ctype_ujis.test b/mysql-test/t/ctype_ujis.test index e5405d9f1bd..9cfb6b14d7e 100644 --- a/mysql-test/t/ctype_ujis.test +++ b/mysql-test/t/ctype_ujis.test @@ -83,3 +83,39 @@ CREATE TABLE t1 ( SHOW CREATE TABLE t1; SHOW COLUMNS FROM t1; DROP TABLE t1; + +# +# Bug #6345 Unexpected behaviour with partial indices +# +--disable_warnings +CREATE TABLE t1 +( + a INTEGER NOT NULL, + b VARCHAR(50) NOT NULL DEFAULT '', + PRIMARY KEY (a), + KEY b (b(10)) +) TYPE=InnoDB CHARACTER SET 'ujis' COLLATE 'ujis_japanese_ci'; +--enable_warnings +INSERT INTO t1 (a, b) VALUES (0, 'aaabbbcccddd'); +INSERT INTO t1 (a, b) VALUES (1, 'eeefffggghhh'); +INSERT INTO t1 (a, b) VALUES (2, 'iiijjjkkkl'); +SELECT t1.* FROM t1 WHERE b='aaabbbcccddd' ORDER BY a; +SELECT t1.* FROM t1 WHERE b='eeefffggghhh' ORDER BY a; +SELECT t1.* FROM t1 WHERE b='iiijjjkkkl' ORDER BY a; +DROP TABLE t1; +--disable_warnings +CREATE TABLE t1 +( + a INTEGER NOT NULL, + b VARCHAR(50) NOT NULL DEFAULT '', + PRIMARY KEY (a), + KEY b (b(10)) +) TYPE=MyISAM CHARACTER SET 'ujis' COLLATE 'ujis_japanese_ci'; +--enable_warnings +INSERT INTO t1 (a, b) VALUES (0, 'aaabbbcccddd'); +INSERT INTO t1 (a, b) VALUES (1, 'eeefffggghhh'); +INSERT INTO t1 (a, b) VALUES (2, 'iiijjjkkkl'); +SELECT t1.* FROM t1 WHERE b='aaabbbcccddd' ORDER BY a; +SELECT t1.* FROM t1 WHERE b='eeefffggghhh' ORDER BY a; +SELECT t1.* FROM t1 WHERE b='iiijjjkkkl' ORDER BY a; +DROP TABLE t1; diff --git a/mysql-test/t/ndb_autodiscover.test b/mysql-test/t/ndb_autodiscover.test index 95b616fc7b2..fd7fe0e60d8 100644 --- a/mysql-test/t/ndb_autodiscover.test +++ b/mysql-test/t/ndb_autodiscover.test @@ -1,7 +1,7 @@ -- source include/have_ndb.inc --disable_warnings -drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9,t10; --enable_warnings ################################################ @@ -472,5 +472,11 @@ system rm var/master-data/test/t9.frm ; # MySQL Server will have been restarted because it has a # ndb_autodiscover2-master.opt file. +create table t10 ( + a int not null primary key, + b blob +) engine=ndb; +insert into t10 values (1, 'kalle'); +--exec $NDB_TOOLS_DIR/ndb_drop_table -d test `$NDB_TOOLS_DIR/ndb_show_tables | grep BLOB` > /dev/null 2>&1 || true diff --git a/mysql-test/t/ndb_autodiscover2.test b/mysql-test/t/ndb_autodiscover2.test index cce75d5ca4f..11e1cc204f7 100644 --- a/mysql-test/t/ndb_autodiscover2.test +++ b/mysql-test/t/ndb_autodiscover2.test @@ -13,4 +13,7 @@ show status like 'handler_discover%'; drop table t9; +--error 1296 +select * from t10; +drop table t10; diff --git a/mysql-test/t/ndb_basic.test b/mysql-test/t/ndb_basic.test index b62d2a8e0e1..2671223ada8 100644 --- a/mysql-test/t/ndb_basic.test +++ b/mysql-test/t/ndb_basic.test @@ -361,6 +361,21 @@ drop table test.t1, t2; drop database mysqltest; # +# BUG#6031 - DROP DATABASE doesn't drop database on first try +# + +--disable_warnings +drop database if exists ndbtest1; +--enable_warnings + +create database ndbtest1; +use ndbtest1; +create table t1(id int) engine=ndbcluster; +drop database ndbtest1; +--error 1008 +drop database ndbtest1; + +# # test support of char(0) # diff --git a/mysql-test/t/ndb_index_ordered.test b/mysql-test/t/ndb_index_ordered.test index 64291c8ab97..53177511bc6 100644 --- a/mysql-test/t/ndb_index_ordered.test +++ b/mysql-test/t/ndb_index_ordered.test @@ -1,7 +1,7 @@ -- source include/have_ndb.inc --disable_warnings -drop table if exists t1; +drop table if exists t1, test1, test2; --enable_warnings # @@ -146,3 +146,29 @@ select * from t1 use index (bc) where b IS NULL and c = 2 order by a; select * from t1 use index (bc) where b < 4 order by a; select * from t1 use index (bc) where b IS NOT NULL order by a; drop table t1; + +# +# Bug #6435 +CREATE TABLE test1 ( +SubscrID int(11) NOT NULL auto_increment, +UsrID int(11) NOT NULL default '0', +PRIMARY KEY (SubscrID), +KEY idx_usrid (UsrID) +) ENGINE=ndbcluster DEFAULT CHARSET=latin1; + +INSERT INTO test1 VALUES (2,224),(3,224),(1,224); + +CREATE TABLE test2 ( +SbclID int(11) NOT NULL auto_increment, +SbcrID int(11) NOT NULL default '0', +PRIMARY KEY (SbclID), +KEY idx_sbcrid (SbcrID) +) ENGINE=ndbcluster DEFAULT CHARSET=latin1; + +INSERT INTO test2 VALUES (3,2),(1,1),(2,1),(4,2); +select * from test1 order by 1; +select * from test2 order by 1; +SELECT s.SubscrID,l.SbclID FROM test1 s left JOIN test2 l ON +l.SbcrID=s.SubscrID WHERE s.UsrID=224 order by 1, 2; +drop table test1; +drop table test2; diff --git a/mysql-test/t/null.test b/mysql-test/t/null.test index 027443c485a..4bc6a4f051a 100644 --- a/mysql-test/t/null.test +++ b/mysql-test/t/null.test @@ -122,3 +122,70 @@ explain select * from t1 where i=2 or i is null; select count(*) from t1 where i=2 or i is null; drop table t1; +# +# NULL has its own type BINARY(0) by default. +# But NULL should be weaker than a constant +# when mixing charsets/collations +# +set names latin2; +# Check that result type is taken from a non-null string +create table t1 select + null as c00, + if(1, null, 'string') as c01, + if(0, null, 'string') as c02, + ifnull(null, 'string') as c03, + ifnull('string', null) as c04, + case when 0 then null else 'string' end as c05, + case when 1 then null else 'string' end as c06, + coalesce(null, 'string') as c07, + coalesce('string', null) as c08, + least('string',null) as c09, + least(null, 'string') as c10, + greatest('string',null) as c11, + greatest(null, 'string') as c12, + nullif('string', null) as c13, + nullif(null, 'string') as c14, + trim('string' from null) as c15, + trim(null from 'string') as c16, + substring_index('string', null, 1) as c17, + substring_index(null, 'string', 1) as c18, + elt(1, null, 'string') as c19, + elt(1, 'string', null) as c20, + concat('string', null) as c21, + concat(null, 'string') as c22, + concat_ws('sep', 'string', null) as c23, + concat_ws('sep', null, 'string') as c24, + concat_ws(null, 'string', 'string') as c25, + make_set(3, 'string', null) as c26, + make_set(3, null, 'string') as c27, + export_set(3, null, 'off', 'sep') as c29, + export_set(3, 'on', null, 'sep') as c30, + export_set(3, 'on', 'off', null) as c31, + replace(null, 'from', 'to') as c32, + replace('str', null, 'to') as c33, + replace('str', 'from', null) as c34, + insert('str', 1, 2, null) as c35, + insert(null, 1, 2, 'str') as c36, + lpad('str', 10, null) as c37, + rpad(null, 10, 'str') as c38; + +show create table t1; +drop table t1; + +# +# Check that comparison is done according to +# non-null string collation, i.e. case insensitively, +# rather than according to NULL's collation, i.e. case sensitively +# +-- in field +select + case 'str' when 'STR' then 'str' when null then 'null' end as c01, + case 'str' when null then 'null' when 'STR' then 'str' end as c02, + field(null, 'str1', 'str2') as c03, + field('str1','STR1', null) as c04, + field('str1', null, 'STR1') as c05, + 'string' in ('STRING', null) as c08, + 'string' in (null, 'STRING') as c09; + +# Restore charset to the default value. +set names latin1; diff --git a/mysql-test/t/rpl_rewrite_db-slave.opt b/mysql-test/t/rpl_rewrite_db-slave.opt new file mode 100644 index 00000000000..b9cd29e9205 --- /dev/null +++ b/mysql-test/t/rpl_rewrite_db-slave.opt @@ -0,0 +1 @@ +"--replicate-rewrite-db=mysqltest1->test" diff --git a/mysql-test/t/rpl_rewrite_db.test b/mysql-test/t/rpl_rewrite_db.test new file mode 100644 index 00000000000..4cc8ae4b676 --- /dev/null +++ b/mysql-test/t/rpl_rewrite_db.test @@ -0,0 +1,19 @@ +source include/master-slave.inc; +--disable_warnings +drop database if exists mysqltest1; +--enable_warnings +create database mysqltest1; + +use mysqltest1; +create table t1 (a int); +insert into t1 values(9); +select * from mysqltest1.t1; +sync_slave_with_master; +show databases like 'mysqltest1'; # should be empty +select * from test.t1; +# cleanup +connection master; +drop table t1; +drop database mysqltest1; +sync_slave_with_master; + diff --git a/mysys/my_init.c b/mysys/my_init.c index 0ef938b434c..e9a61b1833c 100644 --- a/mysys/my_init.c +++ b/mysys/my_init.c @@ -42,8 +42,8 @@ static void netware_init(); #define netware_init() #endif - -my_bool my_init_done=0; +my_bool my_init_done= 0; +uint mysys_usage_id= 0; /* Incremented for each my_init() */ static ulong atoi_octal(const char *str) { @@ -51,7 +51,7 @@ static ulong atoi_octal(const char *str) while (*str && my_isspace(&my_charset_latin1, *str)) str++; str2int(str, - (*str == '0' ? 8 : 10), /* Octalt or decimalt */ + (*str == '0' ? 8 : 10), /* Octalt or decimalt */ 0, INT_MAX, &tmp); return (ulong) tmp; } @@ -74,6 +74,7 @@ my_bool my_init(void) if (my_init_done) return 0; my_init_done=1; + mysys_usage_id++; #if defined(THREAD) && defined(SAFE_MUTEX) safe_mutex_global_init(); /* Must be called early */ #endif diff --git a/ndb/include/mgmapi/mgmapi.h b/ndb/include/mgmapi/mgmapi.h index 6dcf58b44e2..f1ef357421b 100644 --- a/ndb/include/mgmapi/mgmapi.h +++ b/ndb/include/mgmapi/mgmapi.h @@ -733,6 +733,7 @@ extern "C" { int param, unsigned long long * value); int ndb_mgm_get_string_parameter(const ndb_mgm_configuration_iterator*, int param, const char ** value); + int ndb_mgm_purge_stale_sessions(NdbMgmHandle handle, char **); #ifdef __cplusplus } #endif diff --git a/ndb/include/ndb_types.h b/ndb/include/ndb_types.h index a2988dbae78..64b3f517934 100644 --- a/ndb/include/ndb_types.h +++ b/ndb/include/ndb_types.h @@ -21,11 +21,11 @@ #ifndef NDB_TYPES_H #define NDB_TYPES_H -typedef char Int8; +typedef signed char Int8; typedef unsigned char Uint8; -typedef short Int16; +typedef signed short Int16; typedef unsigned short Uint16; -typedef int Int32; +typedef signed int Int32; typedef unsigned int Uint32; typedef unsigned int UintR; @@ -45,10 +45,10 @@ typedef uintptr_t UintPtr; #if defined(WIN32) || defined(NDB_WIN32) typedef unsigned __int64 Uint64; -typedef __int64 Int64; +typedef signed __int64 Int64; #else typedef unsigned long long Uint64; -typedef long long Int64; +typedef signed long long Int64; #endif #endif diff --git a/ndb/include/ndbapi/NdbDictionary.hpp b/ndb/include/ndbapi/NdbDictionary.hpp index 51a6895648f..a3115076624 100644 --- a/ndb/include/ndbapi/NdbDictionary.hpp +++ b/ndb/include/ndbapi/NdbDictionary.hpp @@ -369,7 +369,7 @@ public: */ bool getDistributionKey() const; /** @} *******************************************************************/ - + #ifndef DOXYGEN_SHOULD_SKIP_INTERNAL void setTupleKey(bool); bool getTupleKey() const; @@ -490,6 +490,18 @@ public: * Get column definition via index in table. * @return null if none existing name */ + Column* getColumn(const int attributeId); + + /** + * Get column definition via name. + * @return null if none existing name + */ + Column* getColumn(const char * name); + + /** + * Get column definition via index in table. + * @return null if none existing name + */ const Column* getColumn(const int attributeId) const; /** @} *******************************************************************/ diff --git a/ndb/include/util/Bitmask.hpp b/ndb/include/util/Bitmask.hpp index bb217adab5f..19aa604e4a1 100644 --- a/ndb/include/util/Bitmask.hpp +++ b/ndb/include/util/Bitmask.hpp @@ -105,6 +105,11 @@ public: static void bitXOR(unsigned size, Uint32 data[], const Uint32 data2[]); /** + * bitXORC - Bitwise (x ^ ~y) into first operand. + */ + static void bitXORC(unsigned size, Uint32 data[], const Uint32 data2[]); + + /** * contains - Check if all bits set in data2 are set in data */ static bool contains(unsigned size, Uint32 data[], const Uint32 data2[]); @@ -261,6 +266,14 @@ BitmaskImpl::bitXOR(unsigned size, Uint32 data[], const Uint32 data2[]) } } +inline void +BitmaskImpl::bitXORC(unsigned size, Uint32 data[], const Uint32 data2[]) +{ + for (unsigned i = 0; i < size; i++) { + data[i] ^= ~data2[i]; + } +} + inline bool BitmaskImpl::contains(unsigned size, Uint32 data[], const Uint32 data2[]) { @@ -452,6 +465,12 @@ public: BitmaskPOD<size>& bitXOR(const BitmaskPOD<size>& mask2); /** + * bitXORC - Bitwise (x ^ ~y) into first operand. + */ + static void bitXORC(Uint32 data[], const Uint32 data2[]); + BitmaskPOD<size>& bitXORC(const BitmaskPOD<size>& mask2); + + /** * contains - Check if all bits set in data2 (that) are also set in data (this) */ static bool contains(Uint32 data[], const Uint32 data2[]); @@ -713,6 +732,21 @@ BitmaskPOD<size>::bitXOR(const BitmaskPOD<size>& mask2) } template <unsigned size> +inline void +BitmaskPOD<size>::bitXORC(Uint32 data[], const Uint32 data2[]) +{ + BitmaskImpl::bitXORC(size,data, data2); +} + +template <unsigned size> +inline BitmaskPOD<size>& +BitmaskPOD<size>::bitXORC(const BitmaskPOD<size>& mask2) +{ + BitmaskPOD<size>::bitXORC(rep.data, mask2.rep.data); + return *this; +} + +template <unsigned size> char * BitmaskPOD<size>::getText(const Uint32 data[], char* buf) { diff --git a/ndb/include/util/SocketServer.hpp b/ndb/include/util/SocketServer.hpp index 3860b9ca84b..2fad991e5f8 100644 --- a/ndb/include/util/SocketServer.hpp +++ b/ndb/include/util/SocketServer.hpp @@ -37,7 +37,7 @@ public: public: virtual ~Session() {} virtual void runSession(){} - virtual void stopSession(){} + virtual void stopSession(){ m_stop = true; } protected: friend class SocketServer; friend void* sessionThread_C(void*); @@ -98,6 +98,8 @@ public: */ void stopSessions(bool wait = false); + void foreachSession(void (*f)(SocketServer::Session*, void*), void *data); + private: struct SessionInstance { Service * m_service; diff --git a/ndb/src/common/Makefile.am b/ndb/src/common/Makefile.am index 7fcf2cab636..8733205eca2 100644 --- a/ndb/src/common/Makefile.am +++ b/ndb/src/common/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = portlib debugger util logger transporter mgmcommon editline +SUBDIRS = portlib debugger util logger transporter mgmcommon noinst_LTLIBRARIES = libcommon.la diff --git a/ndb/src/common/Makefile_old b/ndb/src/common/Makefile_old deleted file mode 100644 index ebde75bf3ec..00000000000 --- a/ndb/src/common/Makefile_old +++ /dev/null @@ -1,15 +0,0 @@ -include .defs.mk - -LIB_DIRS := \ - portlib \ - debugger \ - util \ - logger - -ifneq ($(USE_EDITLINE), N) -LIB_DIRS += editline -endif - -DIRS := transporter mgmcommon - -include $(NDB_TOP)/Epilogue.mk diff --git a/ndb/src/common/debugger/Makefile_old b/ndb/src/common/debugger/Makefile_old deleted file mode 100644 index ac3a4475a54..00000000000 --- a/ndb/src/common/debugger/Makefile_old +++ /dev/null @@ -1,11 +0,0 @@ -include .defs.mk - -TYPE := kernel -DIRS := signaldata - -PIC_ARCHIVE := Y -ARCHIVE_TARGET := trace - -SOURCES = SignalLoggerManager.cpp DebuggerNames.cpp BlockNames.cpp LogLevel.cpp EventLogger.cpp GrepError.cpp - -include $(NDB_TOP)/Epilogue.mk diff --git a/ndb/src/common/debugger/signaldata/Makefile_old b/ndb/src/common/debugger/signaldata/Makefile_old deleted file mode 100644 index bd00667b482..00000000000 --- a/ndb/src/common/debugger/signaldata/Makefile_old +++ /dev/null @@ -1,33 +0,0 @@ -include .defs.mk - -TYPE := ndbapi - -PIC_ARCHIVE := Y -ARCHIVE_TARGET := signaldataprint - -SOURCES = TcKeyReq.cpp TcKeyConf.cpp TcKeyRef.cpp \ - TcRollbackRep.cpp \ - TupKey.cpp TupCommit.cpp LqhKey.cpp \ - FsOpenReq.cpp FsCloseReq.cpp FsRef.cpp FsConf.cpp FsReadWriteReq.cpp\ - SignalDataPrint.cpp SignalNames.cpp \ - ContinueB.cpp DihContinueB.cpp NdbfsContinueB.cpp \ - CloseComReqConf.cpp PackedSignal.cpp PrepFailReqRef.cpp \ - GCPSave.cpp DictTabInfo.cpp \ - AlterTable.cpp AlterTab.cpp \ - CreateTrig.cpp AlterTrig.cpp DropTrig.cpp \ - FireTrigOrd.cpp TrigAttrInfo.cpp \ - CreateIndx.cpp AlterIndx.cpp DropIndx.cpp TcIndx.cpp \ - IndxKeyInfo.cpp IndxAttrInfo.cpp \ - FsAppendReq.cpp ScanTab.cpp \ - BackupImpl.cpp BackupSignalData.cpp \ - UtilSequence.cpp UtilPrepare.cpp UtilDelete.cpp UtilExecute.cpp \ - LqhFrag.cpp DropTab.cpp PrepDropTab.cpp LCP.cpp MasterLCP.cpp \ - CopyGCI.cpp SystemError.cpp StartRec.cpp NFCompleteRep.cpp \ - FailRep.cpp DisconnectRep.cpp SignalDroppedRep.cpp \ - SumaImpl.cpp NdbSttor.cpp CreateFragmentation.cpp \ - CntrStart.cpp ReadNodesConf.cpp \ - UtilLock.cpp TuxMaint.cpp TupAccess.cpp AccLock.cpp \ - LqhTrans.cpp - -include $(NDB_TOP)/Epilogue.mk - diff --git a/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp b/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp index 3314f0bd097..a4cee38e06f 100644 --- a/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp +++ b/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp @@ -16,65 +16,9 @@ -#include "GlobalSignalNumbers.h" -#include "signaldata/SignalDataPrint.hpp" -#include "signaldata/TcKeyReq.hpp" -#include "signaldata/TcKeyConf.hpp" -#include "signaldata/TcKeyRef.hpp" -#include "signaldata/LqhKey.hpp" -#include "signaldata/TupKey.hpp" -#include "signaldata/TupCommit.hpp" -#include "signaldata/FsOpenReq.hpp" -#include "signaldata/FsCloseReq.hpp" -#include "signaldata/FsReadWriteReq.hpp" -#include "signaldata/FsRef.hpp" -#include "signaldata/FsConf.hpp" -#include "signaldata/CloseComReqConf.hpp" -#include "signaldata/PackedSignal.hpp" -#include "signaldata/PrepFailReqRef.hpp" -#include "signaldata/DictTabInfo.hpp" -#include "signaldata/AlterTable.hpp" -#include "signaldata/AlterTab.hpp" -#include "signaldata/CreateTrig.hpp" -#include "signaldata/AlterTrig.hpp" -#include "signaldata/DropTrig.hpp" -#include "signaldata/FireTrigOrd.hpp" -#include "signaldata/TrigAttrInfo.hpp" -#include "signaldata/CreateIndx.hpp" -#include "signaldata/AlterIndx.hpp" -#include "signaldata/DropIndx.hpp" -#include "signaldata/TcIndx.hpp" -#include "signaldata/IndxKeyInfo.hpp" -#include "signaldata/IndxAttrInfo.hpp" -#include <signaldata/FsAppendReq.hpp> -#include <signaldata/BackupSignalData.hpp> -#include <signaldata/BackupImpl.hpp> -#include <signaldata/UtilSequence.hpp> -#include <signaldata/UtilPrepare.hpp> -#include <signaldata/UtilExecute.hpp> -#include <signaldata/ScanTab.hpp> -#include <signaldata/ScanFrag.hpp> -#include <signaldata/LqhFrag.hpp> -#include <signaldata/LqhTransConf.hpp> -#include <signaldata/DropTab.hpp> -#include <signaldata/PrepDropTab.hpp> -#include <signaldata/LCP.hpp> -#include <signaldata/MasterLCP.hpp> -#include <signaldata/CopyGCIReq.hpp> -#include <signaldata/SystemError.hpp> -#include <signaldata/StartRec.hpp> -#include <signaldata/NFCompleteRep.hpp> -#include <signaldata/SignalDroppedRep.hpp> -#include <signaldata/FailRep.hpp> -#include <signaldata/DisconnectRep.hpp> -#include <signaldata/SumaImpl.hpp> -#include <signaldata/NdbSttor.hpp> -#include <signaldata/CreateFragmentation.hpp> -#include <signaldata/UtilLock.hpp> -#include <signaldata/CntrStart.hpp> -#include <signaldata/ReadNodesConf.hpp> -#include <signaldata/TuxMaint.hpp> -#include <signaldata/AccLock.hpp> +#include <GlobalSignalNumbers.h> +#include <signaldata/SignalData.hpp> +#include <signaldata/SignalDataPrint.hpp> /** * This is the register @@ -254,9 +198,11 @@ SignalDataPrintFunctions[] = { ,{ 0, 0 } }; -template class Bitmask<1>; -template class Bitmask<2>; -template class Bitmask<4>; +#include <Bitmask.hpp> + template struct BitmaskPOD<1>; template struct BitmaskPOD<2>; template struct BitmaskPOD<4>; +template class Bitmask<1>; +template class Bitmask<2>; +template class Bitmask<4>; diff --git a/ndb/src/common/editline/MANIFEST b/ndb/src/common/editline/MANIFEST deleted file mode 100644 index dc8b4b36f88..00000000000 --- a/ndb/src/common/editline/MANIFEST +++ /dev/null @@ -1,15 +0,0 @@ -File Name Description --------------------------------------------------------- -README Release notes and copyright -MANIFEST This shipping list -Make.os9 OS-9 makefile -Makefile Unix makefile -complete.c Filename completion routines -editline.3 Manual page for editline library -editline.c Line-editing routines -editline_internal.h Internal library header file -os9.h OS-9-specific declarations -sysos9.c OS-9-specific routines -sysunix.c Unix-specific routines -testit.c Test driver -unix.h Unix-specific declarations diff --git a/ndb/src/common/editline/Makefile.am b/ndb/src/common/editline/Makefile.am deleted file mode 100644 index 4f53bdc6326..00000000000 --- a/ndb/src/common/editline/Makefile.am +++ /dev/null @@ -1,10 +0,0 @@ - -noinst_LIBRARIES = libeditline.a - -libeditline_a_SOURCES = complete.c editline.c sysunix.c - -INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/ndb/include -DEFS = -DANSI_ARROWS -DHAVE_TCGETATTR -DSYS_UNIX - -# Don't update the files from bitkeeper -%::SCCS/s.% diff --git a/ndb/src/common/editline/Makefile_old b/ndb/src/common/editline/Makefile_old deleted file mode 100644 index 800df8f0f31..00000000000 --- a/ndb/src/common/editline/Makefile_old +++ /dev/null @@ -1,18 +0,0 @@ -include .defs.mk - -TYPE := - -ARCHIVE_TARGET := editline - -CFLAGS += -DANSI_ARROWS -DHAVE_TCGETATTR -DSYS_UNIX - -ifeq ($(NDB_OS), WIN32) -SOURCES = editline_win32.c -else -SOURCES = complete.c editline.c sysunix.c -endif - -DIRS := test - -include $(NDB_TOP)/Epilogue.mk - diff --git a/ndb/src/common/editline/README b/ndb/src/common/editline/README deleted file mode 100644 index 537c7bd8611..00000000000 --- a/ndb/src/common/editline/README +++ /dev/null @@ -1,53 +0,0 @@ --- -NOTE: This version has been modified by Ericsson/Alzato. Please -see the cvs changelog for more details. --- - -$Revision: 1.2 $ - -This is a line-editing library. It can be linked into almost any -program to provide command-line editing and recall. - -It is call-compatible with the FSF readline library, but it is a -fraction of the size (and offers fewer features). It does not use -standard I/O. It is distributed under a "C News-like" copyright. - -Configuration is done in the Makefile. Type "make testit" to get -a small slow shell for testing. - -This contains some changes since the posting to comp.sources.misc: - - Bugfix for completion on absolute pathnames. - - Better handling of M-n versus showing raw 8bit chars. - - Better signal handling. - - Now supports termios/termio/sgttyb ioctl's. - - Add M-m command to toggle how 8bit data is displayed. -The following changes, made since the last public release, come from -J.G. Vons <vons@cesar.crbca1.sinet.slb.com>: - - History-searching no longer redraws the line wrong - - Added ESC-ESC as synonym for ESC-? - - SIGQUIT (normally ^\) now sends a signal, not indicating EOF. - - Fixed some typo's and unclear wording in the manpage. - - Fixed completion when all entries shared a common prefix. - - Fixed some meta-char line-redrawing bugs. - -Enjoy, - Rich $alz - <rsalz@osf.org> - - Copyright 1992,1993 Simmule Turner and Rich Salz. All rights reserved. - - This software is not subject to any license of the American Telephone - and Telegraph Company or of the Regents of the University of California. - - Permission is granted to anyone to use this software for any purpose on - any computer system, and to alter it and redistribute it freely, subject - to the following restrictions: - 1. The authors are not responsible for the consequences of use of this - software, no matter how awful, even if they arise from flaws in it. - 2. The origin of this software must not be misrepresented, either by - explicit claim or by omission. Since few users ever read sources, - credits must appear in the documentation. - 3. Altered versions must be plainly marked as such, and must not be - misrepresented as being the original software. Since few users - ever read sources, credits must appear in the documentation. - 4. This notice may not be removed or altered. diff --git a/ndb/src/common/editline/complete.c b/ndb/src/common/editline/complete.c deleted file mode 100644 index c524a88c678..00000000000 --- a/ndb/src/common/editline/complete.c +++ /dev/null @@ -1,195 +0,0 @@ -/* -*- c-basic-offset: 4; -*- -** $Revision: 1.8 $ -** -** History and file completion functions for editline library. -*/ -#include "editline_internal.h" - - -/* -** strcmp-like sorting predicate for qsort. -*/ -static int -compare(const void *p1, const void *p2) -{ - const char **v1; - const char **v2; - - v1 = (const char **)p1; - v2 = (const char **)p2; - return strcmp(*v1, *v2); -} - -/* -** Fill in *avp with an array of names that match file, up to its length. -** Ignore . and .. . -*/ -static int -FindMatches(char *dir, char *file, char ***avp) -{ - char **av; - char **new; - char *p; - DIR *dp; - struct dirent *ep; - size_t ac; - size_t len; - - if ((dp = opendir(dir)) == NULL) - return 0; - - av = NULL; - ac = 0; - len = strlen(file); - while ((ep = readdir(dp)) != NULL) { - p = ep->d_name; - if (p[0] == '.' && (p[1] == '\0' || (p[1] == '.' && p[2] == '\0'))) - continue; - if (len && strncmp(p, file, len) != 0) - continue; - - if ((ac % MEM_INC) == 0) { - if ((new = malloc(sizeof(char*) * (ac + MEM_INC))) == NULL) - break; - if (ac) { - memcpy(new, av, ac * sizeof (char **)); - free(av); - } - *avp = av = new; - } - - if ((av[ac] = strdup(p)) == NULL) { - if (ac == 0) - free(av); - break; - } - ac++; - } - - /* Clean up and return. */ - (void)closedir(dp); - if (ac) - qsort(av, ac, sizeof (char **), compare); - return ac; -} - -/* -** Split a pathname into allocated directory and trailing filename parts. -*/ -static int -SplitPath(char *path, char **dirpart, char ** filepart) -{ - static char DOT[] = "."; - char *dpart; - char *fpart; - - if ((fpart = strrchr(path, '/')) == NULL) { - if ((dpart = strdup(DOT)) == NULL) - return -1; - if ((fpart = strdup(path)) == NULL) { - free(dpart); - return -1; - } - } - else { - if ((dpart = strdup(path)) == NULL) - return -1; - dpart[fpart - path + 1] = '\0'; - if ((fpart = strdup(++fpart)) == NULL) { - free(dpart); - return -1; - } - } - *dirpart = dpart; - *filepart = fpart; - return 0; -} - -/* -** Attempt to complete the pathname, returning an allocated copy. -** Fill in *unique if we completed it, or set it to 0 if ambiguous. -*/ -char * -rl_complete(char *pathname,int *unique) -{ - char **av; - char *dir; - char *file; - char *new; - char *p; - size_t ac; - size_t end; - size_t i; - size_t j; - size_t len; - size_t new_len; - size_t p_len; - - if (SplitPath(pathname, &dir, &file) < 0) - return NULL; - if ((ac = FindMatches(dir, file, &av)) == 0) { - free(dir); - free(file); - return NULL; - } - - p = NULL; - len = strlen(file); - if (ac == 1) { - /* Exactly one match -- finish it off. */ - *unique = 1; - j = strlen(av[0]) - len + 2; - p_len = sizeof(char) * (j + 1); - if ((p = malloc(p_len)) != NULL) { - memcpy(p, av[0] + len, j); - new_len = sizeof(char) * (strlen(dir) + strlen(av[0]) + 2); - new = malloc(new_len); - if(new != NULL) { - snprintf(new, new_len, "%s/%s", dir, av[0]); - rl_add_slash(new, p, p_len); - free(new); - } - } - } - else { - /* Find largest matching substring. */ - for (*unique = 0, i = len, end = strlen(av[0]); i < end; i++) - for (j = 1; j < ac; j++) - if (av[0][i] != av[j][i]) - goto breakout; -breakout: - if (i > len) { - j = i - len + 1; - if ((p = malloc(sizeof(char) * j)) != NULL) { - memcpy(p, av[0] + len, j); - p[j - 1] = '\0'; - } - } - } - - /* Clean up and return. */ - free(dir); - free(file); - for (i = 0; i < ac; i++) - free(av[i]); - free(av); - return p; -} - -/* -** Return all possible completions. -*/ -int -rl_list_possib(char *pathname, char ***avp) -{ - char *dir; - char *file; - int ac; - - if (SplitPath(pathname, &dir, &file) < 0) - return 0; - ac = FindMatches(dir, file, avp); - free(dir); - free(file); - return ac; -} diff --git a/ndb/src/common/editline/editline.3 b/ndb/src/common/editline/editline.3 deleted file mode 100644 index 159cc7f87bb..00000000000 --- a/ndb/src/common/editline/editline.3 +++ /dev/null @@ -1,178 +0,0 @@ -.\" $Revision: 1.1 $ -.TH EDITLINE 3 -.SH NAME -editline \- command-line editing library with history -.SH SYNOPSIS -.nf -.B "char *" -.B "readline(prompt)" -.B " char *prompt;" - -.B "void" -.B "add_history(line)" -.B " char *line;" -.fi -.SH DESCRIPTION -.I Editline -is a library that provides an line-editing interface with text recall. -It is intended to be compatible with the -.I readline -library provided by the Free Software Foundation, but much smaller. -The bulk of this manual page describes the user interface. -.PP -The -.I readline -routine returns a line of text with the trailing newline removed. -The data is returned in a buffer allocated with -.IR malloc (3), -so the space should be released with -.IR free (3) -when the calling program is done with it. -Before accepting input from the user, the specified -.I prompt -is displayed on the terminal. -.PP -The -.I add_history -routine makes a copy of the specified -.I line -and adds it to the internal history list. -.SS "User Interface" -A program that uses this library provides a simple emacs-like editing -interface to its users. -A line may be edited before it is sent to the calling program by typing either -control characters or escape sequences. -A control character, shown as a caret followed by a letter, is typed by -holding down the ``control'' key while the letter is typed. -For example, ``^A'' is a control-A. -An escape sequence is entered by typing the ``escape'' key followed by one or -more characters. -The escape key is abbreviated as ``ESC''. -Note that unlike control keys, case matters in escape sequences; ``ESC\ F'' -is not the same as ``ESC\ f''. -.PP -An editing command may be typed anywhere on the line, not just at the -beginning. -In addition, a return may also be typed anywhere on the line, not just at -the end. -.PP -Most editing commands may be given a repeat count, -.IR n , -where -.I n -is a number. -To enter a repeat count, type the escape key, the number, and then -the command to execute. -For example, ``ESC\ 4\ ^f'' moves forward four characters. -If a command may be given a repeat count then the text ``[n]'' is given at the -end of its description. -.PP -The following control characters are accepted: -.RS -.nf -.ta \w'ESC DEL 'u -^A Move to the beginning of the line -^B Move left (backwards) [n] -^D Delete character [n] -^E Move to end of line -^F Move right (forwards) [n] -^G Ring the bell -^H Delete character before cursor (backspace key) [n] -^I Complete filename (tab key); see below -^J Done with line (return key) -^K Kill to end of line (or column [n]) -^L Redisplay line -^M Done with line (alternate return key) -^N Get next line from history [n] -^P Get previous line from history [n] -^R Search backward (forward if [n]) through history for text; -\& prefixing the string with a caret (^) forces it to -\& match only at the beginning of a history line -^T Transpose characters -^V Insert next character, even if it is an edit command -^W Wipe to the mark -^X^X Exchange current location and mark -^Y Yank back last killed text -^[ Start an escape sequence (escape key) -^]c Move forward to next character ``c'' -^? Delete character before cursor (delete key) [n] -.fi -.RE -.PP -The following escape sequences are provided. -.RS -.nf -.ta \w'ESC DEL 'u -ESC\ ^H Delete previous word (backspace key) [n] -ESC\ DEL Delete previous word (delete key) [n] -ESC\ ESC Show possible completions; see below -ESC\ SP Set the mark (space key); see ^X^X and ^Y above -ESC\ . Get the last (or [n]'th) word from previous line -ESC\ ? Show possible completions; see below -ESC\ < Move to start of history -ESC\ > Move to end of history -ESC\ b Move backward a word [n] -ESC\ d Delete word under cursor [n] -ESC\ f Move forward a word [n] -ESC\ l Make word lowercase [n] -ESC\ m Toggle if 8bit chars display as themselves or with -\& an ``M\-'' prefix -ESC\ u Make word uppercase [n] -ESC\ y Yank back last killed text -ESC\ w Make area up to mark yankable -ESC\ nn Set repeat count to the number nn -ESC\ C Read from environment variable ``_C_'', where C is -\& an uppercase letter -.fi -.RE -.PP -The -.I editline -library has a small macro facility. -If you type the escape key followed by an uppercase letter, -.IR C , -then the contents of the environment variable -.I _C_ -are read in as if you had typed them at the keyboard. -For example, if the variable -.I _L_ -contains the following: -.RS -^A^Kecho '^V^[[H^V^[[2J'^M -.RE -Then typing ``ESC L'' will move to the beginning of the line, kill the -entire line, enter the echo command needed to clear the terminal (if your -terminal is like a VT-100), and send the line back to the shell. -.PP -The -.I editline -library also does filename completion. -Suppose the root directory has the following files in it: -.RS -.nf -.ta \w'core 'u -bin vmunix -core vmunix.old -.fi -.RE -If you type ``rm\ /v'' and then the tab key. -.I Editline -will then finish off as much of the name as possible by adding ``munix''. -Because the name is not unique, it will then beep. -If you type the escape key followed by either a question mark or another -escape, it will display the two choices. -If you then type a period and a tab, the library will finish off the filename -for you: -.RS -.nf -.RI "rm /v[TAB]" munix ".[TAB]" old -.fi -.RE -The tab key is shown by ``[TAB]'' and the automatically-entered text -is shown in italics. -.SH "BUGS AND LIMITATIONS" -Cannot handle lines more than 80 columns. -.SH AUTHORS -Simmule R. Turner <uunet.uu.net!capitol!sysgo!simmy> -and Rich $alz <rsalz@osf.org>. -Original manual page by DaviD W. Sanderson <dws@ssec.wisc.edu>. diff --git a/ndb/src/common/editline/editline.c b/ndb/src/common/editline/editline.c deleted file mode 100644 index 886dac2793b..00000000000 --- a/ndb/src/common/editline/editline.c +++ /dev/null @@ -1,1498 +0,0 @@ -/* -*- c-basic-offset: 4; -*- -** $Revision: 1.6 $ -** -** Main editing routines for editline library. -*/ -#include <ndb_global.h> - -#include "editline_internal.h" -#include <signal.h> - -/* -** Manifest constants. -*/ -#define SCREEN_WIDTH 80 -#define SCREEN_ROWS 24 -#define NO_ARG (-1) -#define DEL 127 -#define TAB '\t' -#define CTL(x) ((x) & 0x1F) -#define ISCTL(x) ((x) && (x) < ' ') -#define UNCTL(x) ((x) + 64) -#define META(x) ((x) | 0x80) -#define ISMETA(x) ((x) & 0x80) -#define UNMETA(x) ((x) & 0x7F) -#define MAPSIZE 32 -#define METAMAPSIZE 16 -#if !defined(HIST_SIZE) -#define HIST_SIZE 20 -#endif /* !defined(HIST_SIZE) */ - -/* -** Command status codes. -*/ -typedef enum _STATUS { - CSdone, CSeof, CSmove, CSdispatch, CSstay, CSsignal -} STATUS; - -/* -** The type of case-changing to perform. -*/ -typedef enum _CASE { - TOupper, TOlower -} CASE; - -/* -** Key to command mapping. -*/ -typedef struct _KEYMAP { - char Key; - char Active; - STATUS (*Function)(); -} KEYMAP; - -/* -** Command history structure. -*/ -typedef struct _HISTORY { - int Size; - int Pos; - char *Lines[HIST_SIZE]; -} HISTORY; - -/* -** Globals. -*/ -int rl_eof; -int rl_erase; -int rl_intr; -int rl_kill; -int rl_quit; -#if defined(DO_SIGTSTP) -int rl_susp; -#endif /* defined(DO_SIGTSTP) */ - -static char NIL[] = ""; -static const char *Input = NIL; -static char *Line; -static const char *Prompt; -static char *Yanked; -static char *Screen; -static char NEWLINE[]= CRLF; -static HISTORY H; -static int Repeat; -static int End; -static int Mark; -static int OldPoint; -static int Point; -static int PushBack; -static int Pushed; -static int Signal; -static KEYMAP Map[MAPSIZE]; -static KEYMAP MetaMap[METAMAPSIZE]; -static size_t Length; -static size_t ScreenCount; -static size_t ScreenSize; -static char *backspace; -static int TTYwidth; -static int TTYrows; - -/* Display print 8-bit chars as `M-x' or as the actual 8-bit char? */ -int rl_meta_chars = 1; - -/* -** Declarations. -*/ -static char *editinput(); - -#if defined(USE_TERMCAP) -extern char *getenv(); -extern char *tgetstr(); -extern int tgetent(); -extern int tgetnum(); -#endif /* defined(USE_TERMCAP) */ - -/* -** TTY input/output functions. -*/ - -static void -TTYflush() -{ - if (ScreenCount) { - (void)write(1, Screen, ScreenCount); - ScreenCount = 0; - } -} - -static void -TTYput(const char c) -{ - Screen[ScreenCount] = c; - if (++ScreenCount >= ScreenSize - 1) { - ScreenSize += SCREEN_INC; - Screen = realloc(Screen, sizeof(char) * ScreenSize); - /* XXX what to do if realloc failes? */ - } -} - -static void -TTYputs(const char *p) -{ - while (*p) - TTYput(*p++); -} - -static void -TTYshow(char c) -{ - if (c == DEL) { - TTYput('^'); - TTYput('?'); - } - else if (c == TAB) { - /* XXX */ - } - else if (ISCTL(c)) { - TTYput('^'); - TTYput(UNCTL(c)); - } - else if (rl_meta_chars && ISMETA(c)) { - TTYput('M'); - TTYput('-'); - TTYput(UNMETA(c)); - } - else - TTYput(c); -} - -static void -TTYstring(char *p) -{ - while (*p) - TTYshow(*p++); -} - -static int -TTYget() -{ - char c; - - TTYflush(); - if (Pushed) { - Pushed = 0; - return PushBack; - } - if (*Input) - return *Input++; - return read(0, &c, (size_t)1) == 1 ? c : EOF; -} - -#define TTYback() (backspace ? TTYputs((const char *)backspace) : TTYput('\b')) - -static void -TTYbackn(int n) -{ - while (--n >= 0) - TTYback(); -} - -static void -TTYinfo() -{ - static int init; -#if defined(USE_TERMCAP) - char *term; - char buff[2048]; - char *bp; - char *p; -#endif /* defined(USE_TERMCAP) */ -#if defined(TIOCGWINSZ) - struct winsize W; -#endif /* defined(TIOCGWINSZ) */ - - if (init) { -#if defined(TIOCGWINSZ) - /* Perhaps we got resized. */ - if (ioctl(0, TIOCGWINSZ, &W) >= 0 - && W.ws_col > 0 && W.ws_row > 0) { - TTYwidth = (int)W.ws_col; - TTYrows = (int)W.ws_row; - } -#endif /* defined(TIOCGWINSZ) */ - return; - } - init++; - - TTYwidth = TTYrows = 0; -#if defined(USE_TERMCAP) - bp = &buff[0]; - if ((term = getenv("TERM")) == NULL) - term = "dumb"; - if (tgetent(buff, term) < 0) { - TTYwidth = SCREEN_WIDTH; - TTYrows = SCREEN_ROWS; - return; - } - p = tgetstr("le", &bp); - backspace = p ? strdup(p) : NULL; - TTYwidth = tgetnum("co"); - TTYrows = tgetnum("li"); -#endif /* defined(USE_TERMCAP) */ - -#if defined(TIOCGWINSZ) - if (ioctl(0, TIOCGWINSZ, &W) >= 0) { - TTYwidth = (int)W.ws_col; - TTYrows = (int)W.ws_row; - } -#endif /* defined(TIOCGWINSZ) */ - - if (TTYwidth <= 0 || TTYrows <= 0) { - TTYwidth = SCREEN_WIDTH; - TTYrows = SCREEN_ROWS; - } -} - - -/* -** Print an array of words in columns. -*/ -static void -columns(int ac, char **av) -{ - char *p; - int i; - int j; - int k; - int len; - int skip; - int longest; - int cols; - - /* Find longest name, determine column count from that. */ - for (longest = 0, i = 0; i < ac; i++) - if ((j = strlen((char *)av[i])) > longest) - longest = j; - cols = TTYwidth / (longest + 3); - - TTYputs((const char *)NEWLINE); - for (skip = ac / cols + 1, i = 0; i < skip; i++) { - for (j = i; j < ac; j += skip) { - for (p = av[j], len = strlen((char *)p), k = len; --k >= 0; p++) - TTYput(*p); - if (j + skip < ac) - while (++len < longest + 3) - TTYput(' '); - } - TTYputs((const char *)NEWLINE); - } -} - -static void -reposition() -{ - int i; - char *p; - - TTYput('\r'); - TTYputs((const char *)Prompt); - for (i = Point, p = Line; --i >= 0; p++) - TTYshow(*p); -} - -static void -left(STATUS Change) -{ - char c; - - TTYback(); - if (Point) { - c = Line[Point - 1]; - if (c == TAB) { - /* XXX */ - } - else if (ISCTL(c)) - TTYback(); - else if (rl_meta_chars && ISMETA(c)) { - TTYback(); - TTYback(); - } - } - if (Change == CSmove) - Point--; -} - -static void -right(STATUS Change) -{ - TTYshow(Line[Point]); - if (Change == CSmove) - Point++; -} - -static STATUS -ring_bell() -{ - TTYput('\07'); - TTYflush(); - return CSstay; -} - -static STATUS -do_macro(int c) -{ - char name[4]; - - name[0] = '_'; - name[1] = c; - name[2] = '_'; - name[3] = '\0'; - - if ((Input = (char *)getenv((char *)name)) == NULL) { - Input = NIL; - return ring_bell(); - } - return CSstay; -} - -static STATUS -do_forward(STATUS move) -{ - int i; - char *p; - - i = 0; - do { - p = &Line[Point]; - for ( ; Point < End && (*p == ' ' || !isalnum((int)*p)); Point++, p++) - if (move == CSmove) - right(CSstay); - - for (; Point < End && isalnum((int)*p); Point++, p++) - if (move == CSmove) - right(CSstay); - - if (Point == End) - break; - } while (++i < Repeat); - - return CSstay; -} - -static STATUS -do_case(CASE type) -{ - int i; - int end; - int count; - char *p; - - (void)do_forward(CSstay); - if (OldPoint != Point) { - if ((count = Point - OldPoint) < 0) - count = -count; - Point = OldPoint; - if ((end = Point + count) > End) - end = End; - for (i = Point, p = &Line[i]; i < end; i++, p++) { - if (type == TOupper) { - if (islower((int)*p)) - *p = toupper((int)*p); - } - else if (isupper((int)*p)) - *p = tolower((int)*p); - right(CSmove); - } - } - return CSstay; -} - -static STATUS -case_down_word() -{ - return do_case(TOlower); -} - -static STATUS -case_up_word() -{ - return do_case(TOupper); -} - -static void -ceol() -{ - int extras; - int i; - char *p; - - for (extras = 0, i = Point, p = &Line[i]; i <= End; i++, p++) { - TTYput(' '); - if (*p == TAB) { - /* XXX */ - } - else if (ISCTL(*p)) { - TTYput(' '); - extras++; - } - else if (rl_meta_chars && ISMETA(*p)) { - TTYput(' '); - TTYput(' '); - extras += 2; - } - } - - for (i += extras; i > Point; i--) - TTYback(); -} - -static void -clear_line() -{ - Point = -strlen(Prompt); - TTYput('\r'); - ceol(); - Point = 0; - End = 0; - Line[0] = '\0'; -} - -static STATUS -insert_string(char *p) -{ - size_t len; - int i; - char *new; - char *q; - - len = strlen((char *)p); - if (End + len >= Length) { - if ((new = malloc(sizeof(char) * (Length + len + MEM_INC))) == NULL) - return CSstay; - if (Length) { - memcpy(new, Line, Length); - free(Line); - } - Line = new; - Length += len + MEM_INC; - } - - for (q = &Line[Point], i = End - Point; --i >= 0; ) - q[len + i] = q[i]; - memcpy(&Line[Point], p, len); - End += len; - Line[End] = '\0'; - TTYstring(&Line[Point]); - Point += len; - - return Point == End ? CSstay : CSmove; -} - -static STATUS -redisplay() -{ - TTYputs((const char *)NEWLINE); - TTYputs((const char *)Prompt); - TTYstring(Line); - return CSmove; -} - -static STATUS -redisplay_no_nl() -{ - TTYput('\r'); - TTYputs((const char *)Prompt); - TTYstring(Line); - return CSmove; -} - -static STATUS -toggle_meta_mode() -{ - rl_meta_chars = !rl_meta_chars; - return redisplay(); -} - - -static char * -next_hist() -{ - return H.Pos >= H.Size - 1 ? NULL : H.Lines[++H.Pos]; -} - -static char * -prev_hist() -{ - return H.Pos == 0 ? NULL : H.Lines[--H.Pos]; -} - -static STATUS -do_insert_hist(char *p) -{ - if (p == NULL) - return ring_bell(); - Point = 0; - reposition(); - ceol(); - End = 0; - return insert_string(p); -} - -static STATUS -do_hist(char *(*move)()) -{ - char *p; - int i; - - i = 0; - do { - if ((p = (*move)()) == NULL) - return ring_bell(); - } while (++i < Repeat); - return do_insert_hist(p); -} - -static STATUS -h_next() -{ - return do_hist(next_hist); -} - -static STATUS -h_prev() -{ - return do_hist(prev_hist); -} - -static STATUS -h_first() -{ - return do_insert_hist(H.Lines[H.Pos = 0]); -} - -static STATUS -h_last() -{ - return do_insert_hist(H.Lines[H.Pos = H.Size - 1]); -} - -/* -** Return zero if pat appears as a substring in text. -*/ -static int -substrcmp(char *text, char *pat,int len) -{ - char c; - - if ((c = *pat) == '\0') - return *text == '\0'; - for ( ; *text; text++) - if (*text == c && strncmp(text, pat, len) == 0) - return 0; - return 1; -} - -static char * -search_hist(char *search,char *(*move)()) -{ - static char *old_search; - int len; - int pos; - int (*match)(); - char *pat; - - /* Save or get remembered search pattern. */ - if (search && *search) { - if (old_search) - free(old_search); - old_search = strdup(search); - } - else { - if (old_search == NULL || *old_search == '\0') - return NULL; - search = old_search; - } - - /* Set up pattern-finder. */ - if (*search == '^') { - match = strncmp; - pat = (char *)(search + 1); - } - else { - match = substrcmp; - pat = (char *)search; - } - len = strlen(pat); - - for (pos = H.Pos; (*move)() != NULL; ) - if ((*match)((char *)H.Lines[H.Pos], pat, len) == 0) - return H.Lines[H.Pos]; - H.Pos = pos; - return NULL; -} - -static STATUS -h_search() -{ - static int Searching; - const char *old_prompt; - char *(*move)(); - char *p; - - if (Searching) - return ring_bell(); - Searching = 1; - - clear_line(); - old_prompt = Prompt; - Prompt = "Search: "; - TTYputs((const char *)Prompt); - move = Repeat == NO_ARG ? prev_hist : next_hist; - p = editinput(); - Searching = 0; - if (p == NULL && Signal > 0) { - Signal = 0; - clear_line(); - Prompt = old_prompt; - return redisplay_no_nl(); - } - p = search_hist(p, move); - clear_line(); - Prompt = old_prompt; - if (p == NULL) { - (void)ring_bell(); - return redisplay_no_nl(); - } - return do_insert_hist(p); -} - -static STATUS -fd_char() -{ - int i; - - i = 0; - do { - if (Point >= End) - break; - right(CSmove); - } while (++i < Repeat); - return CSstay; -} - -static void -save_yank(int begin, int i) -{ - if (Yanked) { - free(Yanked); - Yanked = NULL; - } - - if (i < 1) - return; - - if ((Yanked = malloc(sizeof(char) * (i + 1))) != NULL) { - memcpy(Yanked, &Line[begin], i); - Yanked[i] = '\0'; - } -} - -static STATUS -delete_string(int count) -{ - int i; - char *p; - - if (count <= 0 || End == Point) - return ring_bell(); - - if (count == 1 && Point == End - 1) { - /* Optimize common case of delete at end of line. */ - End--; - p = &Line[Point]; - i = 1; - TTYput(' '); - if (*p == TAB) { - /* XXX */ - } - else if (ISCTL(*p)) { - i = 2; - TTYput(' '); - } - else if (rl_meta_chars && ISMETA(*p)) { - i = 3; - TTYput(' '); - TTYput(' '); - } - TTYbackn(i); - *p = '\0'; - return CSmove; - } - if (Point + count > End && (count = End - Point) <= 0) - return CSstay; - - if (count > 1) - save_yank(Point, count); - - ceol(); - for (p = &Line[Point], i = End - (Point + count) + 1; --i >= 0; p++) - p[0] = p[count]; - End -= count; - TTYstring(&Line[Point]); - return CSmove; -} - -static STATUS -bk_char() -{ - int i; - - i = 0; - do { - if (Point == 0) - break; - left(CSmove); - } while (++i < Repeat); - - return CSstay; -} - -static STATUS -bk_del_char() -{ - int i; - - i = 0; - do { - if (Point == 0) - break; - left(CSmove); - } while (++i < Repeat); - - return delete_string(i); -} - -static STATUS -kill_line() -{ - int i; - - if (Repeat != NO_ARG) { - if (Repeat < Point) { - i = Point; - Point = Repeat; - reposition(); - (void)delete_string(i - Point); - } - else if (Repeat > Point) { - right(CSmove); - (void)delete_string(Repeat - Point - 1); - } - return CSmove; - } - - save_yank(Point, End - Point); - ceol(); - Line[Point] = '\0'; - End = Point; - return CSstay; -} - -static STATUS -insert_char(int c) -{ - STATUS s; - char buff[2]; - char *p; - char *q; - int i; - - if (Repeat == NO_ARG || Repeat < 2) { - buff[0] = c; - buff[1] = '\0'; - return insert_string(buff); - } - - if ((p = malloc(sizeof(char) * (Repeat + 1))) == NULL) - return CSstay; - for (i = Repeat, q = p; --i >= 0; ) - *q++ = c; - *q = '\0'; - Repeat = 0; - s = insert_string(p); - free(p); - return s; -} - -static STATUS -meta() -{ - int c; - KEYMAP *kp; - - if ((c = TTYget()) == EOF) - return CSeof; -#if defined(ANSI_ARROWS) - /* Also include VT-100 arrows. */ - if (c == '[' || c == 'O') - switch ((int)(c = TTYget())) { - default: return ring_bell(); - case EOF: return CSeof; - case 'A': return h_prev(); - case 'B': return h_next(); - case 'C': return fd_char(); - case 'D': return bk_char(); - } -#endif /* defined(ANSI_ARROWS) */ - - if (isdigit(c)) { - for (Repeat = c - '0'; (c = TTYget()) != EOF && isdigit(c); ) - Repeat = Repeat * 10 + c - '0'; - Pushed = 1; - PushBack = c; - return CSstay; - } - - if (isupper(c)) - return do_macro(c); - for (OldPoint = Point, kp = MetaMap; kp < &MetaMap[METAMAPSIZE]; kp++) - if (kp->Key == c && kp->Active) - return (*kp->Function)(); - - return ring_bell(); -} - -static STATUS -emacs(int c) -{ - STATUS s; - KEYMAP *kp; - -#if 0 - /* This test makes it impossible to enter eight-bit characters when - * meta-char mode is enabled. */ - if (rl_meta_chars && ISMETA(c)) { - Pushed = 1; - PushBack = UNMETA(c); - return meta(); - } -#endif /* 0 */ - for (kp = Map; kp < &Map[MAPSIZE]; kp++) - if (kp->Key == c && kp->Active) - break; - s = kp < &Map[MAPSIZE] ? (*kp->Function)() : insert_char((int)c); - if (!Pushed) - /* No pushback means no repeat count; hacky, but true. */ - Repeat = NO_ARG; - return s; -} - -static STATUS -TTYspecial(int c) -{ - if (rl_meta_chars && ISMETA(c)) - return CSdispatch; - - if (c == rl_erase || c == DEL) - return bk_del_char(); - if (c == rl_kill) { - if (Point != 0) { - Point = 0; - reposition(); - } - Repeat = NO_ARG; - return kill_line(); - } - if (c == rl_eof && Point == 0 && End == 0) - return CSeof; - if (c == rl_intr) { - Signal = SIGINT; - return CSsignal; - } - if (c == rl_quit) { - Signal = SIGQUIT; - return CSsignal; - } -#if defined(DO_SIGTSTP) - if (c == rl_susp) { - Signal = SIGTSTP; - return CSsignal; - } -#endif /* defined(DO_SIGTSTP) */ - - return CSdispatch; -} - -static char * -editinput() -{ - int c; - - Repeat = NO_ARG; - OldPoint = Point = Mark = End = 0; - Line[0] = '\0'; - - Signal = -1; - while ((c = TTYget()) != EOF) - switch (TTYspecial(c)) { - case CSdone: - return Line; - case CSeof: - return NULL; - case CSsignal: - return (char *)""; - case CSmove: - reposition(); - break; - case CSdispatch: - switch (emacs(c)) { - case CSdone: - return Line; - case CSeof: - return NULL; - case CSsignal: - return (char *)""; - case CSmove: - reposition(); - break; - case CSdispatch: - case CSstay: - break; - } - break; - case CSstay: - break; - } - return NULL; -} - -static void -hist_add(char *p) -{ - int i; - - if ((p = strdup(p)) == NULL) - return; - if (H.Size < HIST_SIZE) - H.Lines[H.Size++] = p; - else { - free(H.Lines[0]); - for (i = 0; i < HIST_SIZE - 1; i++) - H.Lines[i] = H.Lines[i + 1]; - H.Lines[i] = p; - } - H.Pos = H.Size - 1; -} - -static char * -read_redirected() -{ - int size; - char *p; - char *line; - char *end; - - for (size = MEM_INC, p = line = malloc(sizeof(char) * size), end = p + size; ; p++) { - if (p == end) { - size += MEM_INC; - p = line = realloc(line, size); - end = p + size; - } - if (read(0, p, 1) <= 0) { - /* Ignore "incomplete" lines at EOF, just like we do for a tty. */ - free(line); - return NULL; - } - if (*p == '\n') - break; - } - *p = '\0'; - return line; -} - -/* -** For compatibility with FSF readline. -*/ -/* ARGSUSED0 */ -void -rl_reset_terminal(char *p) -{ - (void)p; /* Suppress warning */ -} - -void -rl_initialize() -{ -} - -int -rl_insert(int count, int c) -{ - if (count > 0) { - Repeat = count; - (void)insert_char(c); - (void)redisplay_no_nl(); - } - return 0; -} - -int (*rl_event_hook)(); - -int -rl_key_action(int c, char flag) -{ - KEYMAP *kp; - int size; - - (void)flag; /* Suppress warning */ - - if (ISMETA(c)) { - kp = MetaMap; - size = METAMAPSIZE; - } - else { - kp = Map; - size = MAPSIZE; - } - for ( ; --size >= 0; kp++) - if (kp->Key == c) { - kp->Active = c ? 1 : 0; - return 1; - } - return -1; -} - -char * -readline(const char *prompt) -{ - char *line; - int s; - - if (!isatty(0)) { - TTYflush(); - return read_redirected(); - } - - if (Line == NULL) { - Length = MEM_INC; - if ((Line = malloc(sizeof(char) * Length)) == NULL) - return NULL; - } - - TTYinfo(); - rl_ttyset(0); - hist_add(NIL); - ScreenSize = SCREEN_INC; - Screen = malloc(sizeof(char) * ScreenSize); - Prompt = prompt ? prompt : (char *)NIL; - TTYputs((const char *)Prompt); - if ((line = editinput()) != NULL) { - line = strdup(line); - TTYputs((const char *)NEWLINE); - TTYflush(); - } - rl_ttyset(1); - free(Screen); - free(H.Lines[--H.Size]); - if (Signal > 0) { - s = Signal; - Signal = 0; - (void)kill(getpid(), s); - } - return (char *)line; -} - -void -add_history(char *p) -{ - if (p == NULL || *p == '\0') - return; - -#if defined(UNIQUE_HISTORY) - if (H.Size && strcmp(p, H.Lines[H.Size - 1]) == 0) - return; -#endif /* defined(UNIQUE_HISTORY) */ - hist_add((char *)p); -} - - -static STATUS -beg_line() -{ - if (Point) { - Point = 0; - return CSmove; - } - return CSstay; -} - -static STATUS -del_char() -{ - return delete_string(Repeat == NO_ARG ? 1 : Repeat); -} - -static STATUS -end_line() -{ - if (Point != End) { - Point = End; - return CSmove; - } - return CSstay; -} - -/* -** Return allocated copy of word under cursor, moving cursor after the -** word. -*/ -static char * -find_word() -{ - static char SEPS[] = "\"#;&|^$=`'{}()<>\n\t "; - char *p; - char *new; - size_t len; - - /* Move forward to end of word. */ - p = &Line[Point]; - for ( ; Point < End && strchr(SEPS, (char)*p) == NULL; Point++, p++) - right(CSstay); - - /* Back up to beginning of word. */ - for (p = &Line[Point]; p > Line && strchr(SEPS, (char)p[-1]) == NULL; p--) - continue; - len = Point - (p - Line) + 1; - if ((new = malloc(sizeof(char) * len)) == NULL) - return NULL; - memcpy(new, p, len); - new[len - 1] = '\0'; - return new; -} - -static STATUS -c_complete() -{ - char *p; - char *word; - int unique; - - word = find_word(); - p = (char *)rl_complete((char *)word, &unique); - if (word) - free(word); - if (p && *p) { - (void)insert_string(p); - if (!unique) - (void)ring_bell(); - free(p); - return redisplay_no_nl(); - } - return ring_bell(); -} - -static STATUS -c_possible() -{ - char **av; - char *word; - int ac; - - word = find_word(); - ac = rl_list_possib((char *)word, (char ***)&av); - if (word) - free(word); - if (ac) { - columns(ac, av); - while (--ac >= 0) - free(av[ac]); - free(av); - return redisplay_no_nl(); - } - return ring_bell(); -} - -static STATUS -accept_line() -{ - Line[End] = '\0'; - return CSdone; -} - -static STATUS -transpose() -{ - char c; - - if (Point) { - if (Point == End) - left(CSmove); - c = Line[Point - 1]; - left(CSstay); - Line[Point - 1] = Line[Point]; - TTYshow(Line[Point - 1]); - Line[Point++] = c; - TTYshow(c); - } - return CSstay; -} - -static STATUS -quote() -{ - int c; - - return (c = TTYget()) == EOF ? CSeof : insert_char((int)c); -} - -static STATUS -wipe() -{ - int i; - - if (Mark > End) - return ring_bell(); - - if (Point > Mark) { - i = Point; - Point = Mark; - Mark = i; - reposition(); - } - - return delete_string(Mark - Point); -} - -static STATUS -mk_set() -{ - Mark = Point; - return CSstay; -} - -static STATUS -exchange() -{ - int c; - - if ((c = TTYget()) != CTL('X')) - return c == EOF ? CSeof : ring_bell(); - - if ((c = Mark) <= End) { - Mark = Point; - Point = c; - return CSmove; - } - return CSstay; -} - -static STATUS -yank() -{ - if (Yanked && *Yanked) - return insert_string(Yanked); - return CSstay; -} - -static STATUS -copy_region() -{ - if (Mark > End) - return ring_bell(); - - if (Point > Mark) - save_yank(Mark, Point - Mark); - else - save_yank(Point, Mark - Point); - - return CSstay; -} - -static STATUS -move_to_char() -{ - int c; - int i; - char *p; - - if ((c = TTYget()) == EOF) - return CSeof; - for (i = Point + 1, p = &Line[i]; i < End; i++, p++) - if (*p == c) { - Point = i; - return CSmove; - } - return CSstay; -} - -static STATUS -fd_word() -{ - return do_forward(CSmove); -} - -static STATUS -fd_kill_word() -{ - int i; - - (void)do_forward(CSstay); - if (OldPoint != Point) { - i = Point - OldPoint; - Point = OldPoint; - return delete_string(i); - } - return CSstay; -} - -static STATUS -bk_word() -{ - int i; - char *p; - - i = 0; - do { - for (p = &Line[Point]; p > Line && !isalnum((int)p[-1]); p--) - left(CSmove); - - for (; p > Line && p[-1] != ' ' && isalnum((int)p[-1]); p--) - left(CSmove); - - if (Point == 0) - break; - } while (++i < Repeat); - - return CSstay; -} - -static STATUS -bk_kill_word() -{ - (void)bk_word(); - if (OldPoint != Point) - return delete_string(OldPoint - Point); - return CSstay; -} - -static int -argify(char *line, char ***avp) -{ - char *c; - char **p; - char **new; - int ac; - int i; - - i = MEM_INC; - if ((*avp = p = malloc(sizeof(char*) * i))== NULL) - return 0; - - for (c = line; isspace((int)*c); c++) - continue; - if (*c == '\n' || *c == '\0') - return 0; - - for (ac = 0, p[ac++] = c; *c && *c != '\n'; ) { - if (isspace((int)*c)) { - *c++ = '\0'; - if (*c && *c != '\n') { - if (ac + 1 == i) { - new = malloc(sizeof(char*) * (i + MEM_INC)); - if (new == NULL) { - p[ac] = NULL; - return ac; - } - memcpy(new, p, i * sizeof (char **)); - i += MEM_INC; - free(p); - *avp = p = new; - } - p[ac++] = c; - } - } - else - c++; - } - *c = '\0'; - p[ac] = NULL; - return ac; -} - -static STATUS -last_argument() -{ - char **av; - char *p; - STATUS s; - int ac; - - if (H.Size == 1 || (p = H.Lines[H.Size - 2]) == NULL) - return ring_bell(); - - if ((p = strdup(p)) == NULL) - return CSstay; - ac = argify(p, &av); - - if (Repeat != NO_ARG) - s = Repeat < ac ? insert_string(av[Repeat]) : ring_bell(); - else - s = ac ? insert_string(av[ac - 1]) : CSstay; - - if (ac) - free(av); - free(p); - return s; -} - -static KEYMAP Map[MAPSIZE] = { - { CTL('@'), 1, ring_bell }, - { CTL('A'), 1, beg_line }, - { CTL('B'), 1, bk_char }, - { CTL('D'), 1, del_char }, - { CTL('E'), 1, end_line }, - { CTL('F'), 1, fd_char }, - { CTL('G'), 1, ring_bell }, - { CTL('H'), 1, bk_del_char }, - { CTL('I'), 1, c_complete }, - { CTL('J'), 1, accept_line }, - { CTL('K'), 1, kill_line }, - { CTL('L'), 1, redisplay }, - { CTL('M'), 1, accept_line }, - { CTL('N'), 1, h_next }, - { CTL('O'), 1, ring_bell }, - { CTL('P'), 1, h_prev }, - { CTL('Q'), 1, ring_bell }, - { CTL('R'), 1, h_search }, - { CTL('S'), 1, ring_bell }, - { CTL('T'), 1, transpose }, - { CTL('U'), 1, ring_bell }, - { CTL('V'), 1, quote }, - { CTL('W'), 1, wipe }, - { CTL('X'), 1, exchange }, - { CTL('Y'), 1, yank }, - { CTL('Z'), 1, ring_bell }, - { CTL('['), 1, meta }, - { CTL(']'), 1, move_to_char }, - { CTL('^'), 1, ring_bell }, - { CTL('_'), 1, ring_bell }, -}; - -static KEYMAP MetaMap[16]= { - { CTL('H'), 1, bk_kill_word }, - { CTL('['), 1, c_possible }, - { DEL, 1, bk_kill_word }, - { ' ', 1, mk_set }, - { '.', 1, last_argument }, - { '<', 1, h_first }, - { '>', 1, h_last }, - { '?', 1, c_possible }, - { 'b', 1, bk_word }, - { 'd', 1, fd_kill_word }, - { 'f', 1, fd_word }, - { 'l', 1, case_down_word }, - { 'm', 1, toggle_meta_mode}, - { 'u', 1, case_up_word }, - { 'y', 1, yank }, - { 'w', 1, copy_region }, -}; diff --git a/ndb/src/common/editline/editline_internal.h b/ndb/src/common/editline/editline_internal.h deleted file mode 100644 index d82fa91c44b..00000000000 --- a/ndb/src/common/editline/editline_internal.h +++ /dev/null @@ -1,30 +0,0 @@ -/* $Revision: 1.2 $ -** -** Internal header file for editline library. -*/ - -#include <ndb_global.h> - -#if defined(SYS_UNIX) -#include "unix.h" -#endif /* defined(SYS_UNIX) */ - -#define MEM_INC 64 -#define SCREEN_INC 256 - -/* -** Variables and routines internal to this package. -*/ -extern int rl_eof; -extern int rl_erase; -extern int rl_intr; -extern int rl_kill; -extern int rl_quit; -#if defined(DO_SIGTSTP) -extern int rl_susp; -#endif /* defined(DO_SIGTSTP) */ -extern char *rl_complete(); -extern int rl_list_possib(); -extern void rl_ttyset(); -extern void rl_add_slash(); - diff --git a/ndb/src/common/editline/sysunix.c b/ndb/src/common/editline/sysunix.c deleted file mode 100644 index b0242fb99ce..00000000000 --- a/ndb/src/common/editline/sysunix.c +++ /dev/null @@ -1,132 +0,0 @@ -/* $Revision: 1.4 $ -** -** Unix system-dependant routines for editline library. -*/ -#include "editline_internal.h" - -#if defined(HAVE_TCGETATTR) -#include <termios.h> - -void -rl_ttyset(int Reset) -{ - static struct termios old; - struct termios new; - - if (Reset == 0) { - if (tcgetattr(0, &old) < 0) perror("tcgetattr"); - rl_erase = old.c_cc[VERASE]; - rl_kill = old.c_cc[VKILL]; - rl_eof = old.c_cc[VEOF]; - rl_intr = old.c_cc[VINTR]; - rl_quit = old.c_cc[VQUIT]; -#if defined(DO_SIGTSTP) - rl_susp = old.c_cc[VSUSP]; -#endif /* defined(DO_SIGTSTP) */ - - new = old; - new.c_lflag &= ~(ECHO | ICANON | ISIG); - new.c_iflag &= ~(ISTRIP | INPCK); - new.c_cc[VMIN] = 1; - new.c_cc[VTIME] = 0; - if (tcsetattr(0, TCSADRAIN, &new) < 0) perror("tcsetattr"); - } - else - (void)tcsetattr(0, TCSADRAIN, &old); -} - -#else -#if defined(HAVE_TERMIO) -#include <termio.h> - -void -rl_ttyset(int Reset) -{ - static struct termio old; - struct termio new; - - if (Reset == 0) { - (void)ioctl(0, TCGETA, &old); - rl_erase = old.c_cc[VERASE]; - rl_kill = old.c_cc[VKILL]; - rl_eof = old.c_cc[VEOF]; - rl_intr = old.c_cc[VINTR]; - rl_quit = old.c_cc[VQUIT]; -#if defined(DO_SIGTSTP) - rl_susp = old.c_cc[VSUSP]; -#endif /* defined(DO_SIGTSTP) */ - - new = old; - new.c_lflag &= ~(ECHO | ICANON | ISIG); - new.c_iflag &= ~(ISTRIP | INPCK); - new.c_cc[VMIN] = 1; - new.c_cc[VTIME] = 0; - (void)ioctl(0, TCSETAW, &new); - } - else - (void)ioctl(0, TCSETAW, &old); -} - -#else -#include <sgtty.h> - -void -rl_ttyset(int Reset) -{ - static struct sgttyb old_sgttyb; - static struct tchars old_tchars; - struct sgttyb new_sgttyb; - struct tchars new_tchars; -#if defined(DO_SIGTSTP) - struct ltchars old_ltchars; -#endif /* defined(DO_SIGTSTP) */ - - if (Reset == 0) { - (void)ioctl(0, TIOCGETP, &old_sgttyb); - rl_erase = old_sgttyb.sg_erase; - rl_kill = old_sgttyb.sg_kill; - - (void)ioctl(0, TIOCGETC, &old_tchars); - rl_eof = old_tchars.t_eofc; - rl_intr = old_tchars.t_intrc; - rl_quit = old_tchars.t_quitc; - -#if defined(DO_SIGTSTP) - (void)ioctl(0, TIOCGLTC, &old_ltchars); - rl_susp = old_ltchars.t_suspc; -#endif /* defined(DO_SIGTSTP) */ - - new_sgttyb = old_sgttyb; - new_sgttyb.sg_flags &= ~ECHO; - new_sgttyb.sg_flags |= RAW; -#if defined(PASS8) - new_sgttyb.sg_flags |= PASS8; -#endif /* defined(PASS8) */ - (void)ioctl(0, TIOCSETP, &new_sgttyb); - - new_tchars = old_tchars; - new_tchars.t_intrc = -1; - new_tchars.t_quitc = -1; - (void)ioctl(0, TIOCSETC, &new_tchars); - } - else { - (void)ioctl(0, TIOCSETP, &old_sgttyb); - (void)ioctl(0, TIOCSETC, &old_tchars); - } -} -#endif /* defined(HAVE_TERMIO) */ -#endif /* defined(HAVE_TCGETATTR) */ - -void -rl_add_slash(char *path, char *p, size_t p_len) -{ - struct stat Sb; - - if (stat(path, &Sb) >= 0) { - size_t len= strlen(p); - if (len+1 < p_len) { - p[len]= S_ISDIR(Sb.st_mode) ? '/' : ' '; - p[len+1]= 0; - } - } -} diff --git a/ndb/src/common/editline/test/Makefile b/ndb/src/common/editline/test/Makefile deleted file mode 100644 index 20229d0aa62..00000000000 --- a/ndb/src/common/editline/test/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -include .defs.mk - -TYPE := util - -BIN_TARGET := editline_test -BIN_TARGET_ARCHIVES := editline - -SOURCES = testit.c - -include $(NDB_TOP)/Epilogue.mk diff --git a/ndb/src/common/editline/unix.h b/ndb/src/common/editline/unix.h deleted file mode 100644 index c2fde7547b3..00000000000 --- a/ndb/src/common/editline/unix.h +++ /dev/null @@ -1,9 +0,0 @@ -/* $Revision: 1.3 $ -** -** Editline system header file for Unix. -*/ - -#define CRLF "\r\n" - -#include <ndb_global.h> -#include <dirent.h> diff --git a/ndb/src/common/logger/Makefile_old b/ndb/src/common/logger/Makefile_old deleted file mode 100644 index 994eb86ba35..00000000000 --- a/ndb/src/common/logger/Makefile_old +++ /dev/null @@ -1,27 +0,0 @@ -include .defs.mk - -TYPE := ndbapi - -PIC_ARCHIVE := Y -ARCHIVE_TARGET := logger - -DIRS := loggertest - -SOURCES := Logger.cpp LogHandlerList.cpp LogHandler.cpp \ - ConsoleLogHandler.cpp FileLogHandler.cpp - -ifeq ($(NDB_OS), OSE) -NO_SYSLOG := Y -endif - -ifeq ($(NDB_OS), WIN32) -NO_SYSLOG := Y -endif - -ifneq ($(NO_SYSLOG), Y) -SOURCES += SysLogHandler.cpp -endif - -include $(NDB_TOP)/Epilogue.mk - - diff --git a/ndb/src/common/mgmcommon/LocalConfig.cpp b/ndb/src/common/mgmcommon/LocalConfig.cpp index 3cd4341c6b7..679de716be0 100644 --- a/ndb/src/common/mgmcommon/LocalConfig.cpp +++ b/ndb/src/common/mgmcommon/LocalConfig.cpp @@ -90,7 +90,7 @@ LocalConfig::init(const char *connectString, //7. Check { char buf[256]; - BaseString::snprintf(buf, sizeof(buf), "host=localhost:%s", NDB_BASE_PORT); + BaseString::snprintf(buf, sizeof(buf), "host=localhost:%s", NDB_PORT); if(readConnectString(buf, "default connect string")) return true; } @@ -124,12 +124,12 @@ void LocalConfig::printUsage() const { ndbout << "1. Put a Ndb.cfg file in the directory where you start"<<endl << " the node. "<< endl << " Ex: Ndb.cfg" << endl - << " | host=localhost:"<<NDB_BASE_PORT<<endl; + << " | host=localhost:"<<NDB_PORT<<endl; ndbout << "2. Use the environment variable NDB_CONNECTSTRING to "<<endl << " provide this information." <<endl << " Ex: " << endl - << " >export NDB_CONNECTSTRING=\"host=localhost:"<<NDB_BASE_PORT<<"\"" + << " >export NDB_CONNECTSTRING=\"host=localhost:"<<NDB_PORT<<"\"" <<endl<<endl; } diff --git a/ndb/src/common/mgmcommon/Makefile.am b/ndb/src/common/mgmcommon/Makefile.am index ed6a526eb47..b787da51ab9 100644 --- a/ndb/src/common/mgmcommon/Makefile.am +++ b/ndb/src/common/mgmcommon/Makefile.am @@ -7,7 +7,7 @@ libmgmsrvcommon_la_SOURCES = \ INCLUDES_LOC = -I$(top_srcdir)/ndb/src/mgmapi -I$(top_srcdir)/ndb/src/mgmsrv -DEFS_LOC = -DNDB_BASE_PORT="\"@ndb_port_base@\"" +DEFS_LOC = -DNDB_PORT="\"@ndb_port@\"" include $(top_srcdir)/ndb/config/common.mk.am include $(top_srcdir)/ndb/config/type_ndbapi.mk.am diff --git a/ndb/src/common/mgmcommon/Makefile_old b/ndb/src/common/mgmcommon/Makefile_old deleted file mode 100644 index c7bfda7e3bf..00000000000 --- a/ndb/src/common/mgmcommon/Makefile_old +++ /dev/null @@ -1,29 +0,0 @@ -include .defs.mk - -TYPE := ndbapi mgmapiclient - -PIC_ARCHIVE := Y -ARCHIVE_TARGET := mgmsrvcommon - -# Removed temporary -DIRS := printConfig - -SOURCES = \ - LocalConfig.cpp \ - Config.cpp \ - ConfigInfo.cpp \ - ConfigRetriever.cpp \ - InitConfigFileParser.cpp \ - IPCConfig.cpp - -SOURCES.c = NdbConfig.c - -CFLAGS_IPCConfig.cpp := -I$(call fixpath,$(NDB_TOP)/src/mgmapi) - -include $(NDB_TOP)/Epilogue.mk - - - - - - diff --git a/ndb/src/common/mgmcommon/NdbConfig.c b/ndb/src/common/mgmcommon/NdbConfig.c index e92f8fa8392..8adc4c20dff 100644 --- a/ndb/src/common/mgmcommon/NdbConfig.c +++ b/ndb/src/common/mgmcommon/NdbConfig.c @@ -74,7 +74,7 @@ NdbConfig_NdbCfgName(int with_ndb_home){ static char *get_prefix_buf(int len, int node_id) { - char tmp_buf[sizeof("ndb_pid#########")+1]; + char tmp_buf[sizeof("ndb_pid#############")+1]; char *buf; if (node_id > 0) snprintf(tmp_buf, sizeof(tmp_buf), "ndb_%u", node_id); diff --git a/ndb/src/common/portlib/Makefile_old b/ndb/src/common/portlib/Makefile_old deleted file mode 100644 index 48f4929a839..00000000000 --- a/ndb/src/common/portlib/Makefile_old +++ /dev/null @@ -1,21 +0,0 @@ -include .defs.mk - -DIRS := - -ifeq ($(NDB_OS), SOFTOSE) -DIRS += ose -else -ifeq ($(NDB_OS), OSE) -DIRS += ose -else -ifeq ($(NDB_OS), WIN32) -DIRS += win32 -else -DIRS += unix -endif -endif -endif - - -include $(NDB_TOP)/Epilogue.mk - diff --git a/ndb/src/common/portlib/NdbDaemon.c b/ndb/src/common/portlib/NdbDaemon.c index c73b5927ff4..3f1c1998501 100644 --- a/ndb/src/common/portlib/NdbDaemon.c +++ b/ndb/src/common/portlib/NdbDaemon.c @@ -55,18 +55,21 @@ NdbDaemon_Make(const char* lockfile, const char* logfile, unsigned flags) "%s: lseek failed: %s", lockfile, strerror(errno)); return -1; } +#ifdef F_TLOCK /* Test for lock before becoming daemon */ - if (lockf(lockfd, F_TEST, 0) == -1) { - if (errno == EACCES || errno == EAGAIN) { /* results may vary */ + if (lockf(lockfd, F_TLOCK, 0) == -1) + { + if (errno == EACCES || errno == EAGAIN) { /* results may vary */ snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize, - "%s: already locked by pid=%ld", lockfile, NdbDaemon_DaemonPid); + "%s: already locked by pid=%ld", lockfile, NdbDaemon_DaemonPid); return -1; } NdbDaemon_ErrorCode = errno; snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize, - "%s: lock test failed: %s", lockfile, strerror(errno)); + "%s: lock test failed: %s", lockfile, strerror(errno)); return -1; } +#endif /* Test open log file before becoming daemon */ if (logfile != NULL) { logfd = open(logfile, O_CREAT|O_WRONLY|O_APPEND, 0644); @@ -77,6 +80,15 @@ NdbDaemon_Make(const char* lockfile, const char* logfile, unsigned flags) return -1; } } +#ifdef F_TLOCK + if (lockf(lockfd, F_ULOCK, 0) == -1) + { + snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize, + "%s: fail to unlock", lockfile); + return -1; + } +#endif + /* Fork */ n = fork(); if (n == -1) { diff --git a/ndb/src/common/portlib/old_dirs/unix/Makefile_old b/ndb/src/common/portlib/old_dirs/unix/Makefile_old deleted file mode 100644 index 452196d9f08..00000000000 --- a/ndb/src/common/portlib/old_dirs/unix/Makefile_old +++ /dev/null @@ -1,27 +0,0 @@ -include .defs.mk - -TYPE := util - -PIC_ARCHIVE := Y -ARCHIVE_TARGET := portlib - -SOURCES.c = NdbCondition.c \ - NdbMutex.c \ - NdbSleep.c \ - NdbTick.c \ - NdbEnv.c \ - NdbThread.c \ - NdbHost.c \ - NdbTCP.c \ - NdbDaemon.c - -ifeq ($(NDB_OS), SOFTOSE) - SOURCES += NdbMem_SoftOse.cpp -else - SOURCES.c += NdbMem.c -endif - -include $(NDB_TOP)/Epilogue.mk - -testNdbDaemon: NdbDaemon.c - $(CC) -o $@ NdbDaemon.c $(CCFLAGS) -DNDB_DAEMON_TEST -L$(NDB_TOP)/lib diff --git a/ndb/src/common/transporter/Makefile_old b/ndb/src/common/transporter/Makefile_old deleted file mode 100644 index 372bf640566..00000000000 --- a/ndb/src/common/transporter/Makefile_old +++ /dev/null @@ -1,43 +0,0 @@ -include .defs.mk - -TYPE := util - -PIC_ARCHIVE := Y -ARCHIVE_TARGET := transporter -DIRS := basictest perftest - -# Source files of non-templated classes (.cpp files) -SOURCES = \ - Transporter.cpp \ - SendBuffer.cpp \ - TCP_Transporter.cpp \ - TransporterRegistry.cpp \ - Packer.cpp - -DIRS := basictest perftest - -CCFLAGS_LOC += -I$(call fixpath,$(NDB_TOP)/include/kernel) \ - -I$(call fixpath,$(NDB_TOP)/include/transporter) - - -ifeq ($(NDB_SHM), Y) -SOURCES += SHM_Transporter.cpp -ifeq ($(NDB_OS), WIN32) -SOURCES += SHM_Transporter.win32.cpp -else -SOURCES += SHM_Transporter.unix.cpp -endif -endif - -ifeq ($(NDB_SCI), Y) -SOURCES += SCI_Transporter.cpp -endif - -ifneq ($(findstring OSE, $(NDB_OS)),) - SOURCES += OSE_Transporter.cpp - SOURCES += OSE_Receiver.cpp -endif - - - -include $(NDB_TOP)/Epilogue.mk diff --git a/ndb/src/common/util/Makefile_old b/ndb/src/common/util/Makefile_old deleted file mode 100644 index 65093396246..00000000000 --- a/ndb/src/common/util/Makefile_old +++ /dev/null @@ -1,28 +0,0 @@ -include .defs.mk - -TYPE := util - -PIC_ARCHIVE := Y -ARCHIVE_TARGET := general - -SOURCES = File.cpp md5_hash.cpp Properties.cpp socket_io.cpp \ - SimpleProperties.cpp Parser.cpp InputStream.cpp SocketServer.cpp \ - OutputStream.cpp NdbOut.cpp BaseString.cpp Base64.cpp \ - NdbSqlUtil.cpp ConfigValues.cpp new.cpp - -SOURCES.c = uucode.c random.c getarg.c version.c - -ifeq ($(NDB_OS), OSE) - SOURCES += NdbErrHnd.cpp -endif -ifeq ($(NDB_OS), OSE) - SOURCES += NdbErrHnd.cpp -endif - SOURCES.c += strdup.c strlcat.c strlcpy.c - -DIRS := testSimpleProperties testProperties testConfigValues - -include $(NDB_TOP)/Epilogue.mk - -testNdbSqlUtil: NdbSqlUtil.cpp - $(CC) -o $@ NdbSqlUtil.cpp $(CCFLAGS) -DNDB_SQL_UTIL_TEST -L$(NDB_TOP)/lib -lportlib -lgeneral diff --git a/ndb/src/common/util/SocketServer.cpp b/ndb/src/common/util/SocketServer.cpp index c3cffa1399b..8bee256684d 100644 --- a/ndb/src/common/util/SocketServer.cpp +++ b/ndb/src/common/util/SocketServer.cpp @@ -259,6 +259,15 @@ transfer(NDB_SOCKET_TYPE sock){ } void +SocketServer::foreachSession(void (*func)(SocketServer::Session*, void *), void *data) +{ + for(int i = m_sessions.size() - 1; i >= 0; i--){ + (*func)(m_sessions[i].m_session, data); + } + checkSessions(); +} + +void SocketServer::checkSessions(){ for(int i = m_sessions.size() - 1; i >= 0; i--){ if(m_sessions[i].m_session->m_stopped){ @@ -278,8 +287,10 @@ void SocketServer::stopSessions(bool wait){ int i; for(i = m_sessions.size() - 1; i>=0; i--) - m_sessions[i].m_session->m_stop = true; - + { + m_sessions[i].m_session->stopSession(); + m_sessions[i].m_session->m_stop = true; // to make sure + } for(i = m_services.size() - 1; i>=0; i--) m_services[i].m_service->stopSessions(); diff --git a/ndb/src/common/util/basestring_vsnprintf.c b/ndb/src/common/util/basestring_vsnprintf.c index 7307279f345..8a58ca0fe5c 100644 --- a/ndb/src/common/util/basestring_vsnprintf.c +++ b/ndb/src/common/util/basestring_vsnprintf.c @@ -20,6 +20,10 @@ #include <basestring_vsnprintf.h> #include <my_config.h> + +/* + #define SNPRINTF_RETURN_TRUNC +*/ int basestring_snprintf(char *str, size_t size, const char *format, ...) { @@ -40,7 +44,6 @@ basestring_snprintf(char *str, size_t size, const char *format, ...) * Let's hope vsnprintf works anyways */ #define BASESTRING_VSNPRINTF_FUNC(a,b,c,d) vsnprintf(a,b,c,d) - extern int my_vsnprintf(char *str, size_t size, const char *format, va_list ap); #endif #ifdef SNPRINTF_RETURN_TRUNC static char basestring_vsnprintf_buf[16*1024]; @@ -48,13 +51,27 @@ static char basestring_vsnprintf_buf[16*1024]; int basestring_vsnprintf(char *str, size_t size, const char *format, va_list ap) { - int ret= BASESTRING_VSNPRINTF_FUNC(str, size, format, ap); + if (size == 0) + { #ifdef SNPRINTF_RETURN_TRUNC - if (ret == size-1 || ret == -1) { - ret= BASESTRING_VSNPRINTF_FUNC(basestring_vsnprintf_buf, - sizeof(basestring_vsnprintf_buf), - format, ap); + return BASESTRING_VSNPRINTF_FUNC(basestring_vsnprintf_buf, + sizeof(basestring_vsnprintf_buf), + format, ap); +#else + char buf[1]; + return BASESTRING_VSNPRINTF_FUNC(buf, 1, format, ap); +#endif } + { + int ret= BASESTRING_VSNPRINTF_FUNC(str, size, format, ap); +#ifdef SNPRINTF_RETURN_TRUNC + if (ret == size-1 || ret == -1) + { + ret= BASESTRING_VSNPRINTF_FUNC(basestring_vsnprintf_buf, + sizeof(basestring_vsnprintf_buf), + format, ap); + } #endif - return ret; + return ret; + } } diff --git a/ndb/src/cw/Makefile_old b/ndb/src/cw/Makefile_old deleted file mode 100644 index e710c1e244d..00000000000 --- a/ndb/src/cw/Makefile_old +++ /dev/null @@ -1,6 +0,0 @@ -include .defs.mk - -DIRS := cpcd - -include $(NDB_TOP)/Epilogue.mk - diff --git a/ndb/src/cw/cpcd/Makefile_old b/ndb/src/cw/cpcd/Makefile_old deleted file mode 100644 index f214fb087d2..00000000000 --- a/ndb/src/cw/cpcd/Makefile_old +++ /dev/null @@ -1,11 +0,0 @@ -include .defs.mk - -TYPE := util -BIN_TARGET := ndb_cpcd - -# Source files of non-templated classes (.cpp files) -SOURCES = main.cpp CPCD.cpp Process.cpp APIService.cpp Monitor.cpp common.cpp - -BIN_TARGET_LIBS += logger - -include $(NDB_TOP)/Epilogue.mk diff --git a/ndb/src/kernel/Makefile_old b/ndb/src/kernel/Makefile_old deleted file mode 100644 index d1f1741aca4..00000000000 --- a/ndb/src/kernel/Makefile_old +++ /dev/null @@ -1,5 +0,0 @@ -include .defs.mk - -DIRS := error vm ndb-main blocks - -include $(NDB_TOP)/Epilogue.mk diff --git a/ndb/src/kernel/blocks/Makefile_old b/ndb/src/kernel/blocks/Makefile_old deleted file mode 100644 index ce554dfc3b8..00000000000 --- a/ndb/src/kernel/blocks/Makefile_old +++ /dev/null @@ -1,28 +0,0 @@ -#-------------------------------------------------------------------------- -# -# Name Makefile -# -# -# -# List subdirectories to be travered -include .defs.mk - -DIRS := \ - cmvmi \ - dbacc \ - dbdict \ - dbdih \ - dblqh \ - dbtc \ - dbtup \ - ndbfs \ - ndbcntr \ - qmgr \ - trix \ - backup \ - dbutil \ - suma \ - grep \ - dbtux - -include ${NDB_TOP}/Epilogue.mk diff --git a/ndb/src/kernel/blocks/backup/Makefile_old b/ndb/src/kernel/blocks/backup/Makefile_old deleted file mode 100644 index 989199cbe02..00000000000 --- a/ndb/src/kernel/blocks/backup/Makefile_old +++ /dev/null @@ -1,18 +0,0 @@ -include .defs.mk - -TYPE := kernel - -#ifneq ($(MYSQLCLUSTER_TOP),) -DIRS := restore -#endif - -ARCHIVE_TARGET := backup - -SOURCES = Backup.cpp BackupInit.cpp - -include $(NDB_TOP)/Epilogue.mk - -$(NDB_TOP)/bin/readBackupFile: read.o - $(C++) -o $@ read.o \ - $(NDB_TOP)/lib/libportlib.a $(NDB_TOP)/lib/libgeneral.a - diff --git a/ndb/src/kernel/blocks/cmvmi/Makefile_old b/ndb/src/kernel/blocks/cmvmi/Makefile_old deleted file mode 100644 index d75e5dbf08b..00000000000 --- a/ndb/src/kernel/blocks/cmvmi/Makefile_old +++ /dev/null @@ -1,9 +0,0 @@ -include .defs.mk - -TYPE := kernel - -ARCHIVE_TARGET := cmvmi - -SOURCES = Cmvmi.cpp - -include $(NDB_TOP)/Epilogue.mk diff --git a/ndb/src/kernel/blocks/dbacc/Makefile_old b/ndb/src/kernel/blocks/dbacc/Makefile_old deleted file mode 100644 index 93a830cec95..00000000000 --- a/ndb/src/kernel/blocks/dbacc/Makefile_old +++ /dev/null @@ -1,11 +0,0 @@ -include .defs.mk - -TYPE := kernel - -ARCHIVE_TARGET := dbacc - -SOURCES = \ - DbaccInit.cpp \ - DbaccMain.cpp - -include $(NDB_TOP)/Epilogue.mk diff --git a/ndb/src/kernel/blocks/dbdict/Makefile_old b/ndb/src/kernel/blocks/dbdict/Makefile_old deleted file mode 100644 index 46d938114fb..00000000000 --- a/ndb/src/kernel/blocks/dbdict/Makefile_old +++ /dev/null @@ -1,12 +0,0 @@ -include .defs.mk - -TYPE := kernel - -ARCHIVE_TARGET := dbdict - -SOURCES = \ - Dbdict.cpp - -DIRS := printSchemafile - -include $(NDB_TOP)/Epilogue.mk diff --git a/ndb/src/kernel/blocks/dbdih/Makefile_old b/ndb/src/kernel/blocks/dbdih/Makefile_old deleted file mode 100644 index 83c1b95b5c4..00000000000 --- a/ndb/src/kernel/blocks/dbdih/Makefile_old +++ /dev/null @@ -1,13 +0,0 @@ -include .defs.mk - -TYPE := kernel - -ARCHIVE_TARGET := dbdih - -DIRS := printSysfile - -SOURCES = \ - DbdihInit.cpp \ - DbdihMain.cpp - -include $(NDB_TOP)/Epilogue.mk diff --git a/ndb/src/kernel/blocks/dblqh/Makefile_old b/ndb/src/kernel/blocks/dblqh/Makefile_old deleted file mode 100644 index 520486d8058..00000000000 --- a/ndb/src/kernel/blocks/dblqh/Makefile_old +++ /dev/null @@ -1,12 +0,0 @@ -include .defs.mk - -TYPE := kernel - -ARCHIVE_TARGET := dblqh -DIRS := redoLogReader - -SOURCES = \ - DblqhInit.cpp \ - DblqhMain.cpp - -include $(NDB_TOP)/Epilogue.mk diff --git a/ndb/src/kernel/blocks/dbtc/Makefile_old b/ndb/src/kernel/blocks/dbtc/Makefile_old deleted file mode 100644 index ae876ab1f84..00000000000 --- a/ndb/src/kernel/blocks/dbtc/Makefile_old +++ /dev/null @@ -1,11 +0,0 @@ -include .defs.mk - -TYPE := kernel - -ARCHIVE_TARGET := dbtc -SOURCES = \ - DbtcInit.cpp \ - DbtcMain.cpp - -include $(NDB_TOP)/Epilogue.mk - diff --git a/ndb/src/kernel/blocks/dbtup/Makefile_old b/ndb/src/kernel/blocks/dbtup/Makefile_old deleted file mode 100644 index 87146f4b441..00000000000 --- a/ndb/src/kernel/blocks/dbtup/Makefile_old +++ /dev/null @@ -1,26 +0,0 @@ -include .defs.mk - -TYPE := kernel - -ARCHIVE_TARGET := dbtup -SOURCES = \ - DbtupExecQuery.cpp \ - DbtupBuffer.cpp \ - DbtupRoutines.cpp \ - DbtupCommit.cpp \ - DbtupFixAlloc.cpp \ - DbtupTrigger.cpp \ - DbtupAbort.cpp \ - DbtupLCP.cpp \ - DbtupUndoLog.cpp \ - DbtupPageMap.cpp \ - DbtupPagMan.cpp \ - DbtupStoredProcDef.cpp \ - DbtupMeta.cpp \ - DbtupTabDesMan.cpp \ - DbtupGen.cpp \ - DbtupSystemRestart.cpp \ - DbtupIndex.cpp \ - DbtupDebug.cpp - -include $(NDB_TOP)/Epilogue.mk diff --git a/ndb/src/kernel/blocks/dbtux/Makefile_old b/ndb/src/kernel/blocks/dbtux/Makefile_old deleted file mode 100644 index 30927c31848..00000000000 --- a/ndb/src/kernel/blocks/dbtux/Makefile_old +++ /dev/null @@ -1,17 +0,0 @@ -include .defs.mk - -TYPE = kernel - -ARCHIVE_TARGET = dbtux - -SOURCES = \ - DbtuxGen.cpp \ - DbtuxMeta.cpp \ - DbtuxMaint.cpp \ - DbtuxNode.cpp \ - DbtuxTree.cpp \ - DbtuxScan.cpp \ - DbtuxCmp.cpp \ - DbtuxDebug.cpp - -include $(NDB_TOP)/Epilogue.mk diff --git a/ndb/src/kernel/blocks/dbutil/Makefile_old b/ndb/src/kernel/blocks/dbutil/Makefile_old deleted file mode 100644 index 54b7326e4e5..00000000000 --- a/ndb/src/kernel/blocks/dbutil/Makefile_old +++ /dev/null @@ -1,8 +0,0 @@ -include .defs.mk - -TYPE := kernel - -ARCHIVE_TARGET := dbutil -SOURCES = DbUtil.cpp - -include $(NDB_TOP)/Epilogue.mk diff --git a/ndb/src/kernel/blocks/grep/Makefile_old b/ndb/src/kernel/blocks/grep/Makefile_old deleted file mode 100644 index 5ad5a0bce3b..00000000000 --- a/ndb/src/kernel/blocks/grep/Makefile_old +++ /dev/null @@ -1,9 +0,0 @@ -include .defs.mk - -TYPE := kernel - -ARCHIVE_TARGET := grep - -SOURCES = Grep.cpp GrepInit.cpp - -include $(NDB_TOP)/Epilogue.mk diff --git a/ndb/src/kernel/blocks/ndbcntr/Makefile_old b/ndb/src/kernel/blocks/ndbcntr/Makefile_old deleted file mode 100644 index 8e9c4f01027..00000000000 --- a/ndb/src/kernel/blocks/ndbcntr/Makefile_old +++ /dev/null @@ -1,12 +0,0 @@ -include .defs.mk - -TYPE := kernel - -ARCHIVE_TARGET := ndbcntr - -SOURCES = \ - NdbcntrInit.cpp \ - NdbcntrSysTable.cpp \ - NdbcntrMain.cpp - -include $(NDB_TOP)/Epilogue.mk diff --git a/ndb/src/kernel/blocks/ndbfs/Makefile_old b/ndb/src/kernel/blocks/ndbfs/Makefile_old deleted file mode 100644 index 58e1458bf16..00000000000 --- a/ndb/src/kernel/blocks/ndbfs/Makefile_old +++ /dev/null @@ -1,14 +0,0 @@ -include .defs.mk - -TYPE := kernel - -ARCHIVE_TARGET := ndbfs - -SOURCES = \ - AsyncFile.cpp \ - Ndbfs.cpp VoidFs.cpp \ - Filename.cpp \ - CircularIndex.cpp - -include $(NDB_TOP)/Epilogue.mk - diff --git a/ndb/src/kernel/blocks/qmgr/Makefile_old b/ndb/src/kernel/blocks/qmgr/Makefile_old deleted file mode 100644 index cd15643ea60..00000000000 --- a/ndb/src/kernel/blocks/qmgr/Makefile_old +++ /dev/null @@ -1,11 +0,0 @@ -include .defs.mk - -TYPE := kernel - -ARCHIVE_TARGET := qmgr - -SOURCES = \ - QmgrInit.cpp \ - QmgrMain.cpp - -include $(NDB_TOP)/Epilogue.mk diff --git a/ndb/src/kernel/blocks/suma/Makefile_old b/ndb/src/kernel/blocks/suma/Makefile_old deleted file mode 100644 index 20014c94670..00000000000 --- a/ndb/src/kernel/blocks/suma/Makefile_old +++ /dev/null @@ -1,10 +0,0 @@ -include .defs.mk - -TYPE := kernel - -ARCHIVE_TARGET := suma - -SOURCES = Suma.cpp SumaInit.cpp - -include $(NDB_TOP)/Epilogue.mk - diff --git a/ndb/src/kernel/blocks/trix/Makefile_old b/ndb/src/kernel/blocks/trix/Makefile_old deleted file mode 100644 index 5ac0da11f33..00000000000 --- a/ndb/src/kernel/blocks/trix/Makefile_old +++ /dev/null @@ -1,8 +0,0 @@ -include .defs.mk - -TYPE := kernel - -ARCHIVE_TARGET := trix -SOURCES = Trix.cpp - -include $(NDB_TOP)/Epilogue.mk diff --git a/ndb/src/kernel/error/Makefile_old b/ndb/src/kernel/error/Makefile_old deleted file mode 100644 index 0fe81f083ce..00000000000 --- a/ndb/src/kernel/error/Makefile_old +++ /dev/null @@ -1,12 +0,0 @@ -include .defs.mk - -TYPE := kernel - -ARCHIVE_TARGET := error - -SOURCES = \ - TimeModule.cpp \ - ErrorReporter.cpp \ - ErrorMessages.cpp - -include $(NDB_TOP)/Epilogue.mk diff --git a/ndb/src/kernel/vm/Makefile_old b/ndb/src/kernel/vm/Makefile_old deleted file mode 100644 index a162f3672ce..00000000000 --- a/ndb/src/kernel/vm/Makefile_old +++ /dev/null @@ -1,30 +0,0 @@ -include .defs.mk - -TYPE := kernel - -ARCHIVE_TARGET := kernel - -SOURCES = \ - SimulatedBlock.cpp \ - FastScheduler.cpp \ - TimeQueue.cpp \ - VMSignal.cpp \ - ThreadConfig.cpp \ - TransporterCallback.cpp \ - Emulator.cpp \ - Configuration.cpp \ - WatchDog.cpp \ - SimplePropertiesSection.cpp \ - SectionReader.cpp \ - MetaData.cpp \ - Mutex.cpp SafeCounter.cpp - -CFLAGS_Configuration.cpp := -I$(call fixpath,$(NDB_TOP)/src/mgmapi) - -DIRS := testCopy testDataBuffer testSimplePropertiesSection - -ifneq ($(USE_EDITLINE), N) -DIRS += testLongSig -endif - -include $(NDB_TOP)/Epilogue.mk diff --git a/ndb/src/mgmapi/Makefile_old b/ndb/src/mgmapi/Makefile_old deleted file mode 100644 index fa734f998e6..00000000000 --- a/ndb/src/mgmapi/Makefile_old +++ /dev/null @@ -1,27 +0,0 @@ -include .defs.mk - -TYPE := util - -PIC_ARCHIVE := Y -ARCHIVE_TARGET := mgmapi - -A_LIB := Y -SO_LIB := Y -PIC_LIB := Y - -#DIRS := test - -LIB_TARGET := MGM_API -LIB_TARGET_ARCHIVES := $(ARCHIVE_TARGET) general portlib - -# Source files of non-templated classes (.C files) -SOURCES = mgmapi.cpp mgmapi_configuration.cpp - -CCFLAGS_LOC += -I$(call fixpath,$(NDB_TOP)/include/mgmapi) \ - -I$(call fixpath,$(NDB_TOP)/src/common/mgmcommon) - -CCFLAGS += -DNO_DEBUG_MESSAGES - -# -I$(NDB_TOP)/src/common/mgmcommon - -include $(NDB_TOP)/Epilogue.mk diff --git a/ndb/src/mgmapi/mgmapi.cpp b/ndb/src/mgmapi/mgmapi.cpp index 4b62df968b3..66f0dbb1842 100644 --- a/ndb/src/mgmapi/mgmapi.cpp +++ b/ndb/src/mgmapi/mgmapi.cpp @@ -1834,4 +1834,46 @@ ndb_mgm_set_string_parameter(NdbMgmHandle handle, return res; } +extern "C" +int +ndb_mgm_purge_stale_sessions(NdbMgmHandle handle, char **purged){ + CHECK_HANDLE(handle, 0); + CHECK_CONNECTED(handle, 0); + + Properties args; + + const ParserRow<ParserDummy> reply[]= { + MGM_CMD("purge stale sessions reply", NULL, ""), + MGM_ARG("purged", String, Optional, ""), + MGM_ARG("result", String, Mandatory, "Error message"), + MGM_END() + }; + + const Properties *prop; + prop= ndb_mgm_call(handle, reply, "purge stale sessions", &args); + + if(prop == NULL) { + SET_ERROR(handle, EIO, "Unable to purge stale sessions"); + return -1; + } + + int res= -1; + do { + const char * buf; + if(!prop->get("result", &buf) || strcmp(buf, "Ok") != 0){ + ndbout_c("ERROR Message: %s\n", buf); + break; + } + if (purged) { + if (prop->get("purged", &buf)) + *purged= strdup(buf); + else + *purged= 0; + } + res= 0; + } while(0); + delete prop; + return res; +} + template class Vector<const ParserRow<ParserDummy>*>; diff --git a/ndb/src/mgmclient/CommandInterpreter.cpp b/ndb/src/mgmclient/CommandInterpreter.cpp index e0935c2104e..fde4e5a2e91 100644 --- a/ndb/src/mgmclient/CommandInterpreter.cpp +++ b/ndb/src/mgmclient/CommandInterpreter.cpp @@ -17,7 +17,195 @@ #include <ndb_global.h> #include <my_sys.h> -#include "CommandInterpreter.hpp" +//#define HAVE_GLOBAL_REPLICATION + +#include <Vector.hpp> +#ifdef HAVE_GLOBAL_REPLICATION +#include "../rep/repapi/repapi.h" +#endif + +#include <mgmapi.h> + +class MgmtSrvr; + +/** + * @class CommandInterpreter + * @brief Reads command line in management client + * + * This class has one public method which reads a command line + * from a stream. It then interpret that commmand line and calls a suitable + * method in the MgmtSrvr class which executes the command. + * + * For command syntax, see the HELP command. + */ +class CommandInterpreter { +public: + /** + * Constructor + * @param mgmtSrvr: Management server to use when executing commands + */ + CommandInterpreter(const char *); + ~CommandInterpreter(); + + /** + * Reads one line from the stream, parse the line to find + * a command and then calls a suitable method which executes + * the command. + * + * @return true until quit/bye/exit has been typed + */ + int execute(const char *_line, int _try_reconnect=-1); + +private: + void printError(); + + /** + * Analyse the command line, after the first token. + * + * @param processId: DB process id to send command to or -1 if + * command will be sent to all DB processes. + * @param allAfterFirstToken: What the client gave after the + * first token on the command line + */ + void analyseAfterFirstToken(int processId, char* allAfterFirstTokenCstr); + + /** + * Parse the block specification part of the LOG* commands, + * things after LOG*: [BLOCK = {ALL|<blockName>+}] + * + * @param allAfterLog: What the client gave after the second token + * (LOG*) on the command line + * @param blocks, OUT: ALL or name of all the blocks + * @return: true if correct syntax, otherwise false + */ + bool parseBlockSpecification(const char* allAfterLog, + Vector<const char*>& blocks); + + /** + * A bunch of execute functions: Executes one of the commands + * + * @param processId: DB process id to send command to + * @param parameters: What the client gave after the command name + * on the command line. + * For example if complete input from user is: "1 LOGLEVEL 22" then the + * parameters argument is the string with everything after LOGLEVEL, in + * this case "22". Each function is responsible to check the parameters + * argument. + */ + void executeHelp(char* parameters); + void executeShow(char* parameters); + void executePurge(char* parameters); + void executeShutdown(char* parameters); + void executeRun(char* parameters); + void executeInfo(char* parameters); + void executeClusterLog(char* parameters); + +public: + void executeStop(int processId, const char* parameters, bool all); + void executeEnterSingleUser(char* parameters); + void executeExitSingleUser(char* parameters); + void executeStart(int processId, const char* parameters, bool all); + void executeRestart(int processId, const char* parameters, bool all); + void executeLogLevel(int processId, const char* parameters, bool all); + void executeError(int processId, const char* parameters, bool all); + void executeTrace(int processId, const char* parameters, bool all); + void executeLog(int processId, const char* parameters, bool all); + void executeLogIn(int processId, const char* parameters, bool all); + void executeLogOut(int processId, const char* parameters, bool all); + void executeLogOff(int processId, const char* parameters, bool all); + void executeTestOn(int processId, const char* parameters, bool all); + void executeTestOff(int processId, const char* parameters, bool all); + void executeSet(int processId, const char* parameters, bool all); + void executeGetStat(int processId, const char* parameters, bool all); + void executeStatus(int processId, const char* parameters, bool all); + void executeEventReporting(int processId, const char* parameters, bool all); + void executeDumpState(int processId, const char* parameters, bool all); + void executeStartBackup(char * parameters); + void executeAbortBackup(char * parameters); + + void executeRep(char* parameters); + + void executeCpc(char * parameters); + +public: + bool connect(); + bool disconnect(); + + /** + * A execute function definition + */ +public: + typedef void (CommandInterpreter::* ExecuteFunction)(int processId, + const char * param, + bool all); + + struct CommandFunctionPair { + const char * command; + ExecuteFunction executeFunction; + }; +private: + /** + * + */ + void executeForAll(const char * cmd, + ExecuteFunction fun, + const char * param); + + NdbMgmHandle m_mgmsrv; + bool connected; + const char *host; + int try_reconnect; +#ifdef HAVE_GLOBAL_REPLICATION + NdbRepHandle m_repserver; + const char *rep_host; + bool rep_connected; +#endif +}; + + +/* + * Facade object for CommandInterpreter + */ + +#include "ndb_mgmclient.hpp" +#include "ndb_mgmclient.h" + +Ndb_mgmclient::Ndb_mgmclient(const char *host) +{ + m_cmd= new CommandInterpreter(host); +} +Ndb_mgmclient::~Ndb_mgmclient() +{ + delete m_cmd; +} +int Ndb_mgmclient::execute(const char *_line, int _try_reconnect) +{ + return m_cmd->execute(_line,_try_reconnect); +} +int +Ndb_mgmclient::disconnect() +{ + return m_cmd->disconnect(); +} + +extern "C" { + Ndb_mgmclient_handle ndb_mgmclient_handle_create(const char *connect_string) + { + return (Ndb_mgmclient_handle) new Ndb_mgmclient(connect_string); + } + int ndb_mgmclient_execute(Ndb_mgmclient_handle h, int argc, const char** argv) + { + return ((Ndb_mgmclient*)h)->execute(argc, argv, 1); + } + int ndb_mgmclient_handle_destroy(Ndb_mgmclient_handle h) + { + delete (Ndb_mgmclient*)h; + return 0; + } +} +/* + * The CommandInterpreter + */ #include <mgmapi.h> #include <mgmapi_debug.h> @@ -33,8 +221,22 @@ #endif // HAVE_GLOBAL_REPLICATION #include "MgmtErrorReporter.hpp" -#include "CpcClient.hpp" +#include <Parser.hpp> +#include <SocketServer.hpp> +#include <util/InputStream.hpp> +#include <util/OutputStream.hpp> +int Ndb_mgmclient::execute(int argc, const char** argv, int _try_reconnect) +{ + if (argc <= 0) + return 0; + BaseString _line(argv[0]); + for (int i= 1; i < argc; i++) + { + _line.appfmt(" %s", argv[i]); + } + return m_cmd->execute(_line.c_str(),_try_reconnect); +} /***************************************************************************** * HELP @@ -73,6 +275,7 @@ static const char* helpText = #ifdef HAVE_GLOBAL_REPLICATION "REP CONNECT <host:port> Connect to REP server on host:port\n" #endif +"PURGE STALE SESSIONS Reset reserved nodeid's in the mgmt server\n" "QUIT Quit management client\n" ; @@ -201,7 +404,7 @@ CommandInterpreter::~CommandInterpreter() host = NULL; } -bool +static bool emptyString(const char* s) { if (s == NULL) { @@ -264,18 +467,15 @@ CommandInterpreter::disconnect() //***************************************************************************** int -CommandInterpreter::readAndExecute(int _try_reconnect) +CommandInterpreter::execute(const char *_line, int _try_reconnect) { if (_try_reconnect >= 0) try_reconnect=_try_reconnect; - - char* _line = readline_gets(); char * line; if(_line == NULL) { // ndbout << endl; return false; } - line = my_strdup(_line,MYF(MY_WME)); My_auto_ptr<char> ptr(line); @@ -320,6 +520,10 @@ CommandInterpreter::readAndExecute(int _try_reconnect) executeAbortBackup(allAfterFirstToken); return true; } + else if (strcmp(firstToken, "PURGE") == 0) { + executePurge(allAfterFirstToken); + return true; + } #ifdef HAVE_GLOBAL_REPLICATION else if(strcmp(firstToken, "REPLICATION") == 0 || strcmp(firstToken, "REP") == 0) { @@ -349,10 +553,6 @@ CommandInterpreter::readAndExecute(int _try_reconnect) strcmp(firstToken, "BYE") == 0) && allAfterFirstToken == NULL){ return false; -#if 0 - } else if(strcmp(firstToken, "CPC") == 0) { - executeCpc(allAfterFirstToken); -#endif } else { /** * First token should be a digit, node ID @@ -766,6 +966,46 @@ print_nodes(ndb_mgm_cluster_state *state, ndb_mgm_configuration_iterator *it, } void +CommandInterpreter::executePurge(char* parameters) +{ + int command_ok= 0; + do { + if (emptyString(parameters)) + break; + char* firstToken = strtok(parameters, " "); + char* nextToken = strtok(NULL, " \0"); + if (strcmp(firstToken,"STALE") == 0 && + nextToken && + strcmp(nextToken, "SESSIONS") == 0) { + command_ok= 1; + break; + } + } while(0); + + if (!command_ok) { + ndbout_c("Unexpected command, expected: PURGE STALE SESSIONS"); + return; + } + + int i; + char *str; + connect(); + + if (ndb_mgm_purge_stale_sessions(m_mgmsrv, &str)) { + ndbout_c("Command failed"); + return; + } + if (str) { + ndbout_c("Purged sessions with node id's: %s", str); + free(str); + } + else + { + ndbout_c("No sessions purged"); + } +} + +void CommandInterpreter::executeShow(char* parameters) { int i; @@ -1903,169 +2143,4 @@ CommandInterpreter::executeRep(char* parameters) } #endif // HAVE_GLOBAL_REPLICATION - -/***************************************************************************** - * CPC - *****************************************************************************/ - -#if 0 - -#if 0 -//#ifdef NDB_SOLARIS // XXX fix me -static char* strsep(char** x, const char* y) { return 0; } -#endif - -// Note this code has not been verified -#if 0 -static char * my_strsep(char **stringp, const char *delim) -{ - char *tmp= *stringp; - if (tmp == 0) - return 0; - *stringp = strtok(tmp, delim); - return tmp; -} -#endif - -void -CommandInterpreter::executeCpc(char *parameters) -{ - char *host_str = NULL, *port_str = NULL, *end; - long port = 1234; /* XXX */ - - while((host_str = my_strsep(¶meters, " \t:")) != NULL && - host_str[0] == '\0'); - - if(parameters && parameters[0] != '\0') { - while((port_str = my_strsep(¶meters, " \t:")) != NULL && - port_str[0] == '\0'); - - errno = 0; - port = strtol(port_str, &end, 0); - if(end[0] != '\0') - goto error; - if((port == LONG_MAX || port == LONG_MIN) && - errno == ERANGE) - goto error; - } - - { - SimpleCpcClient cpc(host_str, port); - bool done = false; - - if(cpc.connect() < 0) { - ndbout_c("Cannot connect to %s:%d.", cpc.getHost(), cpc.getPort()); - switch(errno) { - case ENOENT: - ndbout << ": " << "No such host" << endl; - break; - default: - ndbout << ": " << strerror(errno) << endl; - break; - } - return; - } - - while(!done) { - char *line = readline("CPC> "); - if(line != NULL) { - add_history(line); - - char *cmd = strtok(line, " "); - char *arg = strtok(NULL, ""); - - if(arg != NULL) { - while(arg[0] == ' ') - arg++; - if(strlen(arg) == 0) - arg = NULL; - } - - if(cmd != NULL) { - if(strcmp(cmd, "exit") == 0) - done = true; - else if(strcmp(cmd, "list") == 0) - cpc.cmd_list(arg); - else if(strcmp(cmd, "start") == 0) - cpc.cmd_start(arg); - else if(strcmp(cmd, "stop") == 0) - cpc.cmd_stop(arg); - else if(strcmp(cmd, "help") == 0) - cpc.cmd_help(arg); - } - } else { - done = true; - ndbout << endl; - } - } - } - return; - - error: - ndbout << "Error: expected a tcp port number, got '" << port_str << "'." - << endl; - return; -} -#endif - -#if 0 -static -void -CmdBackupCallback(const MgmtSrvr::BackupEvent & event){ - char str[255]; - - ndbout << endl; - - bool ok = false; - switch(event.Event){ - case MgmtSrvr::BackupEvent::BackupStarted: - ok = true; - BaseString::snprintf(str, sizeof(str), - "Backup %d started", event.Started.BackupId); - break; - case MgmtSrvr::BackupEvent::BackupFailedToStart: - ok = true; - BaseString::snprintf(str, sizeof(str), - "Backup failed to start (Error %d)", - event.FailedToStart.ErrorCode); - break; - case MgmtSrvr::BackupEvent::BackupCompleted: - ok = true; - BaseString::snprintf(str, sizeof(str), - "Backup %d completed", - event.Completed.BackupId); - ndbout << str << endl; - - BaseString::snprintf(str, sizeof(str), - " StartGCP: %d StopGCP: %d", - event.Completed.startGCP, event.Completed.stopGCP); - ndbout << str << endl; - - BaseString::snprintf(str, sizeof(str), - " #Records: %d #LogRecords: %d", - event.Completed.NoOfRecords, event.Completed.NoOfLogRecords); - ndbout << str << endl; - - BaseString::snprintf(str, sizeof(str), - " Data: %d bytes Log: %d bytes", - event.Completed.NoOfBytes, event.Completed.NoOfLogBytes); - break; - case MgmtSrvr::BackupEvent::BackupAborted: - ok = true; - BaseString::snprintf(str, sizeof(str), - "Backup %d has been aborted reason %d", - event.Aborted.BackupId, - event.Aborted.Reason); - break; - } - if(!ok){ - BaseString::snprintf(str, sizeof(str), - "Unknown backup event: %d", - event.Event); - - } - ndbout << str << endl; -} -#endif - template class Vector<char const*>; diff --git a/ndb/src/mgmclient/CommandInterpreter.hpp b/ndb/src/mgmclient/CommandInterpreter.hpp deleted file mode 100644 index eecc48a739e..00000000000 --- a/ndb/src/mgmclient/CommandInterpreter.hpp +++ /dev/null @@ -1,197 +0,0 @@ -/* Copyright (C) 2003 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; either version 2 of the License, 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 */ - -#ifndef CommandInterpreter_H -#define CommandInterpreter_H - -//#define HAVE_GLOBAL_REPLICATION -//***************************************************************************** -// Author: Peter Lind -//***************************************************************************** - -#include <ndb_global.h> -#include <Vector.hpp> -#include <editline/editline.h> - -#ifdef HAVE_GLOBAL_REPLICATION -#include "../rep/repapi/repapi.h" -#endif - -#include <mgmapi.h> - -class MgmtSrvr; - -/** - * @class CommandInterpreter - * @brief Reads command line in management client - * - * This class has one public method which reads a command line - * from a stream. It then interpret that commmand line and calls a suitable - * method in the MgmtSrvr class which executes the command. - * - * For command syntax, see the HELP command. - */ -class CommandInterpreter { -public: - /** - * Constructor - * @param mgmtSrvr: Management server to use when executing commands - */ - CommandInterpreter(const char *); - ~CommandInterpreter(); - - /** - * Reads one line from the stream, parse the line to find - * a command and then calls a suitable method which executes - * the command. - * - * @return true until quit/bye/exit has been typed - */ - int readAndExecute(int _try_reconnect=-1); - -private: - /** - * Read a string, and return a pointer to it. - * - * @return NULL on EOF. - */ - char *readline_gets () - { - static char *line_read = (char *)NULL; - - /* If the buffer has already been allocated, return the memory - to the free pool. */ - if (line_read) - { - free (line_read); - line_read = (char *)NULL; - } - - /* Get a line from the user. */ - line_read = readline ("NDB> "); - - /* If the line has any text in it, save it on the history. */ - if (line_read && *line_read) - add_history (line_read); - - return (line_read); - } - - void printError(); - - /** - * Analyse the command line, after the first token. - * - * @param processId: DB process id to send command to or -1 if - * command will be sent to all DB processes. - * @param allAfterFirstToken: What the client gave after the - * first token on the command line - */ - void analyseAfterFirstToken(int processId, char* allAfterFirstTokenCstr); - - /** - * Parse the block specification part of the LOG* commands, - * things after LOG*: [BLOCK = {ALL|<blockName>+}] - * - * @param allAfterLog: What the client gave after the second token - * (LOG*) on the command line - * @param blocks, OUT: ALL or name of all the blocks - * @return: true if correct syntax, otherwise false - */ - bool parseBlockSpecification(const char* allAfterLog, - Vector<const char*>& blocks); - - /** - * A bunch of execute functions: Executes one of the commands - * - * @param processId: DB process id to send command to - * @param parameters: What the client gave after the command name - * on the command line. - * For example if complete input from user is: "1 LOGLEVEL 22" then the - * parameters argument is the string with everything after LOGLEVEL, in - * this case "22". Each function is responsible to check the parameters - * argument. - */ - void executeHelp(char* parameters); - void executeShow(char* parameters); - void executeShutdown(char* parameters); - void executeRun(char* parameters); - void executeInfo(char* parameters); - void executeClusterLog(char* parameters); - -public: - void executeStop(int processId, const char* parameters, bool all); - void executeEnterSingleUser(char* parameters); - void executeExitSingleUser(char* parameters); - void executeStart(int processId, const char* parameters, bool all); - void executeRestart(int processId, const char* parameters, bool all); - void executeLogLevel(int processId, const char* parameters, bool all); - void executeError(int processId, const char* parameters, bool all); - void executeTrace(int processId, const char* parameters, bool all); - void executeLog(int processId, const char* parameters, bool all); - void executeLogIn(int processId, const char* parameters, bool all); - void executeLogOut(int processId, const char* parameters, bool all); - void executeLogOff(int processId, const char* parameters, bool all); - void executeTestOn(int processId, const char* parameters, bool all); - void executeTestOff(int processId, const char* parameters, bool all); - void executeSet(int processId, const char* parameters, bool all); - void executeGetStat(int processId, const char* parameters, bool all); - void executeStatus(int processId, const char* parameters, bool all); - void executeEventReporting(int processId, const char* parameters, bool all); - void executeDumpState(int processId, const char* parameters, bool all); - void executeStartBackup(char * parameters); - void executeAbortBackup(char * parameters); - - void executeRep(char* parameters); - - void executeCpc(char * parameters); - -public: - bool connect(); - bool disconnect(); - - /** - * A execute function definition - */ -public: - typedef void (CommandInterpreter::* ExecuteFunction)(int processId, - const char * param, - bool all); - - struct CommandFunctionPair { - const char * command; - ExecuteFunction executeFunction; - }; -private: - /** - * - */ - void executeForAll(const char * cmd, - ExecuteFunction fun, - const char * param); - - NdbMgmHandle m_mgmsrv; - bool connected; - const char *host; - int try_reconnect; -#ifdef HAVE_GLOBAL_REPLICATION - NdbRepHandle m_repserver; - const char *rep_host; - bool rep_connected; -#endif -}; - -#endif // CommandInterpreter_H diff --git a/ndb/src/mgmclient/Makefile.am b/ndb/src/mgmclient/Makefile.am index e271c7bed53..cd6ddb0ad57 100644 --- a/ndb/src/mgmclient/Makefile.am +++ b/ndb/src/mgmclient/Makefile.am @@ -1,18 +1,19 @@ +noinst_LTLIBRARIES = libndbmgmclient.la ndbtools_PROGRAMS = ndb_mgm -ndb_mgm_SOURCES = \ - main.cpp \ - CommandInterpreter.cpp \ - CpcClient.cpp +libndbmgmclient_la_SOURCES = CommandInterpreter.cpp + +ndb_mgm_SOURCES = main.cpp include $(top_srcdir)/ndb/config/common.mk.am include $(top_srcdir)/ndb/config/type_ndbapi.mk.am INCLUDES += -I$(top_srcdir)/ndb/include/mgmapi -I$(top_srcdir)/ndb/src/common/mgmcommon -LDADD_LOC = $(top_builddir)/ndb/src/libndbclient.la \ - $(top_builddir)/ndb/src/common/editline/libeditline.a \ +LDADD_LOC = $(noinst_LTLIBRARIES) \ + @readline_link@ \ + $(top_builddir)/ndb/src/libndbclient.la \ $(top_builddir)/dbug/libdbug.a \ $(top_builddir)/mysys/libmysys.a \ $(top_builddir)/strings/libmystrings.a \ diff --git a/ndb/src/mgmclient/Makefile_old b/ndb/src/mgmclient/Makefile_old deleted file mode 100644 index d1b2d60a52a..00000000000 --- a/ndb/src/mgmclient/Makefile_old +++ /dev/null @@ -1,25 +0,0 @@ -include .defs.mk - -TYPE := ndbapi - -BIN_TARGET := mgmtclient -BIN_TARGET_LIBS := -BIN_TARGET_ARCHIVES := trace logger mgmapi general mgmsrvcommon portlib repapi - -BIN_TARGET_ARCHIVES += editline - -DIRS = test_cpcd - -# Source files of non-templated classes (.cpp files) -SOURCES = \ - main.cpp \ - CommandInterpreter.cpp \ - CpcClient.cpp - -CCFLAGS_LOC += -I$(call fixpath,$(NDB_TOP)/include/mgmapi) \ - -I$(call fixpath,$(NDB_TOP)/src/common/mgmcommon) - -include $(NDB_TOP)/Epilogue.mk - -_bins_mkconfig : $(NDB_TOP)/bin/$(BIN_TARGET) - diff --git a/ndb/src/mgmclient/main.cpp b/ndb/src/mgmclient/main.cpp index a37214d366b..8f5d9e6656c 100644 --- a/ndb/src/mgmclient/main.cpp +++ b/ndb/src/mgmclient/main.cpp @@ -17,18 +17,29 @@ #include <ndb_global.h> #include <ndb_opts.h> +// copied from mysql.cc to get readline +extern "C" { +#if defined( __WIN__) || defined(OS2) +#include <conio.h> +#elif !defined(__NETWARE__) +#include <readline/readline.h> +extern "C" int add_history(const char *command); /* From readline directory */ +#define HAVE_READLINE +#endif +} + #include <NdbMain.h> #include <NdbHost.h> #include <mgmapi.h> #include <ndb_version.h> #include <LocalConfig.hpp> -#include "CommandInterpreter.hpp" +#include "ndb_mgmclient.hpp" const char *progname = "ndb_mgm"; -static CommandInterpreter* com; +static Ndb_mgmclient* com; extern "C" void @@ -90,6 +101,39 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), return 0; } +static int +read_and_execute(int _try_reconnect) +{ + static char *line_read = (char *)NULL; + + /* If the buffer has already been allocated, return the memory + to the free pool. */ + if (line_read) + { + free (line_read); + line_read = (char *)NULL; + } +#ifdef HAVE_READLINE + /* Get a line from the user. */ + line_read = readline ("ndb_mgm> "); + /* If the line has any text in it, save it on the history. */ + if (line_read && *line_read) + add_history (line_read); +#else + static char linebuffer[254]; + fputs("ndb_mgm> ", stdout); + linebuffer[sizeof(linebuffer)-1]=0; + line_read = fgets(linebuffer, sizeof(linebuffer)-1, stdin); + if (line_read == linebuffer) { + char *q=linebuffer; + while (*q > 31) q++; + *q=0; + line_read= strdup(linebuffer); + } +#endif + return com->execute(line_read,_try_reconnect); +} + int main(int argc, char** argv){ NDB_INIT(argv[0]); const char *_host = 0; @@ -127,8 +171,8 @@ int main(int argc, char** argv){ signal(SIGPIPE, handler); - com = new CommandInterpreter(buf); - while(com->readAndExecute(_try_reconnect)); + com = new Ndb_mgmclient(buf); + while(read_and_execute(_try_reconnect)); delete com; return 0; diff --git a/ndb/src/common/editline/test/testit.c b/ndb/src/mgmclient/ndb_mgmclient.h index 4058f8ae660..265e6bc67ec 100644 --- a/ndb/src/common/editline/test/testit.c +++ b/ndb/src/mgmclient/ndb_mgmclient.h @@ -14,42 +14,20 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* -*- c-basic-offset: 4; -*- -** $Revision: 1.5 $ -** -** A "micro-shell" to test editline library. -** If given any arguments, commands aren't executed. -*/ -#include <ndb_global.h> -#include <editline/editline.h> - -int -main(int argc, char **argv) -{ - char *prompt; - char *p; - int doit; - - (void)argv; /* Suppress warning */ - - doit = argc == 1; - if ((prompt = getenv("TESTPROMPT")) == NULL) - prompt = "testit> "; - - while ((p = readline(prompt)) != NULL) { - (void)printf("\t\t\t|%s|\n", p); - if (doit) { - if (strncmp(p, "cd ", 3) == 0) { - if (chdir(&p[3]) < 0) - perror(&p[3]); - } else { - if (system(p) != 0) - perror(p); - } - } - add_history(p); - free(p); - } - - return 0; +#ifndef Ndb_mgmclient_h +#define Ndb_mgmclient_h + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void* Ndb_mgmclient_handle; +Ndb_mgmclient_handle ndb_mgmclient_handle_create(const char *connect_string); +int ndb_mgmclient_execute(Ndb_mgmclient_handle, int argc, const char** argv); +int ndb_mgmclient_handle_destroy(Ndb_mgmclient_handle); + +#ifdef __cplusplus } +#endif + +#endif /* Ndb_mgmclient_h */ diff --git a/ndb/src/common/editline/editline_win32.c b/ndb/src/mgmclient/ndb_mgmclient.hpp index 5083edb7fae..933d1bab5ce 100644 --- a/ndb/src/common/editline/editline_win32.c +++ b/ndb/src/mgmclient/ndb_mgmclient.hpp @@ -14,19 +14,20 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#ifndef Ndb_mgmclient_hpp +#define Ndb_mgmclient_hpp -#include <ndb_global.h> - - -char* readline(const char* prompt) +class CommandInterpreter; +class Ndb_mgmclient { - char* szBuf; - printf(prompt); - szBuf = (char*)malloc(256); - return gets(szBuf); -} - -void add_history(char* pch) -{ -} - +public: + Ndb_mgmclient(const char*); + ~Ndb_mgmclient(); + int execute(const char *_line, int _try_reconnect=-1); + int execute(int argc, const char** argv, int _try_reconnect=-1); + int disconnect(); +private: + CommandInterpreter *m_cmd; +}; + +#endif // Ndb_mgmclient_hpp diff --git a/ndb/src/mgmsrv/CommandInterpreter.hpp b/ndb/src/mgmsrv/CommandInterpreter.hpp index 3466ee76226..db23f76a5bd 100644 --- a/ndb/src/mgmsrv/CommandInterpreter.hpp +++ b/ndb/src/mgmsrv/CommandInterpreter.hpp @@ -23,7 +23,6 @@ #include <ndb_global.h> #include <Vector.hpp> -#include <editline/editline.h> #include <BaseString.hpp> class MgmtSrvr; @@ -63,26 +62,27 @@ private: */ char *readline_gets () { + static char linebuffer[254]; static char *line_read = (char *)NULL; - // Disable the default file-name completion action of TAB - // rl_bind_key ('\t', rl_insert); - /* If the buffer has already been allocated, return the memory to the free pool. */ if (line_read) - { - free (line_read); - line_read = (char *)NULL; - } + { + free (line_read); + line_read = (char *)NULL; + } /* Get a line from the user. */ - line_read = readline ("NDB> "); - - /* If the line has any text in it, save it on the history. */ - if (line_read && *line_read) - add_history (line_read); - + fputs("ndb_mgmd> ", stdout); + linebuffer[sizeof(linebuffer)-1]=0; + line_read = fgets(linebuffer, sizeof(linebuffer)-1, stdin); + if (line_read == linebuffer) { + char *q=linebuffer; + while (*q > 31) q++; + *q=0; + line_read= strdup(linebuffer); + } return (line_read); } diff --git a/ndb/src/mgmsrv/ConfigInfo.cpp b/ndb/src/mgmsrv/ConfigInfo.cpp index ad346b30ead..4af1556a0c0 100644 --- a/ndb/src/mgmsrv/ConfigInfo.cpp +++ b/ndb/src/mgmsrv/ConfigInfo.cpp @@ -1478,7 +1478,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::USED, false, ConfigInfo::INT, - NDB_BASE_PORT, + NDB_PORT, "0", STR_VALUE(MAX_INT_RNIL) }, @@ -1490,7 +1490,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::USED, false, ConfigInfo::INT, - "2199", + UNDEFINED, "0", STR_VALUE(MAX_INT_RNIL) }, @@ -3010,7 +3010,7 @@ fixPortNumber(InitConfigFileParser::Context & ctx, const char * data){ if(!(ctx.m_userDefaults && ctx.m_userDefaults->get("PortNumber", &base)) && !ctx.m_systemDefaults->get("PortNumber", &base)) { - base= strtoll(NDB_BASE_PORT,0,0)+2; + base= strtoll(NDB_BASE_PORT,0,0); // ctx.reportError("Cannot retrieve base port number"); // return false; } @@ -3442,7 +3442,7 @@ static bool add_server_ports(Vector<ConfigInfo::ConfigRuleSection>§ions, #if 0 Properties * props= ctx.m_config; Properties computers(true); - Uint32 port_base = NDB_BASE_PORT+2; + Uint32 port_base = NDB_BASE_PORT; Uint32 nNodes; ctx.m_userProperties.get("NoOfNodes", &nNodes); diff --git a/ndb/src/mgmsrv/Makefile.am b/ndb/src/mgmsrv/Makefile.am index 3b57b027827..ee5220ef9f8 100644 --- a/ndb/src/mgmsrv/Makefile.am +++ b/ndb/src/mgmsrv/Makefile.am @@ -24,7 +24,6 @@ INCLUDES_LOC = -I$(top_srcdir)/ndb/src/ndbapi \ -I$(top_srcdir)/ndb/src/common/mgmcommon LDADD_LOC = $(top_builddir)/ndb/src/libndbclient.la \ - $(top_builddir)/ndb/src/common/editline/libeditline.a \ $(top_builddir)/dbug/libdbug.a \ $(top_builddir)/mysys/libmysys.a \ $(top_builddir)/strings/libmystrings.a @NDB_SCI_LIBS@ @@ -34,6 +33,7 @@ DEFS_LOC = -DDEFAULT_MYSQL_HOME="\"$(MYSQLBASEdir)\"" \ -DDATADIR="\"$(MYSQLDATAdir)\"" \ -DSHAREDIR="\"$(MYSQLSHAREdir)\"" \ -DMYSQLCLUSTERDIR="\"$(MYSQLCLUSTERdir)\"" \ + -DNDB_PORT="\"@ndb_port@\"" \ -DNDB_BASE_PORT="\"@ndb_port_base@\"" include $(top_srcdir)/ndb/config/common.mk.am diff --git a/ndb/src/mgmsrv/Makefile_old b/ndb/src/mgmsrv/Makefile_old deleted file mode 100644 index c99875ae8b6..00000000000 --- a/ndb/src/mgmsrv/Makefile_old +++ /dev/null @@ -1,41 +0,0 @@ -include .defs.mk - -TYPE := ndbapi mgmapiclient - -BIN_TARGET := mgmtsrvr -BIN_TARGET_LIBS := -BIN_TARGET_ARCHIVES := NDB_API mgmsrvcommon mgmapi general - -ifneq ($(USE_EDITLINE), N) -BIN_TARGET_ARCHIVES += editline -DIRS := mkconfig -endif -BIN_TARGET_ARCHIVES += general - -BIN_FLAGS += $(TERMCAP_LIB) - -# Source files of non-templated classes (.cpp files) -SOURCES = \ - MgmtSrvr.cpp \ - MgmtSrvrGeneralSignalHandling.cpp \ - main.cpp \ - Services.cpp \ - convertStrToInt.cpp \ - NodeLogLevel.cpp \ - NodeLogLevelList.cpp \ - SignalQueue.cpp \ - MgmtSrvrConfig.cpp - -ifeq ($(findstring OSE, $(NDB_OS)),) -SOURCES += CommandInterpreter.cpp -endif - -CCFLAGS_LOC += -I$(call fixpath,$(NDB_TOP)/src/ndbapi) \ - -I$(call fixpath,$(NDB_TOP)/src/mgmapi) \ - -I$(call fixpath,$(NDB_TOP)/include/mgmapi) \ - -I$(call fixpath,$(NDB_TOP)/src/common/mgmcommon) - -include $(NDB_TOP)/Epilogue.mk - -_bins_mkconfig : $(NDB_TOP)/bin/$(BIN_TARGET) - diff --git a/ndb/src/mgmsrv/MgmtSrvr.cpp b/ndb/src/mgmsrv/MgmtSrvr.cpp index 2e30d73290b..a49b29af275 100644 --- a/ndb/src/mgmsrv/MgmtSrvr.cpp +++ b/ndb/src/mgmsrv/MgmtSrvr.cpp @@ -400,11 +400,13 @@ MgmtSrvr::getPort() const { /* Constructor */ MgmtSrvr::MgmtSrvr(NodeId nodeId, + SocketServer *socket_server, const BaseString &configFilename, LocalConfig &local_config, Config * config): _blockNumber(1), // Hard coded block number since it makes it easy to send // signals to other management servers. + m_socket_server(socket_server), _ownReference(0), m_local_config(local_config), theSignalIdleList(NULL), @@ -2094,6 +2096,25 @@ MgmtSrvr::getNodeType(NodeId nodeId) const return nodeTypes[nodeId]; } +void +MgmtSrvr::get_connected_nodes(NodeBitmask &connected_nodes) const +{ + if (theFacade && theFacade->theClusterMgr) + { + for(Uint32 i = 0; i < MAX_NODES; i++) + { + if (getNodeType(i) == NDB_MGM_NODE_TYPE_NDB) + { + const ClusterMgr::Node &node= theFacade->theClusterMgr->getNodeInfo(i); + if (node.connected) + { + connected_nodes.bitOR(node.m_state.m_connected_nodes); + } + } + } + } +} + bool MgmtSrvr::alloc_node_id(NodeId * nodeId, enum ndb_mgm_node_type type, @@ -2106,7 +2127,7 @@ MgmtSrvr::alloc_node_id(NodeId * nodeId, *nodeId, type, client_addr)); if (g_no_nodeid_checks) { if (*nodeId == 0) { - error_string.appfmt("no-nodeid-ckecks set in manegment server.\n" + error_string.appfmt("no-nodeid-checks set in management server.\n" "node id must be set explicitly in connectstring"); DBUG_RETURN(false); } @@ -2115,16 +2136,11 @@ MgmtSrvr::alloc_node_id(NodeId * nodeId, Guard g(m_node_id_mutex); int no_mgm= 0; NodeBitmask connected_nodes(m_reserved_nodes); - for(Uint32 i = 0; i < MAX_NODES; i++) + get_connected_nodes(connected_nodes); { - if (getNodeType(i) == NDB_MGM_NODE_TYPE_NDB && - theFacade && theFacade->theClusterMgr) { - const ClusterMgr::Node &node= theFacade->theClusterMgr->getNodeInfo(i); - if (node.connected) { - connected_nodes.bitOR(node.m_state.m_connected_nodes); - } - } else if (getNodeType(i) == NDB_MGM_NODE_TYPE_MGM) - no_mgm++; + for(Uint32 i = 0; i < MAX_NODES; i++) + if (getNodeType(i) == NDB_MGM_NODE_TYPE_MGM) + no_mgm++; } bool found_matching_id= false; bool found_matching_type= false; @@ -2227,6 +2243,10 @@ MgmtSrvr::alloc_node_id(NodeId * nodeId, m_connect_address[id_found].s_addr= 0; } m_reserved_nodes.set(id_found); + char tmp_str[128]; + m_reserved_nodes.getText(tmp_str); + g_EventLogger.info("Mgmt server state: nodeid %d reserved for ip %s, m_reserved_nodes %s.", + id_found, get_connect_address(id_found), tmp_str); DBUG_RETURN(true); } @@ -2283,6 +2303,36 @@ MgmtSrvr::alloc_node_id(NodeId * nodeId, error_string.appfmt("No node defined with id=%d in config file.", *nodeId); } + + g_EventLogger.warning("Allocate nodeid (%d) failed. Connection from ip %s. " + "Returned error string \"%s\"", + *nodeId, + client_addr != 0 ? inet_ntoa(((struct sockaddr_in *)(client_addr))->sin_addr) : "<none>", + error_string.c_str()); + + NodeBitmask connected_nodes2; + get_connected_nodes(connected_nodes2); + { + BaseString tmp_connected, tmp_not_connected; + for(Uint32 i = 0; i < MAX_NODES; i++) + { + if (connected_nodes2.get(i)) + { + if (!m_reserved_nodes.get(i)) + tmp_connected.appfmt(" %d", i); + } + else if (m_reserved_nodes.get(i)) + { + tmp_not_connected.appfmt(" %d", i); + } + } + if (tmp_connected.length() > 0) + g_EventLogger.info("Mgmt server state: node id's %s connected but not reserved", + tmp_connected.c_str()); + if (tmp_not_connected.length() > 0) + g_EventLogger.info("Mgmt server state: node id's %s not connected but reserved", + tmp_not_connected.c_str()); + } DBUG_RETURN(false); } @@ -2531,10 +2581,15 @@ MgmtSrvr::Allocated_resources::~Allocated_resources() { Guard g(m_mgmsrv.m_node_id_mutex); if (!m_reserved_nodes.isclear()) { + m_mgmsrv.m_reserved_nodes.bitANDC(m_reserved_nodes); // node has been reserved, force update signal to ndb nodes global_flag_send_heartbeat_now= 1; + + char tmp_str[128]; + m_mgmsrv.m_reserved_nodes.getText(tmp_str); + g_EventLogger.info("Mgmt server state: nodeid %d freed, m_reserved_nodes %s.", + get_nodeid(), tmp_str); } - m_mgmsrv.m_reserved_nodes.bitANDC(m_reserved_nodes); } void @@ -2543,6 +2598,17 @@ MgmtSrvr::Allocated_resources::reserve_node(NodeId id) m_reserved_nodes.set(id); } +NodeId +MgmtSrvr::Allocated_resources::get_nodeid() const +{ + for(Uint32 i = 0; i < MAX_NODES; i++) + { + if (m_reserved_nodes.get(i)) + return i; + } + return 0; +} + int MgmtSrvr::setDbParameter(int node, int param, const char * value, BaseString& msg){ diff --git a/ndb/src/mgmsrv/MgmtSrvr.hpp b/ndb/src/mgmsrv/MgmtSrvr.hpp index c796e1e9219..b3257491123 100644 --- a/ndb/src/mgmsrv/MgmtSrvr.hpp +++ b/ndb/src/mgmsrv/MgmtSrvr.hpp @@ -96,7 +96,10 @@ public: // methods to reserve/allocate resources which // will be freed when running destructor void reserve_node(NodeId id); - bool is_reserved(NodeId nodeId) { return m_reserved_nodes.get(nodeId);} + bool is_reserved(NodeId nodeId) { return m_reserved_nodes.get(nodeId); } + bool is_reserved(NodeBitmask mask) { return !mask.bitAND(m_reserved_nodes).isclear(); } + bool isclear() { return m_reserved_nodes.isclear(); } + NodeId get_nodeid() const; private: MgmtSrvr &m_mgmsrv; NodeBitmask m_reserved_nodes; @@ -173,6 +176,7 @@ public: /* Constructor */ MgmtSrvr(NodeId nodeId, /* Local nodeid */ + SocketServer *socket_server, const BaseString &config_filename, /* Where to save config */ LocalConfig &local_config, /* Ndb.cfg filename */ Config * config); @@ -499,6 +503,9 @@ public: int setDbParameter(int node, int parameter, const char * value, BaseString&); const char *get_connect_address(Uint32 node_id) { return inet_ntoa(m_connect_address[node_id]); } + void get_connected_nodes(NodeBitmask &connected_nodes) const; + SocketServer *get_socket_server() { return m_socket_server; } + //************************************************************************** private: //************************************************************************** @@ -525,6 +532,8 @@ private: int _blockNumber; NodeId _ownNodeId; + SocketServer *m_socket_server; + BlockReference _ownReference; NdbMutex *m_configMutex; const Config * _config; diff --git a/ndb/src/mgmsrv/Services.cpp b/ndb/src/mgmsrv/Services.cpp index 2672d8c9d4b..0394c4e80bb 100644 --- a/ndb/src/mgmsrv/Services.cpp +++ b/ndb/src/mgmsrv/Services.cpp @@ -242,6 +242,8 @@ ParserRow<MgmApiSession> commands[] = { MGM_ARG("node", Int, Optional, "Node"), MGM_ARG("filter", String, Mandatory, "Event category"), + MGM_CMD("purge stale sessions", &MgmApiSession::purge_stale_sessions, ""), + MGM_END() }; @@ -1412,6 +1414,46 @@ done: m_output->println(""); } +struct PurgeStruct +{ + NodeBitmask free_nodes;/* free nodes as reported + * by ndbd in apiRegReqConf + */ + BaseString *str; +}; + +void +MgmApiSession::stop_session_if_not_connected(SocketServer::Session *_s, void *data) +{ + MgmApiSession *s= (MgmApiSession *)_s; + struct PurgeStruct &ps= *(struct PurgeStruct *)data; + if (s->m_allocated_resources->is_reserved(ps.free_nodes)) + { + ps.str->appfmt(" %d", s->m_allocated_resources->get_nodeid()); + s->stopSession(); + } +} + +void +MgmApiSession::purge_stale_sessions(Parser_t::Context &ctx, + const class Properties &args) +{ + struct PurgeStruct ps; + BaseString str; + ps.str = &str; + + m_mgmsrv.get_connected_nodes(ps.free_nodes); + ps.free_nodes.bitXORC(NodeBitmask()); // invert connected_nodes to get free nodes + + m_mgmsrv.get_socket_server()->foreachSession(stop_session_if_not_connected,&ps); + + m_output->println("purge stale sessions reply"); + if (str.length() > 0) + m_output->println("purged:%s",str.c_str()); + m_output->println("result: Ok"); + m_output->println(""); +} + template class MutexVector<int>; template class Vector<ParserRow<MgmApiSession> const*>; template class Vector<unsigned short>; diff --git a/ndb/src/mgmsrv/Services.hpp b/ndb/src/mgmsrv/Services.hpp index e47820826b6..bfc915f18f1 100644 --- a/ndb/src/mgmsrv/Services.hpp +++ b/ndb/src/mgmsrv/Services.hpp @@ -28,7 +28,9 @@ /** Undefine this to remove backwards compatibility for "GET CONFIG". */ #define MGM_GET_CONFIG_BACKWARDS_COMPAT -class MgmApiSession : public SocketServer::Session { +class MgmApiSession : public SocketServer::Session +{ + static void stop_session_if_not_connected(SocketServer::Session *_s, void *data); private: typedef Parser<MgmApiSession> Parser_t; @@ -84,6 +86,8 @@ public: void setParameter(Parser_t::Context &ctx, const class Properties &args); void listen_event(Parser_t::Context &ctx, const class Properties &args); + + void purge_stale_sessions(Parser_t::Context &ctx, const class Properties &args); void repCommand(Parser_t::Context &ctx, const class Properties &args); }; diff --git a/ndb/src/mgmsrv/main.cpp b/ndb/src/mgmsrv/main.cpp index 6e3a0b280d1..f85456c8ea6 100644 --- a/ndb/src/mgmsrv/main.cpp +++ b/ndb/src/mgmsrv/main.cpp @@ -83,7 +83,6 @@ struct MgmGlobals { int g_no_nodeid_checks= 0; static MgmGlobals glob; - /****************************************************************************** * Function prototypes ******************************************************************************/ @@ -203,7 +202,7 @@ int main(int argc, char** argv) if (!readGlobalConfig()) goto error_end; - glob.mgmObject = new MgmtSrvr(glob.localNodeId, + glob.mgmObject = new MgmtSrvr(glob.localNodeId, glob.socketServer, BaseString(glob.config_filename), local_config, glob.cluster_config); diff --git a/ndb/src/ndbapi/Makefile_old b/ndb/src/ndbapi/Makefile_old deleted file mode 100644 index 54de9ba96f4..00000000000 --- a/ndb/src/ndbapi/Makefile_old +++ /dev/null @@ -1,60 +0,0 @@ -include .defs.mk - -TYPE := ndbapi - -PIC_ARCHIVE := Y -NONPIC_ARCHIVE := Y -ARCHIVE_TARGET := ndbapi - -A_LIB := Y -SO_LIB := Y -PIC_LIB := Y -LIB_TARGET := NDB_API - -LIB_TARGET_ARCHIVES := $(ARCHIVE_TARGET) \ - transporter \ - general \ - signaldataprint \ - mgmapi mgmsrvcommon \ - portlib \ - logger \ - trace - -DIRS := signal-sender - -CFLAGS_TransporterFacade.cpp := -I$(call fixpath,$(NDB_TOP)/src/mgmapi) -CFLAGS_ClusterMgr.cpp := -I$(call fixpath,$(NDB_TOP)/src/mgmapi) - -# Source files of non-templated classes (.cpp files) -SOURCES = \ - TransporterFacade.cpp \ - ClusterMgr.cpp \ - Ndb.cpp \ - NdbPoolImpl.cpp NdbPool.cpp \ - Ndblist.cpp \ - Ndbif.cpp \ - Ndbinit.cpp \ - ndberror.c Ndberr.cpp NdbErrorOut.cpp \ - NdbConnection.cpp \ - NdbConnectionScan.cpp \ - NdbOperation.cpp \ - NdbOperationSearch.cpp \ - NdbOperationInt.cpp \ - NdbOperationDefine.cpp \ - NdbOperationExec.cpp \ - NdbResultSet.cpp \ - NdbScanOperation.cpp NdbScanFilter.cpp \ - NdbIndexOperation.cpp \ - NdbEventOperation.cpp \ - NdbEventOperationImpl.cpp \ - NdbApiSignal.cpp \ - NdbRecAttr.cpp \ - NdbUtil.cpp \ - NdbReceiver.cpp \ - NdbDictionary.cpp NdbDictionaryImpl.cpp DictCache.cpp - NdbBlob.cpp - -include $(NDB_TOP)/Epilogue.mk - -### -# Backward compatible diff --git a/ndb/src/ndbapi/NdbDictionary.cpp b/ndb/src/ndbapi/NdbDictionary.cpp index c8414ec16a3..09d15c7f962 100644 --- a/ndb/src/ndbapi/NdbDictionary.cpp +++ b/ndb/src/ndbapi/NdbDictionary.cpp @@ -343,6 +343,18 @@ NdbDictionary::Table::getColumn(const int attrId) const { return m_impl.getColumn(attrId); } +NdbDictionary::Column* +NdbDictionary::Table::getColumn(const char * name) +{ + return m_impl.getColumn(name); +} + +NdbDictionary::Column* +NdbDictionary::Table::getColumn(const int attrId) +{ + return m_impl.getColumn(attrId); +} + void NdbDictionary::Table::setLogging(bool val){ m_impl.m_logging = val; @@ -956,6 +968,10 @@ operator<<(NdbOut& out, const NdbDictionary::Column& col) out << " NOT NULL"; else out << " NULL"; + + if (col.getDistributionKey()) + out << " DISTRIBUTION KEY"; + return out; } diff --git a/ndb/src/ndbapi/NdbDictionaryImpl.hpp b/ndb/src/ndbapi/NdbDictionaryImpl.hpp index 12f0946ab67..62d2a951f28 100644 --- a/ndb/src/ndbapi/NdbDictionaryImpl.hpp +++ b/ndb/src/ndbapi/NdbDictionaryImpl.hpp @@ -637,11 +637,9 @@ NdbDictionaryImpl::get_local_table_info(const char * internalTableName, return 0; } } - if (do_add_blob_tables && - info->m_table_impl->m_noOfBlobs && - addBlobTables(*(info->m_table_impl))) { - return 0; - } + if (do_add_blob_tables && info->m_table_impl->m_noOfBlobs) + addBlobTables(*(info->m_table_impl)); + return info; // autoincrement already initialized } diff --git a/ndb/src/ndbapi/NdbOperationExec.cpp b/ndb/src/ndbapi/NdbOperationExec.cpp index 13664794dcd..cccc3b6409f 100644 --- a/ndb/src/ndbapi/NdbOperationExec.cpp +++ b/ndb/src/ndbapi/NdbOperationExec.cpp @@ -192,7 +192,7 @@ NdbOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransId) OperationType tOperationType = theOperationType; Uint32 tTupKeyLen = theTupKeyLen; Uint8 abortOption = - m_abortOption != (Int8)-1 ? m_abortOption : theNdbCon->m_abortOption; + m_abortOption != -1 ? m_abortOption : theNdbCon->m_abortOption; tcKeyReq->setDirtyFlag(tReqInfo, tDirtyIndicator); tcKeyReq->setOperationType(tReqInfo, tOperationType); @@ -543,7 +543,7 @@ NdbOperation::receiveTCKEYREF( NdbApiSignal* aSignal) }//if AbortOption ao = (AbortOption) - (m_abortOption != (Int8)-1 ? m_abortOption : theNdbCon->m_abortOption); + (m_abortOption != -1 ? m_abortOption : theNdbCon->m_abortOption); theReceiver.m_received_result_length = ~0; theStatus = Finished; diff --git a/ndb/src/ndbapi/NdbScanOperation.cpp b/ndb/src/ndbapi/NdbScanOperation.cpp index 86bac7deb16..373fec1a2b0 100644 --- a/ndb/src/ndbapi/NdbScanOperation.cpp +++ b/ndb/src/ndbapi/NdbScanOperation.cpp @@ -850,6 +850,14 @@ NdbScanOperation::doSendScan(int aProcessorId) tSignal = tSignal->next(); } theStatus = WaitResponse; + + m_sent_receivers_count = theParallelism; + if(m_ordered) + { + m_current_api_receiver = theParallelism; + m_api_receivers_count = theParallelism; + } + return tSignalCount; }//NdbOperation::doSendScan() @@ -1507,13 +1515,8 @@ NdbScanOperation::reset_receivers(Uint32 parallell, Uint32 ordered){ m_api_receivers_count = 0; m_current_api_receiver = 0; - m_sent_receivers_count = parallell; + m_sent_receivers_count = 0; m_conf_receivers_count = 0; - - if(ordered){ - m_current_api_receiver = parallell; - m_api_receivers_count = parallell; - } } int diff --git a/ndb/src/ndbapi/ndberror.c b/ndb/src/ndbapi/ndberror.c index 17a80082023..1a0d8132d71 100644 --- a/ndb/src/ndbapi/ndberror.c +++ b/ndb/src/ndbapi/ndberror.c @@ -124,7 +124,8 @@ ErrorBundle ErrorCodes[] = { { 217, TR, "217" }, { 218, TR, "218" }, { 219, TR, "219" }, - { 233, TR, "Out of operation records in transaction coordinator" }, + { 233, TR, + "Out of operation records in transaction coordinator (increase MaxNoOfConcurrentOperations)" }, { 275, TR, "275" }, { 279, TR, "Out of transaction markers in transaction coordinator" }, { 414, TR, "414" }, @@ -137,7 +138,7 @@ ErrorBundle ErrorCodes[] = { { 830, TR, "Out of add fragment operation records" }, { 873, TR, "Out of attrinfo records for scan in tuple manager" }, { 1217, TR, "1217" }, - { 1219, TR, "Out of operation records in local data manager" }, + { 1219, TR, "Out of operation records in local data manager (increase MaxNoOfLocalOperations)" }, { 1220, TR, "1220" }, { 1222, TR, "Out of transaction markers in LQH" }, { 4021, TR, "Out of Send Buffer space in NDB API" }, @@ -149,9 +150,10 @@ ErrorBundle ErrorCodes[] = { */ { 623, IS, "623" }, { 624, IS, "624" }, - { 625, IS, "Out of memory in Ndb Kernel, index part" }, - { 826, IS, "Too many tables and attributes (increase MaxNoOfAttributes)" }, - { 827, IS, "Out of memory in Ndb Kernel, data part" }, + { 625, IS, "Out of memory in Ndb Kernel, index part (increase IndexMemory)" }, + { 800, IS, "Too many ordered indexes (increase MaxNoOfOrderedIndexes)" }, + { 826, IS, "Too many tables and attributes (increase MaxNoOfAttributes or MaxNoOfTables)" }, + { 827, IS, "Out of memory in Ndb Kernel, data part (increase DataMemory)" }, { 832, IS, "832" }, /** @@ -168,10 +170,10 @@ ErrorBundle ErrorCodes[] = { * OverloadError */ { 410, OL, "Out of log file space temporarily" }, - { 677, OL, "Index UNDO buffers overloaded" }, - { 891, OL, "Data UNDO buffers overloaded" }, - { 1221, OL, "REDO log buffers overloaded" }, - { 4006, OL, "Connect failure - out of connection objects" }, + { 677, OL, "Index UNDO buffers overloaded (increase UndoIndexBuffer)" }, + { 891, OL, "Data UNDO buffers overloaded (increase UndoDataBuffer)" }, + { 1221, OL, "REDO log buffers overloaded (increase RedoBuffer)" }, + { 4006, OL, "Connect failure - out of connection objects (increase MaxNoOfConcurrentTransactions)" }, @@ -241,9 +243,9 @@ ErrorBundle ErrorCodes[] = { { 884, AE, "Stack overflow in interpreter" }, { 885, AE, "Stack underflow in interpreter" }, { 886, AE, "More than 65535 instructions executed in interpreter" }, - { 4256, AE, "Must call Ndb::init() before this function" }, + { 4256, AE, "Must call Ndb::init() before this function" }, { 880, AE, "Tried to read too much - too many getValue calls" }, - { 4257, AE, "Tried to read too much - too many getValue calls" }, + { 4257, AE, "Tried to read too much - too many getValue calls" }, /** * Scan application errors @@ -288,7 +290,7 @@ ErrorBundle ErrorCodes[] = { { 283, SE, "Table is being dropped" }, { 284, SE, "Table not defined in transaction coordinator" }, { 285, SE, "Unknown table error in transaction coordinator" }, - { 881, SE, "Unable to create table, out of data pages" }, + { 881, SE, "Unable to create table, out of data pages (increase DataMemory) " }, { 1225, SE, "Table not defined in local query handler" }, { 1226, SE, "Table is being dropped" }, { 1228, SE, "Cannot use drop table for drop index" }, @@ -344,17 +346,11 @@ ErrorBundle ErrorCodes[] = { { 4327, AE, "Distribution Group with 1 byte attribute is not allowed" }, { 4328, AE, "Disk memory attributes not yet supported" }, { 4329, AE, "Variable stored attributes not yet supported" }, - { 4330, AE, "Table names limited to 127 bytes" }, - { 4331, AE, "Attribute names limited to 31 bytes" }, - { 4332, AE, "Maximum 2000 attributes in a table" }, - { 4333, AE, "Maximum 4092 bytes long keys allowed" }, - { 4334, AE, "Attribute properties length limited to 127 bytes" }, { 4400, AE, "Status Error in NdbSchemaCon" }, { 4401, AE, "Only one schema operation per schema transaction" }, { 4402, AE, "No schema operation defined before calling execute" }, - { 4500, AE, "Cannot handle more than 2048 tables in NdbApi" }, { 4501, AE, "Insert in hash table failed when getting table information from Ndb" }, { 4502, AE, "GetValue not allowed in Update operation" }, { 4503, AE, "GetValue not allowed in Insert operation" }, diff --git a/ndb/src/mgmclient/CpcClient.hpp b/ndb/test/include/CpcClient.hpp index 1655bc57b56..1655bc57b56 100644 --- a/ndb/src/mgmclient/CpcClient.hpp +++ b/ndb/test/include/CpcClient.hpp diff --git a/ndb/test/include/NDBT_Test.hpp b/ndb/test/include/NDBT_Test.hpp index b0b5fe15960..8b69faebde8 100644 --- a/ndb/test/include/NDBT_Test.hpp +++ b/ndb/test/include/NDBT_Test.hpp @@ -392,10 +392,10 @@ C##suitname():NDBT_TestSuite(#suitname){ \ // Add a number of equal steps to the testcase #define STEPS(stepfunc, num) \ - for (int i = 0; i < num; i++){ \ + { int i; for (i = 0; i < num; i++){ \ pts = new NDBT_ParallelStep(pt, #stepfunc, stepfunc); \ pt->addStep(pts);\ - } + } } #define VERIFIER(stepfunc) \ ptv = new NDBT_Verifier(pt, #stepfunc, stepfunc); \ diff --git a/ndb/test/ndbapi/Makefile_old b/ndb/test/ndbapi/Makefile_old deleted file mode 100644 index c3198096ec0..00000000000 --- a/ndb/test/ndbapi/Makefile_old +++ /dev/null @@ -1,49 +0,0 @@ -include .defs.mk - - -ifeq ($(NDB_OS), OSE) -DIRS = basic flexBench flexAsynch -else -DIRS = lmc-bench ronja -BIN_DIRS = \ - flexAsynch \ - flexBench \ - flexHammer \ - flexTT \ - create_tab \ - create_all_tabs \ - drop_all_tabs \ - bulk_copy \ - restarter2 restarter \ - restarts testScan testNdbApi \ - testScanInterpreter testIndex \ - testInterpreter \ - testOIBasic \ - testBackup \ - testBasic \ - basicAsynch \ - testNodeRestart \ - testOperations testTransactions \ - testSystemRestart \ - testTimeout \ - testMgm \ - testRestartGci \ - testDataBuffers \ - testDict \ - acid \ - telco \ - indexTest \ - test_event \ - indexTest2 \ - testGrep \ - testBlobs - -ifeq ($(NDB_OS), SOLARIS) -ifeq ($(NDB_COMPILER), FORTE6) - DIRS += flexTimedAsynch -endif -endif -endif - -include ${NDB_TOP}/Epilogue.mk - diff --git a/ndb/test/ndbapi/ScanFunctions.hpp b/ndb/test/ndbapi/ScanFunctions.hpp index 2ff4b751c33..6964f8c73a8 100644 --- a/ndb/test/ndbapi/ScanFunctions.hpp +++ b/ndb/test/ndbapi/ScanFunctions.hpp @@ -286,36 +286,36 @@ void AttribList::buildAttribList(const NdbDictionary::Table* pTab){ attr = new Attrib; attr->numAttribs = 0; attriblist.push_back(attr); - - for(int i = 1; i < pTab->getNoOfColumns(); i++){ + int i; + for(i = 1; i < pTab->getNoOfColumns(); i++){ attr = new Attrib; attr->numAttribs = i; for(int a = 0; a<i; a++) attr->attribs[a] = a; attriblist.push_back(attr); } - for(int i = pTab->getNoOfColumns()-1; i > 0; i--){ + for(i = pTab->getNoOfColumns()-1; i > 0; i--){ attr = new Attrib; attr->numAttribs = i; for(int a = 0; a<i; a++) attr->attribs[a] = a; attriblist.push_back(attr); } - for(int i = pTab->getNoOfColumns(); i > 0; i--){ + for(i = pTab->getNoOfColumns(); i > 0; i--){ attr = new Attrib; attr->numAttribs = pTab->getNoOfColumns() - i; for(int a = 0; a<pTab->getNoOfColumns() - i; a++) attr->attribs[a] = pTab->getNoOfColumns()-a-1; attriblist.push_back(attr); } - for(int i = 1; i < pTab->getNoOfColumns(); i++){ + for(i = 1; i < pTab->getNoOfColumns(); i++){ attr = new Attrib; attr->numAttribs = pTab->getNoOfColumns() - i; for(int a = 0; a<pTab->getNoOfColumns() - i; a++) attr->attribs[a] = pTab->getNoOfColumns()-a-1; attriblist.push_back(attr); } - for(int i = 1; i < pTab->getNoOfColumns(); i++){ + for(i = 1; i < pTab->getNoOfColumns(); i++){ attr = new Attrib; attr->numAttribs = 2; for(int a = 0; a<2; a++){ @@ -345,11 +345,11 @@ void AttribList::buildAttribList(const NdbDictionary::Table* pTab){ attriblist.push_back(attr); #if 1 - for(size_t i = 0; i < attriblist.size(); i++){ + for(size_t j = 0; j < attriblist.size(); j++){ - g_info << attriblist[i]->numAttribs << ": " ; - for(int a = 0; a < attriblist[i]->numAttribs; a++) - g_info << attriblist[i]->attribs[a] << ", "; + g_info << attriblist[j]->numAttribs << ": " ; + for(int a = 0; a < attriblist[j]->numAttribs; a++) + g_info << attriblist[j]->attribs[a] << ", "; g_info << endl; } #endif diff --git a/ndb/test/ndbapi/bank/Makefile_old b/ndb/test/ndbapi/bank/Makefile_old deleted file mode 100644 index f710f9e6612..00000000000 --- a/ndb/test/ndbapi/bank/Makefile_old +++ /dev/null @@ -1,12 +0,0 @@ -include .defs.mk - -DIRS = src bankCreator \ - bankSumAccounts \ - bankTransactionMaker \ - bankValidateAllGLs \ - bankMakeGL \ - bankTimer \ - testBank - - -include $(NDB_TOP)/Epilogue.mk diff --git a/ndb/test/ndbapi/old_dirs/flexBench/Makefile_old b/ndb/test/ndbapi/old_dirs/flexBench/Makefile_old deleted file mode 100644 index bfff5cd161a..00000000000 --- a/ndb/test/ndbapi/old_dirs/flexBench/Makefile_old +++ /dev/null @@ -1,11 +0,0 @@ -include .defs.mk - -TYPE := ndbapitest - -BIN_TARGET := flexBench - -# Source files of non-templated classes (.C files) -SOURCES = flexBench.cpp - -include $(NDB_TOP)/Epilogue.mk - diff --git a/ndb/test/ndbapi/testDataBuffers.cpp b/ndb/test/ndbapi/testDataBuffers.cpp index 04602f51d5f..03d52252334 100644 --- a/ndb/test/ndbapi/testDataBuffers.cpp +++ b/ndb/test/ndbapi/testDataBuffers.cpp @@ -123,15 +123,15 @@ chkerror(char const* fmt, ...) // alignment of addresses and data sizes -static bool isAligned(unsigned x) +static bool isAligned(UintPtr x) { return ((x & 3) == 0); } static bool isAligned(char* p) { - return isAligned(unsigned(p)); + return isAligned(UintPtr(p)); } -static unsigned toAligned(unsigned x) +static unsigned toAligned(UintPtr x) { while (! isAligned(x)) x++; @@ -223,10 +223,10 @@ testcase(int flag) noRandom = ! (flag & 8); ndbout << (noRandom ? "simple sizes" : "randomize sizes") << endl; - int smax = 0, stot = 0; + int smax = 0, stot = 0, i; if (xverbose) ndbout << "- define table " << tab << endl; - for (int i = 0; i < attrcnt; i++) { + for (i = 0; i < attrcnt; i++) { col& c = ccol[i]; memset(&c, 0, sizeof(c)); sprintf(c.aAttrName, "C%d", i); @@ -266,7 +266,7 @@ testcase(int flag) return ndberror("getNdbSchemaOp"); if (top->createTable(tab) < 0) return ndberror("createTable"); - for (int i = 0; i < attrcnt; i++) { + for (i = 0; i < attrcnt; i++) { col& c = ccol[i]; if (top->createAttribute( c.aAttrName, @@ -299,7 +299,7 @@ testcase(int flag) return ndberror("getNdbOperation key=%d", key); if (op->deleteTuple() < 0) return ndberror("deleteTuple key=%d", key); - for (int i = 0; i < attrcnt; i++) { + for (i = 0; i < attrcnt; i++) { col& c = ccol[i]; if (i == 0) { if (op->equal(c.aAttrName, (char*)&key, sizeof(key)) < 0) @@ -329,7 +329,7 @@ testcase(int flag) return ndberror("getNdbOperation key=%d", key); if (op->insertTuple() < 0) return ndberror("insertTuple key=%d", key); - for (int i = 0; i < attrcnt; i++) { + for (i = 0; i < attrcnt; i++) { col& c = ccol[i]; if (i == 0) { if (op->equal(c.aAttrName, (char*)&key, sizeof(key)) < 0) @@ -362,7 +362,7 @@ testcase(int flag) return ndberror("getNdbOperation key=%d", key); if (op->readTuple() < 0) return ndberror("readTuple key=%d", key); - for (int i = 0; i < attrcnt; i++) { + for (i = 0; i < attrcnt; i++) { col& c = ccol[i]; if (i == 0) { if (op->equal(c.aAttrName, (char*)&key, sizeof(key)) < 0) @@ -371,7 +371,7 @@ testcase(int flag) if (xverbose) { char tmp[20]; if (useBuf) - sprintf(tmp, "0x%x", int(c.buf + off)); + sprintf(tmp, "0x%p", c.buf + off); else strcpy(tmp, "ndbapi"); ndbout << "--- column " << i << " addr=" << tmp << endl; @@ -388,23 +388,24 @@ testcase(int flag) } if (con->execute(Commit) != 0) return ndberror("execute key=%d", key); - for (int i = 0; i < attrcnt; i++) { + for (i = 0; i < attrcnt; i++) { col& c = ccol[i]; if (i == 0) { } else if (useBuf) { - for (int j = 0; j < off; j++) { + int j; + for (j = 0; j < off; j++) { if (c.buf[j] != 'B') { return chkerror("mismatch before key=%d col=%d pos=%d ok=%02x bad=%02x", key, i, j, 'B', c.buf[j]); } } - for (int j = 0; j < c.aArraySize; j++) { + for (j = 0; j < c.aArraySize; j++) { if (c.buf[j + off] != byteVal(key, i, j)) { return chkerror("mismatch key=%d col=%d pos=%d ok=%02x bad=%02x", key, i, j, byteVal(key, i, j), c.buf[j]); } } - for (int j = c.aArraySize + off; j < c.bufsiz; j++) { + for (j = c.aArraySize + off; j < c.bufsiz; j++) { if (c.buf[j] != 'B') { return chkerror("mismatch after key=%d col=%d pos=%d ok=%02x bad=%02x", key, i, j, 'B', c.buf[j]); @@ -431,7 +432,8 @@ testcase(int flag) if (xverbose) ndbout << "- scan" << endl; char found[MaxOper]; - for (int k = 0; k < opercnt; k++) + int k; + for (k = 0; k < opercnt; k++) found[k] = 0; for (key = 0; key < opercnt; key++) { int off = makeOff(key); @@ -459,7 +461,7 @@ testcase(int flag) if (op->interpret_exit_ok() < 0) return ndberror("interpret_exit_ok"); } - for (int i = 0; i < attrcnt; i++) { + for (i = 0; i < attrcnt; i++) { col& c = ccol[i]; if (i == 0) { if (op->getValue(c.aAttrName, (char*)&newkey) < 0) @@ -468,7 +470,7 @@ testcase(int flag) if (xverbose) { char tmp[20]; if (useBuf) - sprintf(tmp, "0x%x", int(c.buf + off)); + sprintf(tmp, "0x%p", c.buf + off); else strcpy(tmp, "ndbapi"); ndbout << "--- column " << i << " addr=" << tmp << endl; @@ -489,22 +491,23 @@ testcase(int flag) while ((ret = rs->nextResult()) == 0) { if (key != newkey) return ndberror("unexpected key=%d newkey=%d", key, newkey); - for (int i = 1; i < attrcnt; i++) { + for (i = 1; i < attrcnt; i++) { col& c = ccol[i]; if (useBuf) { - for (int j = 0; j < off; j++) { + int j; + for (j = 0; j < off; j++) { if (c.buf[j] != 'C') { return chkerror("mismatch before key=%d col=%d pos=%d ok=%02x bad=%02x", key, i, j, 'C', c.buf[j]); } } - for (int j = 0; j < c.aArraySize; j++) { + for (j = 0; j < c.aArraySize; j++) { if (c.buf[j + off] != byteVal(key, i, j)) { return chkerror("mismatch key=%d col=%d pos=%d ok=%02x bad=%02x", key, i, j, byteVal(key, i, j), c.buf[j]); } } - for (int j = c.aArraySize + off; j < c.bufsiz; j++) { + for (j = c.aArraySize + off; j < c.bufsiz; j++) { if (c.buf[j] != 'C') { return chkerror("mismatch after key=%d col=%d pos=%d ok=%02x bad=%02x", key, i, j, 'C', c.buf[j]); @@ -533,7 +536,7 @@ testcase(int flag) } con = 0; op = 0; - for (int k = 0; k < opercnt; k++) + for (k = 0; k < opercnt; k++) if (! found[k]) return ndberror("key %d not found", k); ndbout << "scanned " << key << endl; @@ -545,6 +548,7 @@ testcase(int flag) NDB_COMMAND(testDataBuffers, "testDataBuffers", "testDataBuffers", "testDataBuffers", 65535) { + int i; ndb_init(); while (++argv, --argc > 0) { char const* p = argv[0]; @@ -602,7 +606,7 @@ NDB_COMMAND(testDataBuffers, "testDataBuffers", "testDataBuffers", "testDataBuff } } unsigned ok = true; - for (int i = 1; 0 == loopcnt || i <= loopcnt; i++) { + for (i = 1; 0 == loopcnt || i <= loopcnt; i++) { ndbout << "=== loop " << i << " ===" << endl; for (int flag = 0; flag < (1<<testbits); flag++) { if (testcase(flag) < 0) { diff --git a/ndb/test/ndbapi/testDeadlock.cpp b/ndb/test/ndbapi/testDeadlock.cpp index 66fa48173cc..eb985e815ac 100644 --- a/ndb/test/ndbapi/testDeadlock.cpp +++ b/ndb/test/ndbapi/testDeadlock.cpp @@ -459,7 +459,8 @@ wl1822_main(char scantx) static const unsigned thrcount = 2; // create threads for tx1 and tx2 Thr* thrlist[2]; - for (int n = 0; n < thrcount; n++) { + int n; + for (n = 0; n < thrcount; n++) { Thr& thr = *(thrlist[n] = new Thr(1 + n)); CHK(thr.m_ret == 0); } @@ -472,7 +473,7 @@ wl1822_main(char scantx) if (runstep != 0) thr.start(runstep); } - for (int n = 0; n < thrcount; n++) { + for (n = 0; n < thrcount; n++) { Thr& thr = *thrlist[n]; Runstep runstep = wl1822_step[i][n]; if (runstep != 0) @@ -480,7 +481,7 @@ wl1822_main(char scantx) } } // delete threads - for (int n = 0; n < thrcount; n++) { + for (n = 0; n < thrcount; n++) { Thr& thr = *thrlist[n]; thr.exit(); thr.join(); diff --git a/ndb/test/ndbapi/testDict.cpp b/ndb/test/ndbapi/testDict.cpp index 89232de2535..9552e321f00 100644 --- a/ndb/test/ndbapi/testDict.cpp +++ b/ndb/test/ndbapi/testDict.cpp @@ -1431,11 +1431,12 @@ int runTestDictionaryPerf(NDBT_Context* ctx, NDBT_Step* step){ Vector<char*> cols; Vector<const NdbDictionary::Table*> tabs; + int i; Ndb* pNdb = GETNDB(step); const Uint32 count = NDBT_Tables::getNumTables(); - for (int i=0; i < count; i++){ + for (i=0; i < count; i++){ const NdbDictionary::Table * tab = NDBT_Tables::getTable(i); pNdb->getDictionary()->createTable(* tab); @@ -1458,7 +1459,7 @@ runTestDictionaryPerf(NDBT_Context* ctx, NDBT_Step* step){ Uint32 size = cols.size() / 2; char ** columns = &cols[0]; Uint64 start = NdbTick_CurrentMillisecond(); - for(int i = 0; i<times; i++){ + for(i = 0; i<times; i++){ int j = 2 * (rand() % size); const NdbDictionary::Table* tab = (const NdbDictionary::Table*)tcols[j]; const char * col = tcols[j+1]; diff --git a/ndb/test/ndbapi/testIndex.cpp b/ndb/test/ndbapi/testIndex.cpp index ed9e114fd92..6623ad35a7f 100644 --- a/ndb/test/ndbapi/testIndex.cpp +++ b/ndb/test/ndbapi/testIndex.cpp @@ -58,7 +58,9 @@ void AttribList::buildAttribList(const NdbDictionary::Table* pTab){ // Build attrib definitions that describes which attributes to build index // Try to build strange combinations, not just "all" or all PK's - for(int i = 1; i <= pTab->getNoOfColumns(); i++){ + int i; + + for(i = 1; i <= pTab->getNoOfColumns(); i++){ attr = new Attrib; attr->numAttribs = i; for(int a = 0; a<i; a++) @@ -66,7 +68,7 @@ void AttribList::buildAttribList(const NdbDictionary::Table* pTab){ attriblist.push_back(attr); } int b = 0; - for(int i = pTab->getNoOfColumns()-1; i > 0; i--){ + for(i = pTab->getNoOfColumns()-1; i > 0; i--){ attr = new Attrib; attr->numAttribs = i; b++; @@ -74,21 +76,21 @@ void AttribList::buildAttribList(const NdbDictionary::Table* pTab){ attr->attribs[a] = a+b; attriblist.push_back(attr); } - for(int i = pTab->getNoOfColumns(); i > 0; i--){ + for(i = pTab->getNoOfColumns(); i > 0; i--){ attr = new Attrib; attr->numAttribs = pTab->getNoOfColumns() - i; for(int a = 0; a<pTab->getNoOfColumns() - i; a++) attr->attribs[a] = pTab->getNoOfColumns()-a-1; attriblist.push_back(attr); } - for(int i = 1; i < pTab->getNoOfColumns(); i++){ + for(i = 1; i < pTab->getNoOfColumns(); i++){ attr = new Attrib; attr->numAttribs = pTab->getNoOfColumns() - i; for(int a = 0; a<pTab->getNoOfColumns() - i; a++) attr->attribs[a] = pTab->getNoOfColumns()-a-1; attriblist.push_back(attr); } - for(int i = 1; i < pTab->getNoOfColumns(); i++){ + for(i = 1; i < pTab->getNoOfColumns(); i++){ attr = new Attrib; attr->numAttribs = 2; for(int a = 0; a<2; a++){ @@ -226,8 +228,8 @@ int runCreateIndexes(NDBT_Context* ctx, NDBT_Step* step){ while (l < loops && result == NDBT_OK){ - - for (unsigned int i = 0; i < attrList.attriblist.size(); i++){ + unsigned int i; + for (i = 0; i < attrList.attriblist.size(); i++){ // Try to create index if (create_index(ctx, i, pTab, pNdb, attrList.attriblist[i], logged) == NDBT_FAILED) @@ -235,7 +237,7 @@ int runCreateIndexes(NDBT_Context* ctx, NDBT_Step* step){ } // Now drop all indexes that where created - for (unsigned int i = 0; i < attrList.attriblist.size(); i++){ + for (i = 0; i < attrList.attriblist.size(); i++){ // Try to drop index if (drop_index(i, pNdb, pTab, attrList.attriblist[i]) != NDBT_OK) @@ -1083,8 +1085,8 @@ runUniqueNullTransactions(NDBT_Context* ctx, NDBT_Step* step){ else pIdx.setType(NdbDictionary::Index::UniqueHashIndex); pIdx.setStoredIndex(logged); - - for (int c = 0; c< pTab->getNoOfColumns(); c++){ + int c; + for (c = 0; c< pTab->getNoOfColumns(); c++){ const NdbDictionary::Column * col = pTab->getColumn(c); if(col->getPrimaryKey()){ pIdx.addIndexColumn(col->getName()); @@ -1093,7 +1095,7 @@ runUniqueNullTransactions(NDBT_Context* ctx, NDBT_Step* step){ } int colId = -1; - for (int c = 0; c< pTab->getNoOfColumns(); c++){ + for (c = 0; c< pTab->getNoOfColumns(); c++){ const NdbDictionary::Column * col = pTab->getColumn(c); if(col->getNullable()){ pIdx.addIndexColumn(col->getName()); diff --git a/ndb/test/ndbapi/testLcp.cpp b/ndb/test/ndbapi/testLcp.cpp index c92be091a97..d11692db761 100644 --- a/ndb/test/ndbapi/testLcp.cpp +++ b/ndb/test/ndbapi/testLcp.cpp @@ -85,7 +85,8 @@ main(int argc, char ** argv){ g_info << " where ZLCP_OP_WRITE_RT_BREAK is finished before SAVE_PAGES" << endl; require(!pause_lcp()); - for(size_t j = 0; j<g_rows; j++){ + size_t j; + for(j = 0; j<g_rows; j++){ require(!do_op(j)); } require(!continue_lcp(5900)); @@ -98,7 +99,7 @@ main(int argc, char ** argv){ << endl; require(!load_table()); require(!pause_lcp()); - for(size_t j = 0; j<g_rows; j++){ + for(j = 0; j<g_rows; j++){ require(!do_op(j)); } require(!continue_lcp(5901)); @@ -109,7 +110,7 @@ main(int argc, char ** argv){ g_info << "Testing pre LCP operations, undo-ed at commit" << endl; require(!load_table()); require(!pause_lcp()); - for(size_t j = 0; j<g_rows; j++){ + for(j = 0; j<g_rows; j++){ require(!do_op(j)); } require(!continue_lcp(5902)); diff --git a/ndb/test/ndbapi/testNdbApi.cpp b/ndb/test/ndbapi/testNdbApi.cpp index 74cb1f8bcd0..a1ebac609b6 100644 --- a/ndb/test/ndbapi/testNdbApi.cpp +++ b/ndb/test/ndbapi/testNdbApi.cpp @@ -88,10 +88,10 @@ int runTestMaxNdb(NDBT_Context* ctx, NDBT_Step* step){ oldi = i; - for(size_t i = 0; i < ndbVector.size(); i++){ - delete ndbVector[i]; - if(((i+1) % 250) == 0){ - ndbout << "Deleted " << (Uint64) i << " ndb objects " << endl; + for(size_t j = 0; j < ndbVector.size(); j++){ + delete ndbVector[j]; + if(((j+1) % 250) == 0){ + ndbout << "Deleted " << (Uint64) j << " ndb objects " << endl; } } ndbVector.clear(); @@ -178,8 +178,8 @@ int runTestMaxTransaction(NDBT_Context* ctx, NDBT_Step* step){ oldi = i; - for(size_t i = 0; i < conVector.size(); i++){ - pNdb->closeTransaction(conVector[i]); + for(size_t j = 0; j < conVector.size(); j++){ + pNdb->closeTransaction(conVector[j]); } conVector.clear(); l++; @@ -537,8 +537,8 @@ int runTestDeleteNdb(NDBT_Context* ctx, NDBT_Step* step){ } // Delete the ndb objects - for(size_t i = 0; i < ndbVector.size(); i++) - delete ndbVector[i]; + for(size_t j = 0; j < ndbVector.size(); j++) + delete ndbVector[j]; ndbVector.clear(); l++; } diff --git a/ndb/test/ndbapi/testOIBasic.cpp b/ndb/test/ndbapi/testOIBasic.cpp index 21862e02328..41f0686e63b 100644 --- a/ndb/test/ndbapi/testOIBasic.cpp +++ b/ndb/test/ndbapi/testOIBasic.cpp @@ -407,10 +407,11 @@ Col::verify(const void* addr) const const unsigned char* p = (const unsigned char*)addr; unsigned n = (p[0] << 8) | p[1]; assert(n <= m_length); - for (unsigned i = 0; i < n; i++) { + unsigned i; + for (i = 0; i < n; i++) { assert(p[2 + i] != 0); } - for (unsigned i = n; i < m_length; i++) { + for (i = n; i < m_length; i++) { assert(p[2 + i] == 0); } } @@ -3021,7 +3022,8 @@ runstep(Par par, const char* fname, TFunc func, unsigned mode) { LL2(fname); const int threads = (mode & ST ? 1 : par.m_threads); - for (int n = 0; n < threads; n++) { + int n; + for (n = 0; n < threads; n++) { LL4("start " << n); Thr& thr = *g_thrlist[n]; thr.m_par.m_tab = par.m_tab; @@ -3033,7 +3035,7 @@ runstep(Par par, const char* fname, TFunc func, unsigned mode) thr.start(); } unsigned errs = 0; - for (int n = threads - 1; n >= 0; n--) { + for (n = threads - 1; n >= 0; n--) { LL4("stop " << n); Thr& thr = *g_thrlist[n]; thr.stopped(); @@ -3301,10 +3303,11 @@ runtest(Par par) CHK(con.connect() == 0); par.m_con = &con; g_thrlist = new Thr* [par.m_threads]; - for (unsigned n = 0; n < par.m_threads; n++) { + unsigned n; + for (n = 0; n < par.m_threads; n++) { g_thrlist[n] = 0; } - for (unsigned n = 0; n < par.m_threads; n++) { + for (n = 0; n < par.m_threads; n++) { g_thrlist[n] = new Thr(par, n); Thr& thr = *g_thrlist[n]; assert(thr.m_thread != 0); @@ -3330,11 +3333,11 @@ runtest(Par par) } } } - for (unsigned n = 0; n < par.m_threads; n++) { + for (n = 0; n < par.m_threads; n++) { Thr& thr = *g_thrlist[n]; thr.exit(); } - for (unsigned n = 0; n < par.m_threads; n++) { + for (n = 0; n < par.m_threads; n++) { Thr& thr = *g_thrlist[n]; thr.join(); delete &thr; diff --git a/ndb/test/ndbapi/testReadPerf.cpp b/ndb/test/ndbapi/testReadPerf.cpp index 8d0d78cbe8c..380a809ad00 100644 --- a/ndb/test/ndbapi/testReadPerf.cpp +++ b/ndb/test/ndbapi/testReadPerf.cpp @@ -99,7 +99,8 @@ main(int argc, const char** argv){ { "verbose", 'v', arg_flag, &verbose, "Print verbose status", "verbose" } }; const int num_args = 1 + P_MAX; - for(int i = 0; i<P_MAX; i++){ + int i; + for(i = 0; i<P_MAX; i++){ args[i+1].long_name = g_paramters[i].name; args[i+1].short_name = * g_paramters[i].name; args[i+1].type = arg_integer; @@ -127,7 +128,7 @@ main(int argc, const char** argv){ g_err << "Wait until ready failed" << endl; goto error; } - for(int i = optind; i<argc; i++){ + for(i = optind; i<argc; i++){ const char * T = argv[i]; g_info << "Testing " << T << endl; BaseString::snprintf(g_table, sizeof(g_table), T); diff --git a/ndb/test/ndbapi/testRestartGci.cpp b/ndb/test/ndbapi/testRestartGci.cpp index e817245af55..4e541d1f38f 100644 --- a/ndb/test/ndbapi/testRestartGci.cpp +++ b/ndb/test/ndbapi/testRestartGci.cpp @@ -132,7 +132,8 @@ int runVerifyInserts(NDBT_Context* ctx, NDBT_Step* step){ // RULE1: The vector with saved records should have exactly as many // records with lower or same gci as there are in DB int recordsWithLowerOrSameGci = 0; - for (unsigned i = 0; i < savedRecords.size(); i++){ + unsigned i; + for (i = 0; i < savedRecords.size(); i++){ if (savedRecords[i].m_gci <= restartGCI) recordsWithLowerOrSameGci++; } @@ -144,7 +145,7 @@ int runVerifyInserts(NDBT_Context* ctx, NDBT_Step* step){ // RULE2: The records found in db should have same or lower // gci as in the vector - for (unsigned i = 0; i < savedRecords.size(); i++){ + for (i = 0; i < savedRecords.size(); i++){ CHECK(hugoOps.startTransaction(pNdb) == 0); CHECK(hugoOps.pkReadRecord(pNdb, i) == 0); if (hugoOps.execute_Commit(pNdb) != 0){ diff --git a/ndb/test/ndbapi/testScanPerf.cpp b/ndb/test/ndbapi/testScanPerf.cpp index c1334125978..003fc67179f 100644 --- a/ndb/test/ndbapi/testScanPerf.cpp +++ b/ndb/test/ndbapi/testScanPerf.cpp @@ -80,7 +80,8 @@ main(int argc, const char** argv){ { "verbose", 'v', arg_flag, &verbose, "Print verbose status", "verbose" } }; const int num_args = 1 + P_MAX; - for(int i = 0; i<P_MAX; i++){ + int i; + for(i = 0; i<P_MAX; i++){ args[i+1].long_name = g_paramters[i].name; args[i+1].short_name = * g_paramters[i].name; args[i+1].type = arg_integer; @@ -107,7 +108,7 @@ main(int argc, const char** argv){ g_err << "Wait until ready failed" << endl; goto error; } - for(int i = optind; i<argc; i++){ + for(i = optind; i<argc; i++){ const char * T = argv[i]; g_info << "Testing " << T << endl; BaseString::snprintf(g_tablename, sizeof(g_tablename), T); diff --git a/ndb/test/ndbapi/testSystemRestart.cpp b/ndb/test/ndbapi/testSystemRestart.cpp index f8f2b84acc4..35016896495 100644 --- a/ndb/test/ndbapi/testSystemRestart.cpp +++ b/ndb/test/ndbapi/testSystemRestart.cpp @@ -452,7 +452,7 @@ int runSystemRestart3(NDBT_Context* ctx, NDBT_Step* step){ } Vector<int> nodeIds; - for(Uint32 i = 0; i<nodeCount; i++) + for(i = 0; i<nodeCount; i++) nodeIds.push_back(restarter.getDbNodeId(i)); Uint32 currentRestartNodeIndex = 0; @@ -561,7 +561,7 @@ int runSystemRestart4(NDBT_Context* ctx, NDBT_Step* step){ } Vector<int> nodeIds; - for(Uint32 i = 0; i<nodeCount; i++) + for(i = 0; i<nodeCount; i++) nodeIds.push_back(restarter.getDbNodeId(i)); Uint32 currentRestartNodeIndex = 0; @@ -691,7 +691,7 @@ int runSystemRestart5(NDBT_Context* ctx, NDBT_Step* step){ } Vector<int> nodeIds; - for(Uint32 i = 0; i<nodeCount; i++) + for(i = 0; i<nodeCount; i++) nodeIds.push_back(restarter.getDbNodeId(i)); Uint32 currentRestartNodeIndex = 0; @@ -821,7 +821,7 @@ int runSystemRestart6(NDBT_Context* ctx, NDBT_Step* step){ } Vector<int> nodeIds; - for(Uint32 i = 0; i<nodeCount; i++) + for(i = 0; i<nodeCount; i++) nodeIds.push_back(restarter.getDbNodeId(i)); Uint32 currentRestartNodeIndex = 0; @@ -877,7 +877,7 @@ int runSystemRestart7(NDBT_Context* ctx, NDBT_Step* step){ } Vector<int> nodeIds; - for(Uint32 i = 0; i<nodeCount; i++) + for(i = 0; i<nodeCount; i++) nodeIds.push_back(restarter.getDbNodeId(i)); int a_nodeIds[64]; @@ -952,7 +952,7 @@ int runSystemRestart8(NDBT_Context* ctx, NDBT_Step* step){ } Vector<int> nodeIds; - for(Uint32 i = 0; i<nodeCount; i++) + for(i = 0; i<nodeCount; i++) nodeIds.push_back(restarter.getDbNodeId(i)); int a_nodeIds[64]; diff --git a/ndb/test/run-test/Makefile.am b/ndb/test/run-test/Makefile.am index 1eac96e7ac7..c890536dcc6 100644 --- a/ndb/test/run-test/Makefile.am +++ b/ndb/test/run-test/Makefile.am @@ -11,9 +11,8 @@ test_SCRIPTS=atrt-analyze-result.sh atrt-gather-result.sh atrt-setup.sh \ atrt-clear-result.sh make-config.sh make-index.sh make-html-reports.sh atrt_SOURCES = main.cpp -INCLUDES_LOC = -I$(top_srcdir)/ndb/test/include -I$(top_srcdir)/ndb/src/mgmclient -LDADD_LOC = $(top_builddir)/ndb/src/mgmclient/CpcClient.o \ - $(top_builddir)/ndb/test/src/libNDBT.a \ +INCLUDES_LOC = -I$(top_srcdir)/ndb/test/include +LDADD_LOC = $(top_builddir)/ndb/test/src/libNDBT.a \ $(top_builddir)/ndb/src/libndbclient.la \ $(top_builddir)/dbug/libdbug.a \ $(top_builddir)/mysys/libmysys.a \ diff --git a/ndb/test/run-test/Makefile_old b/ndb/test/run-test/Makefile_old deleted file mode 100644 index 6b4689b2dbb..00000000000 --- a/ndb/test/run-test/Makefile_old +++ /dev/null @@ -1,22 +0,0 @@ -include .defs.mk - -TYPE := util - -BIN_TARGET := atrt -BIN_TARGET_LIBS := mgmapi - -SOURCES = main.cpp -SCRIPTS = atrt-analyze-result.sh atrt-gather-result.sh atrt-setup.sh \ - atrt-clear-result.sh make-config.sh - -OBJECTS_LOC = $(call fixpath,$(NDB_TOP)/src/mgmclient/CpcClient.o) - -CFLAGS_main.cpp := -I$(call fixpath,$(NDB_TOP)/src/mgmclient) -CCFLAGS_LOC += -I$(call fixpath,$(NDB_TOP)/include/mgmapi) - -include $(NDB_TOP)/Epilogue.mk - -_bins:: - -rm -f $(SCRIPTS:%=$(NDB_TOP)/bin/%) - cp $(SCRIPTS) $(NDB_TOP)/bin - diff --git a/ndb/src/mgmclient/CpcClient.cpp b/ndb/test/src/CpcClient.cpp index d407ba65312..d407ba65312 100644 --- a/ndb/src/mgmclient/CpcClient.cpp +++ b/ndb/test/src/CpcClient.cpp diff --git a/ndb/test/src/Makefile.am b/ndb/test/src/Makefile.am index a8f34a0ea22..56f3d6a1ec6 100644 --- a/ndb/test/src/Makefile.am +++ b/ndb/test/src/Makefile.am @@ -9,7 +9,8 @@ libNDBT_a_SOURCES = \ HugoAsynchTransactions.cpp UtilTransactions.cpp \ NdbRestarter.cpp NdbRestarts.cpp NDBT_Output.cpp \ NdbBackup.cpp NdbConfig.cpp NdbGrep.cpp NDBT_Table.cpp \ - NdbSchemaCon.cpp NdbSchemaOp.cpp getarg.c + NdbSchemaCon.cpp NdbSchemaOp.cpp getarg.c \ + CpcClient.cpp INCLUDES_LOC = -I$(top_srcdir)/ndb/src/common/mgmcommon -I$(top_srcdir)/ndb/include/mgmcommon -I$(top_srcdir)/ndb/include/kernel -I$(top_srcdir)/ndb/src/mgmapi diff --git a/ndb/test/src/Makefile_old b/ndb/test/src/Makefile_old deleted file mode 100644 index 2738ce1aba2..00000000000 --- a/ndb/test/src/Makefile_old +++ /dev/null @@ -1,33 +0,0 @@ -include .defs.mk - -TYPE := ndbapitest - -ARCHIVE_TARGET := NDBT - -SOURCES = NDBT_ReturnCodes.cpp \ - NDBT_Error.cpp NDBT_Tables.cpp NDBT_ResultRow.cpp \ - NDBT_Test.cpp HugoCalculator.cpp \ - HugoOperations.cpp HugoTransactions.cpp \ - HugoAsynchTransactions.cpp UtilTransactions.cpp \ - NdbRestarter.cpp NdbRestarts.cpp NDBT_Output.cpp \ - NdbBackup.cpp NdbConfig.cpp NdbGrep.cpp NDBT_Table.cpp - -SOURCES.c = - -CFLAGS_NdbRestarter.cpp := -I$(call fixpath,$(NDB_TOP)/src/common/mgmcommon) -CFLAGS_NdbConfig.cpp := -I$(call fixpath,$(NDB_TOP)/include/mgmcommon) \ - -I$(call fixpath,$(NDB_TOP)/src/mgmapi) -CFLAGS_NdbRestarts.cpp := -I$(call fixpath,$(NDB_TOP)/include/kernel) -CFLAGS_NdbBackup.cpp := -I$(call fixpath,$(NDB_TOP)/include/mgmcommon) \ - -I$(call fixpath,$(NDB_TOP)/src/mgmapi) \ - -I$(call fixpath,$(NDB_TOP)/include/kernel) -CFLAGS_NdbGrep.cpp += -I$(call fixpath,$(NDB_TOP)/include/kernel) -I$(call fixpath,$(NDB_TOP)/include/mgmcommon) - -include $(NDB_TOP)/Epilogue.mk - - - - - - - diff --git a/ndb/test/tools/Makefile.am b/ndb/test/tools/Makefile.am index 8d94c21b721..3255267b636 100644 --- a/ndb/test/tools/Makefile.am +++ b/ndb/test/tools/Makefile.am @@ -20,12 +20,10 @@ copy_tab_SOURCES = copy_tab.cpp create_index_SOURCES = create_index.cpp ndb_cpcc_SOURCES = cpcc.cpp -INCLUDES_LOC = -I$(top_srcdir)/ndb/src/mgmclient - include $(top_srcdir)/ndb/config/common.mk.am include $(top_srcdir)/ndb/config/type_ndbapitest.mk.am -ndb_cpcc_LDADD = $(LDADD) $(top_builddir)/ndb/src/mgmclient/CpcClient.o +ndb_cpcc_LDADD = $(LDADD) # Don't update the files from bitkeeper %::SCCS/s.% diff --git a/ndb/test/tools/Makefile_old b/ndb/test/tools/Makefile_old deleted file mode 100644 index b8e90ae207f..00000000000 --- a/ndb/test/tools/Makefile_old +++ /dev/null @@ -1,9 +0,0 @@ -include .defs.mk - -DIRS := hugoCalculator hugoFill hugoLoad hugoLockRecords \ - hugoPkDelete hugoPkRead hugoPkReadRecord hugoPkUpdate \ - hugoScanRead hugoScanUpdate restart waiter - -include $(NDB_TOP)/Epilogue.mk - -_bins_ndbapi : _libs_src diff --git a/ndb/test/tools/old_dirs/waiter/Makefile_old b/ndb/test/tools/old_dirs/waiter/Makefile_old deleted file mode 100644 index da2c9daff00..00000000000 --- a/ndb/test/tools/old_dirs/waiter/Makefile_old +++ /dev/null @@ -1,11 +0,0 @@ -include .defs.mk - -TYPE := ndbapitest - -BIN_TARGET := waiter - -# Source files of non-templated classes (.C files) -SOURCES = waiter.cpp - -include $(NDB_TOP)/Epilogue.mk - diff --git a/ndb/tools/Makefile.am b/ndb/tools/Makefile.am index 64625f69ea2..fad9bf9ff84 100644 --- a/ndb/tools/Makefile.am +++ b/ndb/tools/Makefile.am @@ -1,5 +1,6 @@ ndbtools_PROGRAMS = \ + ndb_test_platform \ ndb_waiter \ ndb_drop_table \ ndb_delete_all \ @@ -11,6 +12,7 @@ ndbtools_PROGRAMS = \ tools_common_sources = ../test/src/NDBT_ReturnCodes.cpp ../test/src/NDBT_Table.cpp ../test/src/NDBT_Output.cpp +ndb_test_platform_SOURCES = ndb_test_platform.cpp ndb_waiter_SOURCES = waiter.cpp $(tools_common_sources) ndb_delete_all_SOURCES = delete_all.cpp $(tools_common_sources) ndb_desc_SOURCES = desc.cpp $(tools_common_sources) @@ -23,6 +25,7 @@ ndb_select_count_SOURCES = select_count.cpp $(tools_common_sources) include $(top_srcdir)/ndb/config/common.mk.am include $(top_srcdir)/ndb/config/type_ndbapitools.mk.am +ndb_test_platform_LDFLAGS = @ndb_bin_am_ldflags@ ndb_waiter_LDFLAGS = @ndb_bin_am_ldflags@ ndb_drop_table_LDFLAGS = @ndb_bin_am_ldflags@ ndb_delete_all_LDFLAGS = @ndb_bin_am_ldflags@ diff --git a/ndb/tools/Makefile_old b/ndb/tools/Makefile_old deleted file mode 100644 index b9dc6883e18..00000000000 --- a/ndb/tools/Makefile_old +++ /dev/null @@ -1,12 +0,0 @@ -include .defs.mk - -BIN_DIRS = select_all select_count desc list_tables \ - drop_tab delete_all copy_tab \ - create_index drop_index verify_index cpcc - -ifneq ($(NDB_ODBC),N) -BIN_DIRS += ndbsql -endif - -include $(NDB_TOP)/Epilogue.mk - diff --git a/ndb/tools/ndb_test_platform.cpp b/ndb/tools/ndb_test_platform.cpp new file mode 100644 index 00000000000..72dd146dacd --- /dev/null +++ b/ndb/tools/ndb_test_platform.cpp @@ -0,0 +1,95 @@ +/* Copyright (C) 2003 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; either version 2 of the License, 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 */ + + +#include <ndb_global.h> +#include <my_sys.h> +#include <BaseString.hpp> + +/* + * Test BaseString::snprintf + */ + +static +int test_snprintf(const char * fmt, int buf_sz, int result) +{ + int ret; + char buf[100]; + ret = BaseString::snprintf(buf, buf_sz, fmt); + + if(ret < 0) + { + printf("BaseString::snprint returns %d with size=%d and strlen(fmt)=%d\n", + ret, buf_sz, strlen(fmt)); + return -1; + } + + if(ret+1 == buf_sz) + { + printf("BaseString::snprint truncates returns %d with size=%d and strlen(fmt)=%d\n", + ret, buf_sz, strlen(fmt)); + return -1; + } + + if(ret != result) + { + printf("BaseString::snprint returns incorrect value: returned=%d != expected=%d\n", + ret, result); + return -1; + } + + for(ret = 0; ret+1 < buf_sz && ret < result; ret++) + { + if(buf[ret] != fmt[ret]) + { + printf("BaseString::snprint Incorrect value in output buffer: " + "size=%d returned=expected=%d at pos=%d result=%d != expected=%d\n", + buf_sz, result, ret, buf[ret], fmt[ret]); + return -1; + } + } + return 0; +} + +int +main(void) +{ + /* + * Test BaseString::snprintf + */ + + if(test_snprintf("test", 1, 4)) + return -1; + + if(test_snprintf("test", 0, 4)) + return -1; + + if(test_snprintf("test", 100, 4)) + return -1; + + /* + * Test UintPtr + */ + + if (sizeof(UintPtr) != sizeof(Uint32*)) + { + printf("sizeof(UintPtr)=%d != sizeof(Uint32*)=%d\n", + sizeof(UintPtr), sizeof(Uint32*)); + return -1; + } + + return 0; +} diff --git a/ndb/tools/waiter.cpp b/ndb/tools/waiter.cpp index c9e76bb8ed3..be572d7c275 100644 --- a/ndb/tools/waiter.cpp +++ b/ndb/tools/waiter.cpp @@ -86,7 +86,7 @@ int main(int argc, char** argv){ if (_hostName == NULL){ LocalConfig lcfg; - if(!lcfg.init()) + if(!lcfg.init(opt_connect_str, 0)) { lcfg.printError(); lcfg.printUsage(); diff --git a/scripts/fill_help_tables.sh b/scripts/fill_help_tables.sh index cb5437f7178..1f44e9fa488 100644 --- a/scripts/fill_help_tables.sh +++ b/scripts/fill_help_tables.sh @@ -197,6 +197,9 @@ sub prepare_name $a =~ s/(\@node(.*?)\n)/ /g; $a =~ s/(\@tab)/\t/g; $a =~ s/\@item/ /g; + $a =~ s/\@minus\{\}/-/g; + $a =~ s/\@var\{((.|\n)+?)\}/$1/go; + $a =~ s/\@command\{((.|\n)+?)\}/$1/go; $a =~ s/\@code\{((.|\n)+?)\}/$1/go; $a =~ s/\@strong\{(.+?)\}/$1/go; $a =~ s/\@samp\{(.+?)\}/$1/go; @@ -244,6 +247,9 @@ sub prepare_description $a =~ s/(\@item)/ /g; $a =~ s/(\@tindex\s(.*?)\n)//g; $a =~ s/(\@c\s(.*?)\n)//g; + $a =~ s/\@minus\{\}/-/g; + $a =~ s/\@var\{((.|\n)+?)\}/$1/go; + $a =~ s/\@command\{((.|\n)+?)\}/$1/go; $a =~ s/\@code\{((.|\n)+?)\}/$1/go; $a =~ s/\@strong\{(.+?)\}/$1/go; $a =~ s/\@samp\{(.+?)\}/$1/go; @@ -273,6 +279,7 @@ sub prepare_example $a =~ s/(^\@c for_help_topic(.*?)\n)//g; + $a =~ s/\@var\{((.|\n)+?)\}/$1/go; $a =~ s/\\/\\\\/g; $a =~ s/(\@{)/{/g; $a =~ s/(\@})/}/g; diff --git a/sql/field.cc b/sql/field.cc index 1275e1bbb8e..56e3ab71bd8 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -4418,6 +4418,8 @@ String *Field_string::val_str(String *val_buffer __attribute__((unused)), int Field_string::cmp(const char *a_ptr, const char *b_ptr) { + uint a_len, b_len; + if (field_charset->strxfrm_multiply > 1) { /* @@ -4429,10 +4431,19 @@ int Field_string::cmp(const char *a_ptr, const char *b_ptr) (const uchar*) b_ptr, field_length); } - return my_strnncoll(field_charset,(const uchar*) a_ptr, field_length, - (const uchar*) b_ptr, field_length); + if (field_charset->mbmaxlen != 1) + { + uint char_len= field_length/field_charset->mbmaxlen; + a_len= my_charpos(field_charset, a_ptr, a_ptr + field_length, char_len); + b_len= my_charpos(field_charset, b_ptr, b_ptr + field_length, char_len); + } + else + a_len= b_len= field_length; + return my_strnncoll(field_charset,(const uchar*) a_ptr, a_len, + (const uchar*) b_ptr, b_len); } + void Field_string::sort_string(char *to,uint length) { uint tmp=my_strnxfrm(field_charset, @@ -5958,8 +5969,14 @@ Field *make_field(char *ptr, uint32 field_length, if (f_is_alpha(pack_flag)) { if (!f_is_packed(pack_flag)) - return new Field_string(ptr,field_length,null_pos,null_bit, - unireg_check, field_name, table, field_charset); + { + if (field_type == FIELD_TYPE_STRING || + field_type == FIELD_TYPE_VAR_STRING) + return new Field_string(ptr,field_length,null_pos,null_bit, + unireg_check, field_name, table, + field_charset); + return 0; // Error + } uint pack_length=calc_pack_length((enum_field_types) f_packtype(pack_flag), diff --git a/sql/field_conv.cc b/sql/field_conv.cc index 890687fc925..61a5a28f47b 100644 --- a/sql/field_conv.cc +++ b/sql/field_conv.cc @@ -473,7 +473,7 @@ void (*Copy_field::get_copy_func(Field *to,Field *from))(Copy_field*) { if (to->flags & BLOB_FLAG) { - if (!(from->flags & BLOB_FLAG)) + if (!(from->flags & BLOB_FLAG) || from->charset() != to->charset()) return do_conv_blob; if (from_length != to_length || to->table->db_low_byte_first != from->table->db_low_byte_first) diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index b2e115e9779..17aaaf20fa2 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -1290,7 +1290,6 @@ int ha_ndbcluster::set_bounds(NdbIndexScanOperation *op, Field *field= key_part->field; uint part_len= key_part->length; uint part_store_len= key_part->store_length; - bool part_nullable= (bool) key_part->null_bit; // Info about each key part struct part_st { bool part_last; @@ -1312,9 +1311,9 @@ int ha_ndbcluster::set_bounds(NdbIndexScanOperation *op, p.part_last= (tot_len + part_store_len >= key_tot_len[j]); p.key= keys[j]; p.part_ptr= &p.key->key[tot_len]; - p.part_null= (field->maybe_null() && *p.part_ptr); + p.part_null= key_part->null_bit && *p.part_ptr; p.bound_ptr= (const char *) - p.part_null ? 0 : part_nullable ? p.part_ptr + 1 : p.part_ptr; + p.part_null ? 0 : key_part->null_bit ? p.part_ptr + 1 : p.part_ptr; if (j == 0) { @@ -2325,7 +2324,7 @@ int ha_ndbcluster::index_last(byte *buf) DBUG_RETURN(0); } } - DBUG_RETURN(1); + DBUG_RETURN(res); } @@ -2788,7 +2787,7 @@ int ha_ndbcluster::reset() const char **ha_ndbcluster::bas_ext() const -{ static const char *ext[]= { ".ndb", NullS }; return ext; } +{ static const char *ext[]= { ha_ndb_ext, NullS }; return ext; } /* @@ -3322,7 +3321,7 @@ int ha_ndbcluster::create(const char *name, { NDBTAB tab; NDBCOL col; - uint pack_length, length, i; + uint pack_length, length, i, pk_length= 0; const void *data, *pack_data; const char **key_names= form->keynames.type_names; char name2[FN_HEADLEN]; @@ -3369,6 +3368,8 @@ int ha_ndbcluster::create(const char *name, if ((my_errno= create_ndb_column(col, field, info))) DBUG_RETURN(my_errno); tab.addColumn(col); + if(col.getPrimaryKey()) + pk_length += (field->pack_length() + 3) / 4; } // No primary key, create shadow key as 64 bit, auto increment @@ -3382,6 +3383,39 @@ int ha_ndbcluster::create(const char *name, col.setPrimaryKey(TRUE); col.setAutoIncrement(TRUE); tab.addColumn(col); + pk_length += 2; + } + + // Make sure that blob tables don't have to big part size + for (i= 0; i < form->fields; i++) + { + /** + * The extra +7 concists + * 2 - words from pk in blob table + * 5 - from extra words added by tup/dict?? + */ + switch (form->field[i]->real_type()) { + case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_MEDIUM_BLOB: + case MYSQL_TYPE_LONG_BLOB: + { + NdbDictionary::Column * col = tab.getColumn(i); + int size = pk_length + (col->getPartSize()+3)/4 + 7; + if(size > NDB_MAX_TUPLE_SIZE_IN_WORDS && + (pk_length+7) < NDB_MAX_TUPLE_SIZE_IN_WORDS) + { + size = NDB_MAX_TUPLE_SIZE_IN_WORDS - pk_length - 7; + col->setPartSize(4*size); + } + /** + * If size > NDB_MAX and pk_length+7 >= NDB_MAX + * then the table can't be created anyway, so skip + * changing part size, and have error later + */ + } + default: + break; + } } if ((my_errno= check_ndb_connection())) diff --git a/sql/handler.cc b/sql/handler.cc index bb5e980f7bf..5dae7950390 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -54,7 +54,11 @@ static int NEAR_F delete_file(const char *name,const char *ext,int extflag); -ulong ha_read_count, ha_discover_count; +ulong ha_read_count, ha_write_count, ha_delete_count, ha_update_count, + ha_read_key_count, ha_read_next_count, ha_read_prev_count, + ha_read_first_count, ha_read_last_count, + ha_commit_count, ha_rollback_count, + ha_read_rnd_count, ha_read_rnd_next_count, ha_discover_count; static SHOW_COMP_OPTION have_yes= SHOW_OPTION_YES; @@ -105,9 +109,12 @@ const char *tx_isolation_names[] = TYPELIB tx_isolation_typelib= {array_elements(tx_isolation_names)-1,"", tx_isolation_names, NULL}; +static TYPELIB known_extensions= {0,"known_exts", NULL, NULL}; +uint known_extensions_id= 0; + enum db_type ha_resolve_by_name(const char *name, uint namelen) { - THD *thd= current_thd; + THD *thd=current_thd; if (thd && !my_strcasecmp(&my_charset_latin1, name, "DEFAULT")) { return (enum db_type) thd->variables.table_type; } @@ -138,7 +145,6 @@ const char *ha_get_storage_engine(enum db_type db_type) enum db_type ha_checktype(enum db_type database_type) { show_table_type_st *types; - THD *thd= current_thd; for (types= sys_table_types; types->type; types++) { if ((database_type == types->db_type) && @@ -157,11 +163,12 @@ enum db_type ha_checktype(enum db_type database_type) break; } - return ((enum db_type) thd->variables.table_type != DB_TYPE_UNKNOWN ? - (enum db_type) thd->variables.table_type : - (enum db_type) global_system_variables.table_type != - DB_TYPE_UNKNOWN ? - (enum db_type) global_system_variables.table_type : DB_TYPE_MYISAM); + return + DB_TYPE_UNKNOWN != (enum db_type) current_thd->variables.table_type ? + (enum db_type) current_thd->variables.table_type : + DB_TYPE_UNKNOWN != (enum db_type) global_system_variables.table_type ? + (enum db_type) global_system_variables.table_type : + DB_TYPE_MYISAM; } /* ha_checktype */ @@ -558,7 +565,7 @@ int ha_commit_trans(THD *thd, THD_TRANS* trans) thd->variables.tx_isolation=thd->session_tx_isolation; if (operation_done) { - statistic_increment(thd->status_var.ha_commit_count,&LOCK_status); + statistic_increment(ha_commit_count,&LOCK_status); thd->transaction.cleanup(); } if (need_start_waiters) @@ -577,6 +584,12 @@ int ha_rollback_trans(THD *thd, THD_TRANS *trans) if (opt_using_transactions) { bool operation_done=0; + /* + As rollback can be 30 times slower than insert in InnoDB, and user may + not know there's rollback (if it's because of a dupl row), better warn. + */ + const char *save_proc_info= thd->proc_info; + thd->proc_info= "Rolling back"; #ifdef HAVE_NDBCLUSTER_DB if (trans->ndb_tid) { @@ -647,7 +660,8 @@ int ha_rollback_trans(THD *thd, THD_TRANS *trans) } thd->variables.tx_isolation=thd->session_tx_isolation; if (operation_done) - statistic_increment(thd->status_var.ha_rollback_count,&LOCK_status); + statistic_increment(ha_rollback_count,&LOCK_status); + thd->proc_info= save_proc_info; } #endif /* USING_TRANSACTIONS */ DBUG_RETURN(error); @@ -720,7 +734,7 @@ int ha_rollback_to_savepoint(THD *thd, char *savepoint_name) operation_done=1; #endif if (operation_done) - statistic_increment(thd->status_var.ha_rollback_count,&LOCK_status); + statistic_increment(ha_rollback_count,&LOCK_status); } #endif /* USING_TRANSACTIONS */ @@ -760,6 +774,25 @@ int ha_savepoint(THD *thd, char *savepoint_name) DBUG_RETURN(error); } + +int ha_start_consistent_snapshot(THD *thd) +{ +#ifdef HAVE_INNOBASE_DB + if ((have_innodb == SHOW_OPTION_YES) && + !innobase_start_trx_and_assign_read_view(thd)) + return 0; +#endif + /* + Same idea as when one wants to CREATE TABLE in one engine which does not + exist: + */ + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR, + "This MySQL server does not support any " + "consistent-read capable storage engine"); + return 0; +} + + bool ha_flush_logs() { bool result=0; @@ -783,14 +816,10 @@ bool ha_flush_logs() int ha_delete_table(enum db_type table_type, const char *path) { - handler *file; char tmp_path[FN_REFLEN]; - - /* DB_TYPE_UNKNOWN is used in ALTER TABLE when renaming only .frm files */ - if (table_type == DB_TYPE_UNKNOWN || - ! (file=get_new_handler((TABLE*) 0, table_type))) + handler *file=get_new_handler((TABLE*) 0, table_type); + if (!file) return ENOENT; - if (lower_case_table_names == 2 && !(file->table_flags() & HA_FILE_BASED)) { /* Ensure that table handler get path in lower case */ @@ -919,7 +948,7 @@ int handler::read_first_row(byte * buf, uint primary_key) register int error; DBUG_ENTER("handler::read_first_row"); - statistic_increment(current_thd->status_var.ha_read_first_count,&LOCK_status); + statistic_increment(ha_read_first_count,&LOCK_status); /* If there is very few deleted rows in the table, find the first row by @@ -943,163 +972,41 @@ int handler::read_first_row(byte * buf, uint primary_key) /* - Generate the next auto-increment number based on increment and offset - - In most cases increment= offset= 1, in which case we get: - 1,2,3,4,5,... - If increment=10 and offset=5 and previous number is 1, we get: - 1,5,15,25,35,... -*/ - -inline ulonglong -next_insert_id(ulonglong nr,struct system_variables *variables) -{ - nr= (((nr+ variables->auto_increment_increment - - variables->auto_increment_offset)) / - (ulonglong) variables->auto_increment_increment); - return (nr* (ulonglong) variables->auto_increment_increment + - variables->auto_increment_offset); -} - - -/* - Updates columns with type NEXT_NUMBER if: - - - If column value is set to NULL (in which case - auto_increment_field_not_null is 0) - - If column is set to 0 and (sql_mode & MODE_NO_AUTO_VALUE_ON_ZERO) is not - set. In the future we will only set NEXT_NUMBER fields if one sets them - to NULL (or they are not included in the insert list). - - - There are two different cases when the above is true: - - - thd->next_insert_id == 0 (This is the normal case) - In this case we set the set the column for the first row to the value - next_insert_id(get_auto_increment(column))) which is normally - max-used-column-value +1. - - We call get_auto_increment() only for the first row in a multi-row - statement. For the following rows we generate new numbers based on the - last used number. - - - thd->next_insert_id != 0. This happens when we have read a statement - from the binary log or when one has used SET LAST_INSERT_ID=#. - - In this case we will set the column to the value of next_insert_id. - The next row will be given the id - next_insert_id(next_insert_id) - - The idea is that generated auto_increment values are predictable and - independent of the column values in the table. This is needed to be - able to replicate into a table that already has rows with a higher - auto-increment value than the one that is inserted. - - After we have already generated an auto-increment number and the user - inserts a column with a higher value than the last used one, we will - start counting from the inserted value. - - thd->next_insert_id is cleared after it's been used for a statement. + Updates field with field_type NEXT_NUMBER according to following: + if field = 0 change field to the next free key in database. */ void handler::update_auto_increment() { - ulonglong nr; - THD *thd= table->in_use; - struct system_variables *variables= &thd->variables; + longlong nr; + THD *thd; DBUG_ENTER("handler::update_auto_increment"); - - /* - We must save the previous value to be able to restore it if the - row was not inserted - */ - thd->prev_insert_id= thd->next_insert_id; - - if ((nr= table->next_number_field->val_int()) != 0 || + if (table->next_number_field->val_int() != 0 || table->auto_increment_field_not_null && - thd->variables.sql_mode & MODE_NO_AUTO_VALUE_ON_ZERO) + current_thd->variables.sql_mode & MODE_NO_AUTO_VALUE_ON_ZERO) { - /* Clear flag for next row */ table->auto_increment_field_not_null= FALSE; - /* Mark that we didn't generate a new value **/ auto_increment_column_changed=0; - - /* Update next_insert_id if we have already generated a value */ - if (thd->clear_next_insert_id && nr >= thd->next_insert_id) - { - if (variables->auto_increment_increment != 1) - nr= next_insert_id(nr, variables); - else - nr++; - thd->next_insert_id= nr; - DBUG_PRINT("info",("next_insert_id: %lu", (ulong) nr)); - } DBUG_VOID_RETURN; } table->auto_increment_field_not_null= FALSE; - if (!(nr= thd->next_insert_id)) - { - nr= get_auto_increment(); - if (variables->auto_increment_increment != 1) - nr= next_insert_id(nr-1, variables); - /* - Update next row based on the found value. This way we don't have to - call the handler for every generated auto-increment value on a - multi-row statement - */ - thd->next_insert_id= nr; - } - - DBUG_PRINT("info",("auto_increment: %lu", (ulong) nr)); - - /* Mark that we should clear next_insert_id before next stmt */ - thd->clear_next_insert_id= 1; - - if (!table->next_number_field->store((longlong) nr)) + thd=current_thd; + if ((nr=thd->next_insert_id)) + thd->next_insert_id=0; // Clear after use + else + nr=get_auto_increment(); + if (!table->next_number_field->store(nr)) thd->insert_id((ulonglong) nr); else thd->insert_id(table->next_number_field->val_int()); - - /* - We can't set next_insert_id if the auto-increment key is not the - first key part, as there is no guarantee that the first parts will be in - sequence - */ - if (!table->next_number_key_offset) - { - /* - Set next insert id to point to next auto-increment value to be able to - handle multi-row statements - This works even if auto_increment_increment > 1 - */ - thd->next_insert_id= next_insert_id(nr, variables); - } - else - thd->next_insert_id= 0; - - /* Mark that we generated a new value */ auto_increment_column_changed=1; DBUG_VOID_RETURN; } -/* - restore_auto_increment - - In case of error on write, we restore the last used next_insert_id value - because the previous value was not used. -*/ -void handler::restore_auto_increment() +longlong handler::get_auto_increment() { - THD *thd= table->in_use; - if (thd->next_insert_id) - thd->next_insert_id= thd->prev_insert_id; -} - - -ulonglong handler::get_auto_increment() -{ - ulonglong nr; + longlong nr; int error; (void) extra(HA_EXTRA_KEYREAD); @@ -1111,8 +1018,7 @@ ulonglong handler::get_auto_increment() else { byte key[MAX_KEY_LENGTH]; - key_copy(key, table->record[0], - table->key_info + table->next_number_index, + key_copy(key,table,table->next_number_index, table->next_number_key_offset); error=index_read(table->record[1], key, table->next_number_key_offset, HA_READ_PREFIX_LAST); @@ -1121,8 +1027,8 @@ ulonglong handler::get_auto_increment() if (error) nr=1; else - nr=((ulonglong) table->next_number_field-> - val_int_offset(table->rec_buff_length)+1); + nr=(longlong) table->next_number_field-> + val_int_offset(table->rec_buff_length)+1; index_end(); (void) extra(HA_EXTRA_NO_KEYREAD); return nr; @@ -1365,7 +1271,7 @@ int ha_create_table(const char *name, HA_CREATE_INFO *create_info, char name_buff[FN_REFLEN]; DBUG_ENTER("ha_create_table"); - if (openfrm(current_thd, name,"",0,(uint) READ_ALL, 0, &table)) + if (openfrm(name,"",0,(uint) READ_ALL, 0, &table)) DBUG_RETURN(1); if (update_create_info) { @@ -1430,7 +1336,7 @@ int ha_create_table_from_engine(THD* thd, if ((error = writefrm(path, frmblob, frmlen))) goto err_end; - if (openfrm(thd, path,"",0,(uint) READ_ALL, 0, &table)) + if (openfrm(path,"",0,(uint) READ_ALL, 0, &table)) DBUG_RETURN(1); update_create_info_from_table(&create_info, &table); @@ -1755,3 +1661,65 @@ int handler::index_read_idx(byte * buf, uint index, const byte * key, error= ha_index_end(); return error; } + + +/* + Returns a list of all known extensions. + + SYNOPSIS + ha_known_exts() + + NOTES + No mutexes, worst case race is a minor surplus memory allocation + We have to recreate the extension map if mysqld is restarted (for example + within libmysqld) + + RETURN VALUE + pointer pointer to TYPELIB structure +*/ + +TYPELIB *ha_known_exts(void) +{ + if (!known_extensions.type_names || mysys_usage_id != known_extensions_id) + { + show_table_type_st *types; + List<char> found_exts; + List_iterator_fast<char> it(found_exts); + const char **ext, *old_ext; + + known_extensions_id= mysys_usage_id; + found_exts.push_back((char*) ".db"); + for (types= sys_table_types; types->type; types++) + { + if (*types->value == SHOW_OPTION_YES) + { + handler *file= get_new_handler(0,(enum db_type) types->db_type); + for (ext= file->bas_ext(); *ext; ext++) + { + while ((old_ext= it++)) + { + if (!strcmp(old_ext, *ext)) + break; + } + if (!old_ext) + found_exts.push_back((char *) *ext); + + it.rewind(); + } + delete file; + } + } + ext= (const char **) my_once_alloc(sizeof(char *)* + (found_exts.elements+1), + MYF(MY_WME | MY_FAE)); + + DBUG_ASSERT(ext); + known_extensions.count= found_exts.elements; + known_extensions.type_names= ext; + + while ((old_ext= it++)) + *ext++= old_ext; + *ext= 0; + } + return &known_extensions; +} diff --git a/sql/handler.h b/sql/handler.h index c408425ed60..858a7861dba 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -138,6 +138,8 @@ #define HA_CACHE_TBL_ASKTRANSACT 2 #define HA_CACHE_TBL_TRANSACT 4 +/* Options of START TRANSACTION statement (and later of SET TRANSACTION stmt) */ +#define MYSQL_START_TRANS_OPT_WITH_CONS_SNAPSHOT 1 enum db_type { @@ -590,5 +592,5 @@ int ha_discover(THD* thd, const char* dbname, const char* name, int ha_find_files(THD *thd,const char *db,const char *path, const char *wild, bool dir,List<char>* files); int ha_table_exists(THD* thd, const char* db, const char* name); - - +TYPELIB *ha_known_exts(void); +int ha_start_consistent_snapshot(THD *thd); diff --git a/sql/item.cc b/sql/item.cc index 59126603544..157b420805c 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -490,13 +490,13 @@ bool DTCollation::aggregate(DTCollation &dt, uint flags) } else if ((flags & MY_COLL_ALLOW_COERCIBLE_CONV) && derivation < dt.derivation && - dt.derivation == DERIVATION_COERCIBLE) + dt.derivation >= DERIVATION_COERCIBLE) { // Do nothing; } else if ((flags & MY_COLL_ALLOW_COERCIBLE_CONV) && dt.derivation < derivation && - derivation == DERIVATION_COERCIBLE) + derivation >= DERIVATION_COERCIBLE) { set(dt); strong= nagg; diff --git a/sql/item.h b/sql/item.h index 93c396b95b0..7b8fed1ecaa 100644 --- a/sql/item.h +++ b/sql/item.h @@ -32,6 +32,7 @@ class Item_field; enum Derivation { + DERIVATION_IGNORABLE= 4, DERIVATION_COERCIBLE= 3, DERIVATION_IMPLICIT= 2, DERIVATION_NONE= 1, @@ -99,6 +100,7 @@ public: { switch(derivation) { + case DERIVATION_IGNORABLE: return "IGNORABLE"; case DERIVATION_COERCIBLE: return "COERCIBLE"; case DERIVATION_IMPLICIT: return "IMPLICIT"; case DERIVATION_EXPLICIT: return "EXPLICIT"; @@ -577,6 +579,7 @@ public: max_length= 0; name= name_par ? name_par : (char*) "NULL"; fixed= 1; + collation.set(&my_charset_bin, DERIVATION_IGNORABLE); } enum Type type() const { return NULL_ITEM; } bool eq(const Item *item, bool binary_cmp) const; diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 566cacca487..394507af4f0 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -161,21 +161,24 @@ static bool extract_date_time(DATE_TIME_FORMAT *format, { int weekday= 0, yearday= 0, daypart= 0; int week_number= -1; - CHARSET_INFO *cs= &my_charset_bin; int error= 0; - bool usa_time= 0; - bool sunday_first_n_first_week_non_iso= -2; - bool strict_week_number; int strict_week_number_year= -1; - bool strict_week_number_year_type= -1; int frac_part; + bool usa_time= 0; + bool sunday_first_n_first_week_non_iso; + bool strict_week_number; + bool strict_week_number_year_type; const char *val_begin= val; const char *val_end= val + length; const char *ptr= format->format.str; const char *end= ptr + format->format.length; + CHARSET_INFO *cs= &my_charset_bin; DBUG_ENTER("extract_date_time"); LINT_INIT(strict_week_number); + /* Remove valgrind varnings when using gcc 3.3 and -O1 */ + PURIFY_OR_LINT_INIT(strict_week_number_year_type); + PURIFY_OR_LINT_INIT(sunday_first_n_first_week_non_iso); if (!sub_pattern_end) bzero((char*) l_time, sizeof(*l_time)); diff --git a/sql/lex.h b/sql/lex.h index 89daf46218c..325d052de90 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -65,7 +65,6 @@ static SYMBOL symbols[] = { { "AGAINST", SYM(AGAINST)}, { "AGGREGATE", SYM(AGGREGATE_SYM)}, { "ALL", SYM(ALL)}, - { "ALGORITHM", SYM(ALGORITHM_SYM)}, { "ALTER", SYM(ALTER)}, { "ANALYZE", SYM(ANALYZE_SYM)}, { "AND", SYM(AND_SYM)}, @@ -73,7 +72,6 @@ static SYMBOL symbols[] = { { "AS", SYM(AS)}, { "ASC", SYM(ASC)}, { "ASCII", SYM(ASCII_SYM)}, - { "ASENSITIVE", SYM(ASENSITIVE_SYM)}, { "AUTO_INCREMENT", SYM(AUTO_INC)}, { "AVG", SYM(AVG_SYM)}, { "AVG_ROW_LENGTH", SYM(AVG_ROW_LENGTH)}, @@ -95,9 +93,7 @@ static SYMBOL symbols[] = { { "BY", SYM(BY)}, { "BYTE", SYM(BYTE_SYM)}, { "CACHE", SYM(CACHE_SYM)}, - { "CALL", SYM(CALL_SYM)}, { "CASCADE", SYM(CASCADE)}, - { "CASCADED", SYM(CASCADED)}, { "CASE", SYM(CASE_SYM)}, { "CHANGE", SYM(CHANGE)}, { "CHANGED", SYM(CHANGED)}, @@ -118,11 +114,8 @@ static SYMBOL symbols[] = { { "COMMITTED", SYM(COMMITTED_SYM)}, { "COMPRESSED", SYM(COMPRESSED_SYM)}, { "CONCURRENT", SYM(CONCURRENT)}, - { "CONDITION", SYM(CONDITION_SYM)}, - { "CONNECTION", SYM(CONNECTION_SYM)}, + { "CONSISTENT", SYM(CONSISTENT_SYM)}, { "CONSTRAINT", SYM(CONSTRAINT)}, - { "CONTAINS", SYM(CONTAINS_SYM)}, - { "CONTINUE", SYM(CONTINUE_SYM)}, { "CONVERT", SYM(CONVERT_SYM)}, { "CREATE", SYM(CREATE)}, { "CROSS", SYM(CROSS)}, @@ -131,7 +124,6 @@ static SYMBOL symbols[] = { { "CURRENT_TIME", SYM(CURTIME)}, { "CURRENT_TIMESTAMP", SYM(NOW_SYM)}, { "CURRENT_USER", SYM(CURRENT_USER)}, - { "CURSOR", SYM(CURSOR_SYM)}, { "DATA", SYM(DATA_SYM)}, { "DATABASE", SYM(DATABASE)}, { "DATABASES", SYM(DATABASES)}, @@ -145,16 +137,13 @@ static SYMBOL symbols[] = { { "DEALLOCATE", SYM(DEALLOCATE_SYM)}, { "DEC", SYM(DECIMAL_SYM)}, { "DECIMAL", SYM(DECIMAL_SYM)}, - { "DECLARE", SYM(DECLARE_SYM)}, { "DEFAULT", SYM(DEFAULT)}, - { "DEFINER", SYM(DEFINER_SYM)}, { "DELAYED", SYM(DELAYED_SYM)}, { "DELAY_KEY_WRITE", SYM(DELAY_KEY_WRITE_SYM)}, { "DELETE", SYM(DELETE_SYM)}, { "DESC", SYM(DESC)}, { "DESCRIBE", SYM(DESCRIBE)}, { "DES_KEY_FILE", SYM(DES_KEY_FILE)}, - { "DETERMINISTIC", SYM(DETERMINISTIC_SYM)}, { "DIRECTORY", SYM(DIRECTORY_SYM)}, { "DISABLE", SYM(DISABLE_SYM)}, { "DISCARD", SYM(DISCARD)}, @@ -168,9 +157,7 @@ static SYMBOL symbols[] = { { "DUMPFILE", SYM(DUMPFILE)}, { "DUPLICATE", SYM(DUPLICATE_SYM)}, { "DYNAMIC", SYM(DYNAMIC_SYM)}, - { "EACH", SYM(EACH_SYM)}, { "ELSE", SYM(ELSE)}, - { "ELSEIF", SYM(ELSEIF_SYM)}, { "ENABLE", SYM(ENABLE_SYM)}, { "ENCLOSED", SYM(ENCLOSED)}, { "END", SYM(END)}, @@ -183,13 +170,11 @@ static SYMBOL symbols[] = { { "EVENTS", SYM(EVENTS_SYM)}, { "EXECUTE", SYM(EXECUTE_SYM)}, { "EXISTS", SYM(EXISTS)}, - { "EXIT", SYM(EXIT_SYM)}, { "EXPANSION", SYM(EXPANSION_SYM)}, { "EXPLAIN", SYM(DESCRIBE)}, { "EXTENDED", SYM(EXTENDED_SYM)}, { "FALSE", SYM(FALSE_SYM)}, { "FAST", SYM(FAST_SYM)}, - { "FETCH", SYM(FETCH_SYM)}, { "FIELDS", SYM(COLUMNS)}, { "FILE", SYM(FILE_SYM)}, { "FIRST", SYM(FIRST_SYM)}, @@ -201,17 +186,14 @@ static SYMBOL symbols[] = { { "FOR", SYM(FOR_SYM)}, { "FORCE", SYM(FORCE_SYM)}, { "FOREIGN", SYM(FOREIGN)}, - { "FOUND", SYM(FOUND_SYM)}, - { "FRAC_SECOND", SYM(FRAC_SECOND_SYM)}, { "FROM", SYM(FROM)}, { "FULL", SYM(FULL)}, { "FULLTEXT", SYM(FULLTEXT_SYM)}, - { "FUNCTION", SYM(FUNCTION_SYM)}, + { "FUNCTION", SYM(UDF_SYM)}, { "GEOMETRY", SYM(GEOMETRY_SYM)}, { "GEOMETRYCOLLECTION",SYM(GEOMETRYCOLLECTION)}, { "GET_FORMAT", SYM(GET_FORMAT)}, { "GLOBAL", SYM(GLOBAL_SYM)}, - { "GOTO", SYM(GOTO_SYM)}, { "GRANT", SYM(GRANT)}, { "GRANTS", SYM(GRANTS)}, { "GROUP", SYM(GROUP)}, @@ -236,8 +218,6 @@ static SYMBOL symbols[] = { { "INNER", SYM(INNER_SYM)}, { "INNOBASE", SYM(INNOBASE_SYM)}, { "INNODB", SYM(INNOBASE_SYM)}, - { "INOUT", SYM(INOUT_SYM)}, - { "INSENSITIVE", SYM(INSENSITIVE_SYM)}, { "INSERT", SYM(INSERT)}, { "INSERT_METHOD", SYM(INSERT_METHOD)}, { "INT", SYM(INT_SYM)}, @@ -253,17 +233,12 @@ static SYMBOL symbols[] = { { "IS", SYM(IS)}, { "ISOLATION", SYM(ISOLATION)}, { "ISSUER", SYM(ISSUER_SYM)}, - { "ITERATE", SYM(ITERATE_SYM)}, - { "INVOKER", SYM(INVOKER_SYM)}, { "JOIN", SYM(JOIN_SYM)}, { "KEY", SYM(KEY_SYM)}, { "KEYS", SYM(KEYS)}, { "KILL", SYM(KILL_SYM)}, - { "LABEL", SYM(LABEL_SYM)}, - { "LANGUAGE", SYM(LANGUAGE_SYM)}, { "LAST", SYM(LAST_SYM)}, { "LEADING", SYM(LEADING)}, - { "LEAVE", SYM(LEAVE_SYM)}, { "LEAVES", SYM(LEAVES)}, { "LEFT", SYM(LEFT)}, { "LEVEL", SYM(LEVEL_SYM)}, @@ -281,7 +256,6 @@ static SYMBOL symbols[] = { { "LONG", SYM(LONG_SYM)}, { "LONGBLOB", SYM(LONGBLOB)}, { "LONGTEXT", SYM(LONGTEXT)}, - { "LOOP", SYM(LOOP_SYM)}, { "LOW_PRIORITY", SYM(LOW_PRIORITY)}, { "MASTER", SYM(MASTER_SYM)}, { "MASTER_CONNECT_RETRY", SYM(MASTER_CONNECT_RETRY_SYM)}, @@ -307,7 +281,6 @@ static SYMBOL symbols[] = { { "MEDIUMBLOB", SYM(MEDIUMBLOB)}, { "MEDIUMINT", SYM(MEDIUMINT)}, { "MEDIUMTEXT", SYM(MEDIUMTEXT)}, - { "MERGE", SYM(MERGE_SYM)}, { "MICROSECOND", SYM(MICROSECOND_SYM)}, { "MIDDLEINT", SYM(MEDIUMINT)}, /* For powerbuilder */ { "MINUTE", SYM(MINUTE_SYM)}, @@ -316,13 +289,11 @@ static SYMBOL symbols[] = { { "MIN_ROWS", SYM(MIN_ROWS)}, { "MOD", SYM(MOD_SYM)}, { "MODE", SYM(MODE_SYM)}, - { "MODIFIES", SYM(MODIFIES_SYM)}, { "MODIFY", SYM(MODIFY_SYM)}, { "MONTH", SYM(MONTH_SYM)}, { "MULTILINESTRING", SYM(MULTILINESTRING)}, { "MULTIPOINT", SYM(MULTIPOINT)}, { "MULTIPOLYGON", SYM(MULTIPOLYGON)}, - { "NAME", SYM(NAME_SYM)}, { "NAMES", SYM(NAMES_SYM)}, { "NATIONAL", SYM(NATIONAL_SYM)}, { "NATURAL", SYM(NATURAL)}, @@ -348,7 +319,6 @@ static SYMBOL symbols[] = { { "OPTIONALLY", SYM(OPTIONALLY)}, { "OR", SYM(OR_SYM)}, { "ORDER", SYM(ORDER_SYM)}, - { "OUT", SYM(OUT_SYM)}, { "OUTER", SYM(OUTER)}, { "OUTFILE", SYM(OUTFILE)}, { "PACK_KEYS", SYM(PACK_KEYS_SYM)}, @@ -365,7 +335,6 @@ static SYMBOL symbols[] = { { "PROCESS" , SYM(PROCESS)}, { "PROCESSLIST", SYM(PROCESSLIST_SYM)}, { "PURGE", SYM(PURGE)}, - { "QUARTER", SYM(QUARTER_SYM)}, { "QUERY", SYM(QUERY_SYM)}, { "QUICK", SYM(QUICK)}, { "RAID0", SYM(RAID_0_SYM)}, @@ -373,7 +342,6 @@ static SYMBOL symbols[] = { { "RAID_CHUNKSIZE", SYM(RAID_CHUNKSIZE)}, { "RAID_TYPE", SYM(RAID_TYPE)}, { "READ", SYM(READ_SYM)}, - { "READS", SYM(READS_SYM)}, { "REAL", SYM(REAL)}, { "REFERENCES", SYM(REFERENCES)}, { "REGEXP", SYM(REGEXP)}, @@ -386,13 +354,11 @@ static SYMBOL symbols[] = { { "REPEATABLE", SYM(REPEATABLE_SYM)}, { "REPLACE", SYM(REPLACE)}, { "REPLICATION", SYM(REPLICATION)}, - { "REPEAT", SYM(REPEAT_SYM)}, { "REQUIRE", SYM(REQUIRE_SYM)}, { "RESET", SYM(RESET_SYM)}, { "RESTORE", SYM(RESTORE_SYM)}, { "RESTRICT", SYM(RESTRICT)}, - { "RETURN", SYM(RETURN_SYM)}, - { "RETURNS", SYM(RETURNS_SYM)}, + { "RETURNS", SYM(UDF_RETURNS_SYM)}, { "REVOKE", SYM(REVOKE)}, { "RIGHT", SYM(RIGHT)}, { "RLIKE", SYM(REGEXP)}, /* Like in mSQL2 */ @@ -403,13 +369,9 @@ static SYMBOL symbols[] = { { "ROW_FORMAT", SYM(ROW_FORMAT_SYM)}, { "RTREE", SYM(RTREE_SYM)}, { "SAVEPOINT", SYM(SAVEPOINT_SYM)}, - { "SCHEMA", SYM(DATABASE)}, - { "SCHEMAS", SYM(DATABASES)}, { "SECOND", SYM(SECOND_SYM)}, { "SECOND_MICROSECOND", SYM(SECOND_MICROSECOND_SYM)}, - { "SECURITY", SYM(SECURITY_SYM)}, { "SELECT", SYM(SELECT_SYM)}, - { "SENSITIVE", SYM(SENSITIVE_SYM)}, { "SEPARATOR", SYM(SEPARATOR_SYM)}, { "SERIAL", SYM(SERIAL_SYM)}, { "SERIALIZABLE", SYM(SERIALIZABLE_SYM)}, @@ -421,16 +383,12 @@ static SYMBOL symbols[] = { { "SIGNED", SYM(SIGNED_SYM)}, { "SIMPLE", SYM(SIMPLE_SYM)}, { "SLAVE", SYM(SLAVE)}, + { "SNAPSHOT", SYM(SNAPSHOT_SYM)}, { "SMALLINT", SYM(SMALLINT)}, { "SOME", SYM(ANY_SYM)}, { "SONAME", SYM(UDF_SONAME_SYM)}, { "SOUNDS", SYM(SOUNDS_SYM)}, { "SPATIAL", SYM(SPATIAL_SYM)}, - { "SPECIFIC", SYM(SPECIFIC_SYM)}, - { "SQL", SYM(SQL_SYM)}, - { "SQLEXCEPTION", SYM(SQLEXCEPTION_SYM)}, - { "SQLSTATE", SYM(SQLSTATE_SYM)}, - { "SQLWARNING", SYM(SQLWARNING_SYM)}, { "SQL_BIG_RESULT", SYM(SQL_BIG_RESULT)}, { "SQL_BUFFER_RESULT", SYM(SQL_BUFFER_RESULT)}, { "SQL_CACHE", SYM(SQL_CACHE_SYM)}, @@ -438,15 +396,6 @@ static SYMBOL symbols[] = { { "SQL_NO_CACHE", SYM(SQL_NO_CACHE_SYM)}, { "SQL_SMALL_RESULT", SYM(SQL_SMALL_RESULT)}, { "SQL_THREAD", SYM(SQL_THREAD)}, - { "SQL_TSI_FRAC_SECOND", SYM(FRAC_SECOND_SYM)}, - { "SQL_TSI_SECOND", SYM(SECOND_SYM)}, - { "SQL_TSI_MINUTE", SYM(MINUTE_SYM)}, - { "SQL_TSI_HOUR", SYM(HOUR_SYM)}, - { "SQL_TSI_DAY", SYM(DAY_SYM)}, - { "SQL_TSI_WEEK", SYM(WEEK_SYM)}, - { "SQL_TSI_MONTH", SYM(MONTH_SYM)}, - { "SQL_TSI_QUARTER", SYM(QUARTER_SYM)}, - { "SQL_TSI_YEAR", SYM(YEAR_SYM)}, { "SSL", SYM(SSL_SYM)}, { "START", SYM(START_SYM)}, { "STARTING", SYM(STARTING)}, @@ -462,28 +411,22 @@ static SYMBOL symbols[] = { { "TABLES", SYM(TABLES)}, { "TABLESPACE", SYM(TABLESPACE)}, { "TEMPORARY", SYM(TEMPORARY)}, - { "TEMPTABLE", SYM(TEMPTABLE_SYM)}, { "TERMINATED", SYM(TERMINATED)}, { "TEXT", SYM(TEXT_SYM)}, { "THEN", SYM(THEN_SYM)}, { "TIME", SYM(TIME_SYM)}, { "TIMESTAMP", SYM(TIMESTAMP)}, - { "TIMESTAMPADD", SYM(TIMESTAMP_ADD)}, - { "TIMESTAMPDIFF", SYM(TIMESTAMP_DIFF)}, { "TINYBLOB", SYM(TINYBLOB)}, { "TINYINT", SYM(TINYINT)}, { "TINYTEXT", SYM(TINYTEXT)}, { "TO", SYM(TO_SYM)}, { "TRAILING", SYM(TRAILING)}, { "TRANSACTION", SYM(TRANSACTION_SYM)}, - { "TRIGGER", SYM(TRIGGER_SYM)}, { "TRUE", SYM(TRUE_SYM)}, { "TRUNCATE", SYM(TRUNCATE_SYM)}, { "TYPE", SYM(TYPE_SYM)}, { "TYPES", SYM(TYPES_SYM)}, { "UNCOMMITTED", SYM(UNCOMMITTED_SYM)}, - { "UNDEFINED", SYM(UNDEFINED_SYM)}, - { "UNDO", SYM(UNDO_SYM)}, { "UNICODE", SYM(UNICODE_SYM)}, { "UNION", SYM(UNION_SYM)}, { "UNIQUE", SYM(UNIQUE_SYM)}, @@ -508,11 +451,8 @@ static SYMBOL symbols[] = { { "VARIABLES", SYM(VARIABLES)}, { "VARYING", SYM(VARYING)}, { "WARNINGS", SYM(WARNINGS)}, - { "WEEK", SYM(WEEK_SYM)}, { "WHEN", SYM(WHEN_SYM)}, { "WHERE", SYM(WHERE)}, - { "WHILE", SYM(WHILE_SYM)}, - { "VIEW", SYM(VIEW_SYM)}, { "WITH", SYM(WITH)}, { "WORK", SYM(WORK_SYM)}, { "WRITE", SYM(WRITE_SYM)}, @@ -559,6 +499,7 @@ static SYMBOL sql_functions[] = { { "CONCAT", SYM(CONCAT)}, { "CONCAT_WS", SYM(CONCAT_WS)}, { "CONNECTION_ID", F_SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_connection_id)}, + { "CONTAINS", F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_contains)}, { "CONV", F_SYM(FUNC_ARG3),0,CREATE_FUNC(create_func_conv)}, { "CONVERT_TZ", SYM(CONVERT_TZ_SYM)}, { "COUNT", SYM(COUNT_SYM)}, @@ -695,13 +636,14 @@ static SYMBOL sql_functions[] = { { "POSITION", SYM(POSITION_SYM)}, { "POW", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_pow)}, { "POWER", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_pow)}, + { "QUARTER", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_quarter)}, { "QUOTE", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_quote)}, { "RADIANS", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_radians)}, { "RAND", SYM(RAND)}, { "RELEASE_LOCK", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_release_lock)}, + { "REPEAT", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_repeat)}, { "REVERSE", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_reverse)}, { "ROUND", SYM(ROUND)}, - { "ROW_COUNT", SYM(ROW_COUNT_SYM)}, { "RPAD", F_SYM(FUNC_ARG3),0,CREATE_FUNC(create_func_rpad)}, { "RTRIM", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_rtrim)}, { "SEC_TO_TIME", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sec_to_time)}, @@ -744,6 +686,7 @@ static SYMBOL sql_functions[] = { { "UUID", F_SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_uuid)}, { "VARIANCE", SYM(VARIANCE_SYM)}, { "VERSION", F_SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_version)}, + { "WEEK", SYM(WEEK_SYM)}, { "WEEKDAY", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_weekday)}, { "WEEKOFYEAR", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_weekofyear)}, { "WITHIN", F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_within)}, diff --git a/sql/log.cc b/sql/log.cc index ef538c3b03f..bcd99326501 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -35,7 +35,7 @@ #include "message.h" #endif -MYSQL_LOG mysql_log, mysql_slow_log, mysql_bin_log; +MYSQL_LOG mysql_log,mysql_update_log,mysql_slow_log,mysql_bin_log; ulong sync_binlog_counter= 0; static bool test_if_number(const char *str, @@ -129,8 +129,7 @@ static int find_uniq_filename(char *name) MYSQL_LOG::MYSQL_LOG() :bytes_written(0), last_time(0), query_start(0), name(0), file_id(1), open_count(1), log_type(LOG_CLOSED), write_error(0), inited(0), - need_start_event(1), description_event_for_exec(0), - description_event_for_queue(0) + need_start_event(1) { /* We don't want to initialize LOCK_Log here as such initialization depends on @@ -158,8 +157,6 @@ void MYSQL_LOG::cleanup() { inited= 0; close(LOG_CLOSE_INDEX); - delete description_event_for_queue; - delete description_event_for_exec; (void) pthread_mutex_destroy(&LOCK_log); (void) pthread_mutex_destroy(&LOCK_index); (void) pthread_cond_destroy(&update_cond); @@ -229,8 +226,7 @@ bool MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg, const char *new_name, const char *index_file_name_arg, enum cache_type io_cache_type_arg, bool no_auto_events_arg, - ulong max_size_arg, - bool null_created_arg) + ulong max_size_arg) { char buff[512]; File file= -1, index_file_nr= -1; @@ -328,8 +324,8 @@ bool MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg, if (my_b_safe_write(&log_file, (byte*) BINLOG_MAGIC, BIN_LOG_HEADER_SIZE)) goto err; - bytes_written+= BIN_LOG_HEADER_SIZE; - write_file_name_to_index_file= 1; + bytes_written += BIN_LOG_HEADER_SIZE; + write_file_name_to_index_file=1; } if (!my_b_inited(&index_file)) @@ -359,50 +355,10 @@ bool MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg, } if (need_start_event && !no_auto_events) { - /* - In 4.x we set need_start_event=0 here, but in 5.0 we want a Start event - even if this is not the very first binlog. - */ - Format_description_log_event s(BINLOG_VERSION); - if (!s.is_valid()) - goto err; - if (null_created_arg) - s.created= 0; - if (s.write(&log_file)) - goto err; - bytes_written+= s.data_written; - } - if (description_event_for_queue && - description_event_for_queue->binlog_version>=4) - { - /* - This is a relay log written to by the I/O slave thread. - Write the event so that others can later know the format of this relay - log. - Note that this event is very close to the original event from the - master (it has binlog version of the master, event types of the - master), so this is suitable to parse the next relay log's event. It - has been produced by - Format_description_log_event::Format_description_log_event(char* - buf,). - Why don't we want to write the description_event_for_queue if this - event is for format<4 (3.23 or 4.x): this is because in that case, the - description_event_for_queue describes the data received from the - master, but not the data written to the relay log (*conversion*), - which is in format 4 (slave's). - */ - /* - Set 'created' to 0, so that in next relay logs this event does not - trigger cleaning actions on the slave in - Format_description_log_event::exec_event(). - */ - description_event_for_queue->created= 0; - /* Don't set log_pos in event header */ - description_event_for_queue->artificial_event=1; - - if (description_event_for_queue->write(&log_file)) - goto err; - bytes_written+= description_event_for_queue->data_written; + need_start_event=0; + Start_log_event s; + s.set_log_pos(this); + s.write(&log_file); } if (flush_io_cache(&log_file) || my_sync(log_file.file, MYF(MY_WME))) @@ -698,7 +654,7 @@ bool MYSQL_LOG::reset_logs(THD* thd) if (!thd->slave_thread) need_start_event=1; open(save_name, save_log_type, 0, index_file_name, - io_cache_type, no_auto_events, max_size, 0); + io_cache_type, no_auto_events, max_size); my_free((gptr) save_name, MYF(0)); err: @@ -880,18 +836,22 @@ int MYSQL_LOG::purge_logs(const char *to_log, while ((strcmp(to_log,log_info.log_file_name) || (exit_loop=included)) && !log_in_use(log_info.log_file_name)) { - ulong file_size= 0; + ulong tmp; + LINT_INIT(tmp); if (decrease_log_space) //stat the file we want to delete { MY_STAT s; - - /* - If we could not stat, we can't know the amount - of space that deletion will free. In most cases, - deletion won't work either, so it's not a problem. - */ if (my_stat(log_info.log_file_name,&s,MYF(0))) - file_size= s.st_size; + tmp= s.st_size; + else + { + /* + If we could not stat, we can't know the amount + of space that deletion will free. In most cases, + deletion won't work either, so it's not a problem. + */ + tmp= 0; + } } /* It's not fatal if we can't delete a log file ; @@ -899,7 +859,7 @@ int MYSQL_LOG::purge_logs(const char *to_log, */ DBUG_PRINT("info",("purging %s",log_info.log_file_name)); if (!my_delete(log_info.log_file_name, MYF(0)) && decrease_log_space) - *decrease_log_space-= file_size; + *decrease_log_space-= tmp; if (find_next_log(&log_info, 0) || exit_loop) break; } @@ -1064,8 +1024,9 @@ void MYSQL_LOG::new_file(bool need_lock) */ THD *thd = current_thd; /* may be 0 if we are reacting to SIGHUP */ Rotate_log_event r(thd,new_name+dirname_length(new_name)); + r.set_log_pos(this); r.write(&log_file); - bytes_written += r.data_written; + bytes_written += r.get_event_len(); } /* Update needs to be signalled even if there is no rotate event @@ -1083,17 +1044,8 @@ void MYSQL_LOG::new_file(bool need_lock) Note that at this point, log_type != LOG_CLOSED (important for is_open()). */ - /* - new_file() is only used for rotation (in FLUSH LOGS or because size > - max_binlog_size or max_relay_log_size). - If this is a binary log, the Format_description_log_event at the beginning of - the new file should have created=0 (to distinguish with the - Format_description_log_event written at server startup, which should - trigger temp tables deletion on slaves. - */ - open(old_name, save_log_type, new_name_ptr, index_file_name, io_cache_type, - no_auto_events, max_size, 1); + no_auto_events, max_size); if (this == &mysql_bin_log) report_pos_in_innodb(); my_free(old_name,MYF(0)); @@ -1124,7 +1076,7 @@ bool MYSQL_LOG::append(Log_event* ev) error=1; goto err; } - bytes_written+= ev->data_written; + bytes_written += ev->get_event_len(); DBUG_PRINT("info",("max_size: %lu",max_size)); if ((uint) my_b_append_tell(&log_file) > max_size) { @@ -1177,7 +1129,7 @@ err: /* Write to normal (not rotable) log - This is the format for the 'normal' log. + This is the format for the 'normal', 'slow' and 'update' logs. */ bool MYSQL_LOG::write(THD *thd,enum enum_server_command command, @@ -1268,15 +1220,11 @@ bool MYSQL_LOG::write(THD *thd,enum enum_server_command command, inline bool sync_binlog(IO_CACHE *cache) { - if (sync_binlog_period == ++sync_binlog_counter && sync_binlog_period) - { - sync_binlog_counter= 0; - return my_sync(cache->file, MYF(MY_WME)); - } - return 0; + return (sync_binlog_period && + (sync_binlog_period == ++sync_binlog_counter) && + (sync_binlog_counter= 0, my_sync(cache->file, MYF(MY_WME)))); } - /* Write an event to the binary log */ @@ -1344,7 +1292,7 @@ bool MYSQL_LOG::write(Log_event* event_info) if (thd) { - /* NOTE: CHARSET AND TZ REPL WILL BE REWRITTEN SHORTLY */ +#if MYSQL_VERSION_ID < 50000 /* To make replication of charsets working in 4.1 we are writing values of charset related variables before every statement in the binlog, @@ -1370,6 +1318,7 @@ COLLATION_CONNECTION=%u,COLLATION_DATABASE=%u,COLLATION_SERVER=%u", (uint) thd->variables.collation_database->number, (uint) thd->variables.collation_server->number); Query_log_event e(thd, buf, written, 0); + e.set_log_pos(this); if (e.write(file)) goto err; } @@ -1385,26 +1334,31 @@ COLLATION_CONNECTION=%u,COLLATION_DATABASE=%u,COLLATION_SERVER=%u", thd->variables.time_zone->get_name()->ptr(), "'", NullS); Query_log_event e(thd, buf, buf_end - buf, 0); + e.set_log_pos(this); if (e.write(file)) goto err; } +#endif if (thd->last_insert_id_used) { Intvar_log_event e(thd,(uchar) LAST_INSERT_ID_EVENT, thd->current_insert_id); + e.set_log_pos(this); if (e.write(file)) goto err; } if (thd->insert_id_used) { Intvar_log_event e(thd,(uchar) INSERT_ID_EVENT,thd->last_insert_id); + e.set_log_pos(this); if (e.write(file)) goto err; } if (thd->rand_used) { Rand_log_event e(thd,thd->rand_saved_seed1,thd->rand_saved_seed2); + e.set_log_pos(this); if (e.write(file)) goto err; } @@ -1420,6 +1374,7 @@ COLLATION_CONNECTION=%u,COLLATION_DATABASE=%u,COLLATION_SERVER=%u", user_var_event->length, user_var_event->type, user_var_event->charset_number); + e.set_log_pos(this); if (e.write(file)) goto err; } @@ -1431,17 +1386,48 @@ COLLATION_CONNECTION=%u,COLLATION_DATABASE=%u,COLLATION_SERVER=%u", p= strmov(strmov(buf, "SET CHARACTER SET "), thd->variables.convert_set->name); Query_log_event e(thd, buf, (ulong) (p - buf), 0); + e.set_log_pos(this); if (e.write(file)) goto err; } #endif + + /* + If the user has set FOREIGN_KEY_CHECKS=0 we wrap every SQL + command in the binlog inside: + SET FOREIGN_KEY_CHECKS=0; + <command>; + SET FOREIGN_KEY_CHECKS=1; + */ + + if (thd->options & OPTION_NO_FOREIGN_KEY_CHECKS) + { + Query_log_event e(thd, "SET FOREIGN_KEY_CHECKS=0", 24, 0); + e.set_log_pos(this); + if (e.write(file)) + goto err; + } } /* Write the SQL command */ + event_info->set_log_pos(this); if (event_info->write(file)) goto err; + /* Write log events to reset the 'run environment' of the SQL command */ + + if (thd) + { + if (thd->options & OPTION_NO_FOREIGN_KEY_CHECKS) + { + Query_log_event e(thd, "SET FOREIGN_KEY_CHECKS=1", 24, 0); + e.set_log_pos(this); + if (e.write(file)) + goto err; + } + } + /* Tell for transactional table handlers up to which position in the binlog file we wrote. The table handler can store this info, and @@ -1618,6 +1604,7 @@ bool MYSQL_LOG::write(THD *thd, IO_CACHE *cache, bool commit_or_rollback) master's binlog, which would result in wrong positions being shown to the user, MASTER_POS_WAIT undue waiting etc. */ + qinfo.set_log_pos(this); if (qinfo.write(&log_file)) goto err; } @@ -1643,6 +1630,7 @@ bool MYSQL_LOG::write(THD *thd, IO_CACHE *cache, bool commit_or_rollback) commit_or_rollback ? "COMMIT" : "ROLLBACK", commit_or_rollback ? 6 : 8, TRUE); + qinfo.set_log_pos(this); if (qinfo.write(&log_file) || flush_io_cache(&log_file) || sync_binlog(&log_file)) goto err; @@ -1704,7 +1692,8 @@ err: /* - Write to the slow query log. + Write update log in a format suitable for incremental backup + This is also used by the slow query log. */ bool MYSQL_LOG::write(THD *thd,const char *query, uint query_length, @@ -1714,12 +1703,19 @@ bool MYSQL_LOG::write(THD *thd,const char *query, uint query_length, time_t current_time; if (!is_open()) return 0; + DBUG_ENTER("MYSQL_LOG::write"); + VOID(pthread_mutex_lock(&LOCK_log)); if (is_open()) { // Safety agains reopen int tmp_errno=0; char buff[80],*end; end=buff; + if (!(thd->options & OPTION_UPDATE_LOG)) + { + VOID(pthread_mutex_unlock(&LOCK_log)); + DBUG_RETURN(0); + } if (!(specialflag & SPECIAL_SHORT_LOG_FORMAT) || query_start_arg) { current_time=time(NULL); @@ -1818,7 +1814,7 @@ bool MYSQL_LOG::write(THD *thd,const char *query, uint query_length, } } VOID(pthread_mutex_unlock(&LOCK_log)); - return error; + DBUG_RETURN(error); } @@ -1838,16 +1834,19 @@ bool MYSQL_LOG::write(THD *thd,const char *query, uint query_length, THD::enter_cond() (see NOTES in sql_class.h). */ -void MYSQL_LOG:: wait_for_update(THD* thd, bool master_or_slave) +void MYSQL_LOG::wait_for_update(THD* thd, bool master_or_slave) { - const char* old_msg = thd->enter_cond(&update_cond, &LOCK_log, - master_or_slave ? - "Has read all relay log; waiting for \ -the slave I/O thread to update it" : - "Has sent all binlog to slave; \ -waiting for binlog to be updated"); + const char *old_msg; + DBUG_ENTER("wait_for_update"); + old_msg= thd->enter_cond(&update_cond, &LOCK_log, + master_or_slave ? + "Has read all relay log; waiting for the slave I/O " + "thread to update it" : + "Has sent all binlog to slave; waiting for binlog " + "to be updated"); pthread_cond_wait(&update_cond, &LOCK_log); thd->exit_cond(old_msg); + DBUG_VOID_RETURN; } @@ -1878,8 +1877,8 @@ void MYSQL_LOG::close(uint exiting) (exiting & LOG_CLOSE_STOP_EVENT)) { Stop_log_event s; + s.set_log_pos(this); s.write(&log_file); - bytes_written+= s.data_written; signal_update(); } #endif /* HAVE_REPLICATION */ @@ -2204,6 +2203,15 @@ void MYSQL_LOG::report_pos_in_innodb() DBUG_VOID_RETURN; } + +void MYSQL_LOG::signal_update() +{ + DBUG_ENTER("MYSQL_LOG::signal_update"); + pthread_cond_broadcast(&update_cond); + DBUG_VOID_RETURN; +} + + #ifdef __NT__ void print_buffer_to_nt_eventlog(enum loglevel level, char *buff, uint length, int buffLen) diff --git a/sql/log_event.cc b/sql/log_event.cc index c7f6f25e74a..091566c5d90 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -180,12 +180,10 @@ static void cleanup_load_tmpdir() write_str() */ -static bool write_str(IO_CACHE *file, char *str, uint length) +static bool write_str(IO_CACHE *file, char *str, byte length) { - byte tmp[1]; - tmp[0]= (byte) length; - return (my_b_safe_write(file, tmp, sizeof(tmp)) || - my_b_safe_write(file, (byte*) str, length)); + return (my_b_safe_write(file, &length, 1) || + my_b_safe_write(file, (byte*) str, (int) length)); } @@ -193,18 +191,17 @@ static bool write_str(IO_CACHE *file, char *str, uint length) read_str() */ -static inline int read_str(char **buf, char *buf_end, char **str, - uint8 *len) +static inline int read_str(char * &buf, char *buf_end, char * &str, + uint8 &len) { - if (*buf + ((uint) (uchar) **buf) >= buf_end) + if (buf + (uint) (uchar) *buf >= buf_end) return 1; - *len= (uint8) **buf; - *str= (*buf)+1; - (*buf)+= (uint) *len+1; + len = (uint8) *buf; + str= buf+1; + buf+= (uint) len+1; return 0; } - /* Transforms a string into "" or its expression in 0x... form. */ @@ -228,25 +225,9 @@ static char *str_to_hex(char *to, char *from, uint len) return p; // pointer to end 0 of 'to' } -/* - Prints a "session_var=value" string. Used by mysqlbinlog to print some SET - commands just before it prints a query. -*/ - -static void print_set_option(FILE* file, uint32 bits_changed, uint32 option, - uint32 flags, const char* name, bool* need_comma) -{ - if (bits_changed & option) - { - if (*need_comma) - fprintf(file,", "); - fprintf(file,"%s=%d", name, (bool)(flags & option)); - *need_comma= 1; - } -} /************************************************************************** - Log_event methods (= the parent class of all events) + Log_event methods **************************************************************************/ /* @@ -256,7 +237,7 @@ static void print_set_option(FILE* file, uint32 bits_changed, uint32 option, const char* Log_event::get_type_str() { switch(get_type_code()) { - case START_EVENT_V3: return "Start_v3"; + case START_EVENT: return "Start"; case STOP_EVENT: return "Stop"; case QUERY_EVENT: return "Query"; case ROTATE_EVENT: return "Rotate"; @@ -270,7 +251,6 @@ const char* Log_event::get_type_str() case EXEC_LOAD_EVENT: return "Exec_load"; case RAND_EVENT: return "RAND"; case USER_VAR_EVENT: return "User var"; - case FORMAT_DESCRIPTION_EVENT: return "Format_desc"; default: return "Unknown"; /* impossible */ } } @@ -282,7 +262,8 @@ const char* Log_event::get_type_str() #ifndef MYSQL_CLIENT Log_event::Log_event(THD* thd_arg, uint16 flags_arg, bool using_trans) - :log_pos(0), temp_buf(0), exec_time(0), flags(flags_arg), thd(thd_arg) + :log_pos(0), temp_buf(0), exec_time(0), cached_event_len(0), + flags(flags_arg), thd(thd_arg) { server_id= thd->server_id; when= thd->start_time; @@ -299,7 +280,7 @@ Log_event::Log_event(THD* thd_arg, uint16 flags_arg, bool using_trans) */ Log_event::Log_event() - :temp_buf(0), exec_time(0), flags(0), cache_stmt(0), + :temp_buf(0), exec_time(0), cached_event_len(0), flags(0), cache_stmt(0), thd(0) { server_id= ::server_id; @@ -313,70 +294,24 @@ Log_event::Log_event() Log_event::Log_event() */ -Log_event::Log_event(const char* buf, - const Format_description_log_event* description_event) - :temp_buf(0), cache_stmt(0) +Log_event::Log_event(const char* buf, bool old_format) + :temp_buf(0), cached_event_len(0), cache_stmt(0) { -#ifndef MYSQL_CLIENT - thd = 0; -#endif when = uint4korr(buf); server_id = uint4korr(buf + SERVER_ID_OFFSET); - if (description_event->binlog_version==1) + if (old_format) { - log_pos= 0; - flags= 0; - return; + log_pos=0; + flags=0; } - /* 4.0 or newer */ - log_pos= uint4korr(buf + LOG_POS_OFFSET); - /* - If the log is 4.0 (so here it can only be a 4.0 relay log read by the SQL - thread or a 4.0 master binlog read by the I/O thread), log_pos is the - beginning of the event: we transform it into the end of the event, which is - more useful. - But how do you know that the log is 4.0: you know it if description_event - is version 3 *and* you are not reading a Format_desc (remember that - mysqlbinlog starts by assuming that 5.0 logs are in 4.0 format, until it - finds a Format_desc). - */ - if (description_event->binlog_version==3 && - buf[EVENT_TYPE_OFFSET]<FORMAT_DESCRIPTION_EVENT && log_pos) - { - /* - If log_pos=0, don't change it. log_pos==0 is a marker to mean - "don't change rli->group_master_log_pos" (see - inc_group_relay_log_pos()). As it is unreal log_pos, adding the event - len's is nonsense. For example, a fake Rotate event should - not have its log_pos (which is 0) changed or it will modify - Exec_master_log_pos in SHOW SLAVE STATUS, displaying a nonsense value - of (a non-zero offset which does not exist in the master's binlog, so - which will cause problems if the user uses this value in - CHANGE MASTER). - */ - log_pos+= uint4korr(buf + EVENT_LEN_OFFSET); - } - DBUG_PRINT("info", ("log_pos: %lu", (ulong) log_pos)); - - flags= uint2korr(buf + FLAGS_OFFSET); - if ((buf[EVENT_TYPE_OFFSET] == FORMAT_DESCRIPTION_EVENT) || - (buf[EVENT_TYPE_OFFSET] == ROTATE_EVENT)) + else { - /* - These events always have a header which stops here (i.e. their header is - FROZEN). - */ - /* - Initialization to zero of all other Log_event members as they're not - specified. Currently there are no such members; in the future there will - be an event UID (but Format_description and Rotate don't need this UID, - as they are not propagated through --log-slave-updates (remember the UID - is used to not play a query twice when you have two masters which are - slaves of a 3rd master). Then we are done. - */ - return; + log_pos = uint4korr(buf + LOG_POS_OFFSET); + flags = uint2korr(buf + FLAGS_OFFSET); } - /* otherwise, go on with reading the header from buf (nothing now) */ +#ifndef MYSQL_CLIENT + thd = 0; +#endif } #ifndef MYSQL_CLIENT @@ -429,10 +364,10 @@ int Log_event::exec_event(struct st_relay_log_info* rli) has already been updated. */ if ((thd->options & OPTION_BEGIN) && opt_using_transactions) - rli->inc_event_relay_log_pos(); + rli->inc_event_relay_log_pos(get_event_len()); else { - rli->inc_group_relay_log_pos(log_pos); + rli->inc_group_relay_log_pos(get_event_len(),log_pos); flush_relay_log_info(rli); /* Note that Rotate_log_event::exec_event() does not call this function, @@ -494,95 +429,49 @@ void Log_event::init_show_field_list(List<Item>* field_list) field_list->push_back(new Item_empty_string("Event_type", 20)); field_list->push_back(new Item_return_int("Server_id", 10, MYSQL_TYPE_LONG)); - field_list->push_back(new Item_return_int("End_log_pos", 11, + field_list->push_back(new Item_return_int("Orig_log_pos", 11, MYSQL_TYPE_LONGLONG)); field_list->push_back(new Item_empty_string("Info", 20)); } #endif /* !MYSQL_CLIENT */ - /* Log_event::write() */ -bool Log_event::write_header(IO_CACHE* file, ulong event_data_length) +int Log_event::write(IO_CACHE* file) { - byte header[LOG_EVENT_HEADER_LEN]; - DBUG_ENTER("Log_event::write_header"); - - /* Store number of bytes that will be written by this event */ - data_written= event_data_length + sizeof(header); - - /* - log_pos != 0 if this is relay-log event. In this case we should not - change the position - */ - - if (is_artificial_event()) - { - /* - We should not do any cleanup on slave when reading this. We - mark this by setting log_pos to 0. Start_log_event_v3() will - detect this on reading and set artificial_event=1 for the event. - */ - log_pos= 0; - } - else if (!log_pos) - { - /* - Calculate position of end of event - - Note that with a SEQ_READ_APPEND cache, my_b_tell() does not - work well. So this will give slightly wrong positions for the - Format_desc/Rotate/Stop events which the slave writes to its - relay log. For example, the initial Format_desc will have - end_log_pos=91 instead of 95. Because after writing the first 4 - bytes of the relay log, my_b_tell() still reports 0. Because - my_b_append() does not update the counter which my_b_tell() - later uses (one should probably use my_b_append_tell() to work - around this). To get right positions even when writing to the - relay log, we use the (new) my_b_safe_tell(). - - Note that this raises a question on the correctness of all these - DBUG_ASSERT(my_b_tell()=rli->event_relay_log_pos). - - If in a transaction, the log_pos which we calculate below is not - very good (because then my_b_safe_tell() returns start position - of the BEGIN, so it's like the statement was at the BEGIN's - place), but it's not a very serious problem (as the slave, when - it is in a transaction, does not take those end_log_pos into - account (as it calls inc_event_relay_log_pos()). To be fixed - later, so that it looks less strange. But not bug. - */ - - log_pos= my_b_safe_tell(file)+data_written; - } + return (write_header(file) || write_data(file)) ? -1 : 0; +} - /* - Header will be of size LOG_EVENT_HEADER_LEN for all events, except for - FORMAT_DESCRIPTION_EVENT and ROTATE_EVENT, where it will be - LOG_EVENT_MINIMAL_HEADER_LEN (remember these 2 have a frozen header, - because we read them before knowing the format). - */ - int4store(header, (ulong) when); // timestamp - header[EVENT_TYPE_OFFSET]= get_type_code(); - int4store(header+ SERVER_ID_OFFSET, server_id); - int4store(header+ EVENT_LEN_OFFSET, data_written); - int4store(header+ LOG_POS_OFFSET, log_pos); - int2store(header+ FLAGS_OFFSET, flags); +/* + Log_event::write_header() +*/ - DBUG_RETURN(my_b_safe_write(file, header, sizeof(header)) != 0); +int Log_event::write_header(IO_CACHE* file) +{ + char buf[LOG_EVENT_HEADER_LEN]; + char* pos = buf; + int4store(pos, (ulong) when); // timestamp + pos += 4; + *pos++ = get_type_code(); // event type code + int4store(pos, server_id); + pos += 4; + long tmp=get_data_size() + LOG_EVENT_HEADER_LEN; + int4store(pos, tmp); + pos += 4; + int4store(pos, log_pos); + pos += 4; + int2store(pos, flags); + pos += 2; + return (my_b_safe_write(file, (byte*) buf, (uint) (pos - buf))); } /* Log_event::read_log_event() - - This needn't be format-tolerant, because we only read - LOG_EVENT_MINIMAL_HEADER_LEN (we just want to read the event's length). - */ #ifndef MYSQL_CLIENT @@ -591,7 +480,7 @@ int Log_event::read_log_event(IO_CACHE* file, String* packet, { ulong data_len; int result=0; - char buf[LOG_EVENT_MINIMAL_HEADER_LEN]; + char buf[LOG_EVENT_HEADER_LEN]; DBUG_ENTER("read_log_event"); if (log_lock) @@ -611,25 +500,24 @@ int Log_event::read_log_event(IO_CACHE* file, String* packet, goto end; } data_len= uint4korr(buf + EVENT_LEN_OFFSET); - if (data_len < LOG_EVENT_MINIMAL_HEADER_LEN || + if (data_len < LOG_EVENT_HEADER_LEN || data_len > current_thd->variables.max_allowed_packet) { DBUG_PRINT("error",("data_len: %ld", data_len)); - result= ((data_len < LOG_EVENT_MINIMAL_HEADER_LEN) ? LOG_READ_BOGUS : + result= ((data_len < LOG_EVENT_HEADER_LEN) ? LOG_READ_BOGUS : LOG_READ_TOO_LARGE); goto end; } packet->append(buf, sizeof(buf)); - data_len-= LOG_EVENT_MINIMAL_HEADER_LEN; + data_len-= LOG_EVENT_HEADER_LEN; if (data_len) { if (packet->append(file, data_len)) { /* - Here if we hit EOF it's really an error: as data_len is >=0 - there's supposed to be more bytes available. + Here we should never hit EOF in a non-error condition. EOF means we are reading the event partially, which should - never happen: either we read badly or the binlog is truncated. + never happen. */ result= file->error >= 0 ? LOG_READ_TRUNC: LOG_READ_IO; /* Implicit goto end; */ @@ -657,42 +545,24 @@ end: Log_event::read_log_event() NOTE: - Allocates memory; The caller is responsible for clean-up. + Allocates memory; The caller is responsible for clean-up */ #ifndef MYSQL_CLIENT Log_event* Log_event::read_log_event(IO_CACHE* file, pthread_mutex_t* log_lock, - const Format_description_log_event *description_event) + bool old_format) #else -Log_event* Log_event::read_log_event(IO_CACHE* file, - const Format_description_log_event *description_event) +Log_event* Log_event::read_log_event(IO_CACHE* file, bool old_format) #endif { - DBUG_ASSERT(description_event); - char head[LOG_EVENT_MINIMAL_HEADER_LEN]; - /* - First we only want to read at most LOG_EVENT_MINIMAL_HEADER_LEN, just to - check the event for sanity and to know its length; no need to really parse - it. We say "at most" because this could be a 3.23 master, which has header - of 13 bytes, whereas LOG_EVENT_MINIMAL_HEADER_LEN is 19 bytes (it's "minimal" - over the set {MySQL >=4.0}). - */ - uint header_size= min(description_event->common_header_len, - LOG_EVENT_MINIMAL_HEADER_LEN); + char head[LOG_EVENT_HEADER_LEN]; + uint header_size= old_format ? OLD_HEADER_LEN : LOG_EVENT_HEADER_LEN; LOCK_MUTEX; - DBUG_PRINT("info", ("my_b_tell=%lu", my_b_tell(file))); if (my_b_read(file, (byte *) head, header_size)) { - DBUG_PRINT("info", ("Log_event::read_log_event(IO_CACHE*,Format_desc*) \ -failed my_b_read")); UNLOCK_MUTEX; - /* - No error here; it could be that we are at the file's end. However if the - next my_b_read() fails (below), it will be an error as we were able to - read the first bytes. - */ return 0; } @@ -726,8 +596,7 @@ failed my_b_read")); error = "read error"; goto err; } - if ((res= read_log_event(buf, data_len, &error, - description_event))) + if ((res = read_log_event(buf, data_len, &error, old_format))) res->register_temp_buf(buf); err: @@ -754,18 +623,13 @@ Error in Log_event::read_log_event(): '%s', data_len: %d, event_type: %d", /* Log_event::read_log_event() - Binlog format tolerance is in (buf, event_len, description_event) - constructors. */ -Log_event* Log_event::read_log_event(const char* buf, uint event_len, - const char **error, - const Format_description_log_event *description_event) +Log_event* Log_event::read_log_event(const char* buf, int event_len, + const char **error, bool old_format) { - Log_event* ev; - DBUG_ENTER("Log_event::read_log_event(char*,...)"); - DBUG_ASSERT(description_event); - DBUG_PRINT("info", ("binlog_version: %d", description_event->binlog_version)); + DBUG_ENTER("Log_event::read_log_event"); + if (event_len < EVENT_LEN_OFFSET || (uint) event_len != uint4korr(buf+EVENT_LEN_OFFSET)) { @@ -773,87 +637,74 @@ Log_event* Log_event::read_log_event(const char* buf, uint event_len, DBUG_RETURN(NULL); // general sanity check - will fail on a partial read } + Log_event* ev = NULL; + switch(buf[EVENT_TYPE_OFFSET]) { case QUERY_EVENT: - ev = new Query_log_event(buf, event_len, description_event); + ev = new Query_log_event(buf, event_len, old_format); break; case LOAD_EVENT: - ev = new Create_file_log_event(buf, event_len, description_event); + ev = new Create_file_log_event(buf, event_len, old_format); break; case NEW_LOAD_EVENT: - ev = new Load_log_event(buf, event_len, description_event); + ev = new Load_log_event(buf, event_len, old_format); break; case ROTATE_EVENT: - ev = new Rotate_log_event(buf, event_len, description_event); + ev = new Rotate_log_event(buf, event_len, old_format); break; #ifdef HAVE_REPLICATION - case SLAVE_EVENT: /* can never happen (unused event) */ + case SLAVE_EVENT: ev = new Slave_log_event(buf, event_len); break; #endif /* HAVE_REPLICATION */ case CREATE_FILE_EVENT: - ev = new Create_file_log_event(buf, event_len, description_event); + ev = new Create_file_log_event(buf, event_len, old_format); break; case APPEND_BLOCK_EVENT: - ev = new Append_block_log_event(buf, event_len, description_event); + ev = new Append_block_log_event(buf, event_len); break; case DELETE_FILE_EVENT: - ev = new Delete_file_log_event(buf, event_len, description_event); + ev = new Delete_file_log_event(buf, event_len); break; case EXEC_LOAD_EVENT: - ev = new Execute_load_log_event(buf, event_len, description_event); + ev = new Execute_load_log_event(buf, event_len); break; - case START_EVENT_V3: /* this is sent only by MySQL <=4.x */ - ev = new Start_log_event_v3(buf, description_event); + case START_EVENT: + ev = new Start_log_event(buf, old_format); break; #ifdef HAVE_REPLICATION case STOP_EVENT: - ev = new Stop_log_event(buf, description_event); + ev = new Stop_log_event(buf, old_format); break; #endif /* HAVE_REPLICATION */ case INTVAR_EVENT: - ev = new Intvar_log_event(buf, description_event); + ev = new Intvar_log_event(buf, old_format); break; case RAND_EVENT: - ev = new Rand_log_event(buf, description_event); + ev = new Rand_log_event(buf, old_format); break; case USER_VAR_EVENT: - ev = new User_var_log_event(buf, description_event); - break; - case FORMAT_DESCRIPTION_EVENT: - ev = new Format_description_log_event(buf, event_len, description_event); + ev = new User_var_log_event(buf, old_format); break; default: - DBUG_PRINT("error",("Unknown evernt code: %d",(int) buf[EVENT_TYPE_OFFSET])); - ev= NULL; break; } - /* - is_valid() are small event-specific sanity tests which are important; for - example there are some my_malloc() in constructors - (e.g. Query_log_event::Query_log_event(char*...)); when these my_malloc() - fail we can't return an error out of the constructor (because constructor - is "void") ; so instead we leave the pointer we wanted to allocate - (e.g. 'query') to 0 and we test it in is_valid(). Same for - Format_description_log_event, member 'post_header_len'. - */ if (!ev || !ev->is_valid()) { - DBUG_PRINT("error",("Found invalid event in binary log")); - delete ev; #ifdef MYSQL_CLIENT - if (!force_opt) /* then mysqlbinlog dies */ + if (!force_opt) { *error= "Found invalid event in binary log"; DBUG_RETURN(0); } - ev= new Unknown_log_event(buf, description_event); + ev= new Unknown_log_event(buf, old_format); #else *error= "Found invalid event in binary log"; DBUG_RETURN(0); #endif } + ev->cached_event_len = event_len; DBUG_RETURN(ev); } @@ -868,7 +719,7 @@ void Log_event::print_header(FILE* file) char llbuff[22]; fputc('#', file); print_timestamp(file); - fprintf(file, " server id %d end_log_pos %s ", server_id, + fprintf(file, " server id %d log_pos %s ", server_id, llstr(log_pos,llbuff)); } @@ -900,6 +751,19 @@ void Log_event::print_timestamp(FILE* file, time_t* ts) #endif /* MYSQL_CLIENT */ +/* + Log_event::set_log_pos() +*/ + +#ifndef MYSQL_CLIENT +void Log_event::set_log_pos(MYSQL_LOG* log) +{ + if (!log_pos) + log_pos = my_b_tell(&log->log_file); +} +#endif /* !MYSQL_CLIENT */ + + /************************************************************************** Query_log_event methods **************************************************************************/ @@ -908,15 +772,10 @@ void Log_event::print_timestamp(FILE* file, time_t* ts) /* Query_log_event::pack_info() - This (which is used only for SHOW BINLOG EVENTS) could be updated to - print SET @@session_var=. But this is not urgent, as SHOW BINLOG EVENTS is - only an information, it does not produce suitable queries to replay (for - example it does not print LOAD DATA INFILE). */ void Query_log_event::pack_info(Protocol *protocol) { - // TODO: show the catalog ?? char *buf, *pos; if (!(buf= my_malloc(9 + db_len + q_len, MYF(MY_WME)))) return; @@ -940,27 +799,31 @@ void Query_log_event::pack_info(Protocol *protocol) /* Query_log_event::write() +*/ + +int Query_log_event::write(IO_CACHE* file) +{ + return query ? Log_event::write(file) : -1; +} - NOTES: - In this event we have to modify the header to have the correct - EVENT_LEN_OFFSET as we don't yet know how many status variables we - will print! + +/* + Query_log_event::write_data() */ -bool Query_log_event::write(IO_CACHE* file) +int Query_log_event::write_data(IO_CACHE* file) { - uchar buf[QUERY_HEADER_LEN+1+4+1+8+1+1+FN_REFLEN+5], *start, *start_of_status; - ulong event_length; + char buf[QUERY_HEADER_LEN]; if (!query) - return 1; // Something wrong with event - + return -1; + /* We want to store the thread id: (- as an information for the user when he reads the binlog) - if the query uses temporary table: for the slave SQL thread to know to which master connection the temp table belongs. - Now imagine we (write()) are called by the slave SQL thread (we are + Now imagine we (write_data()) are called by the slave SQL thread (we are logging a query executed by this thread; the slave runs with --log-slave-updates). Then this query will be logged with thread_id=the_thread_id_of_the_SQL_thread. Imagine that 2 temp tables of @@ -997,77 +860,9 @@ bool Query_log_event::write(IO_CACHE* file) buf[Q_DB_LEN_OFFSET] = (char) db_len; int2store(buf + Q_ERR_CODE_OFFSET, error_code); - /* - You MUST always write status vars in increasing order of code. This - guarantees that a slightly older slave will be able to parse those he - knows. - */ - start_of_status= start= buf+QUERY_HEADER_LEN; - if (flags2_inited) - { - *(start++)= Q_FLAGS2_CODE; - int4store(start, flags2); - start+= 4; - } - if (sql_mode_inited) - { - *(start++)= Q_SQL_MODE_CODE; - int8store(start, sql_mode); - start+= 8; - } - if (catalog_len >= 0) // i.e. "catalog inited" (false for 4.0 events) - { - *(start++)= Q_CATALOG_CODE; - *(start++)= (uchar) catalog_len; - bmove(start, catalog, catalog_len); - start+= catalog_len; - /* - We write a \0 at the end. As we also have written the length, it's - apparently useless; but in fact it enables us to just do - catalog= a_pointer_to_the_buffer_of_the_read_event - later in the slave SQL thread. - If we didn't have the \0, we would need to memdup to build the catalog in - the slave SQL thread. - And still the interest of having the length too is that in the slave SQL - thread we immediately know at which position the catalog ends (no need to - search for '\0'. In other words: length saves search, \0 saves mem alloc, - at the cost of 1 redundant byte on the disk. - Note that this is only a fix until we change 'catalog' to LEX_STRING - (then we won't need the \0). - */ - *(start++)= '\0'; - } - if (auto_increment_increment != 1) - { - *start++= Q_AUTO_INCREMENT; - int2store(start, auto_increment_increment); - int2store(start+2, auto_increment_offset); - start+= 4; - } - /* - Here there could be code like - if (command-line-option-which-says-"log_this_variable") - { - *(start++)= Q_THIS_VARIABLE_CODE; - int4store(start, this_variable); - start+= 4; - } - */ - - /* Store length of status variables */ - status_vars_len= (uint) (start-start_of_status); - int2store(buf + Q_STATUS_VARS_LEN_OFFSET, status_vars_len); - - /* - Calculate length of whole event - The "1" below is the \0 in the db's length - */ - event_length= (uint) (start-buf) + db_len + 1 + q_len; - - return (write_header(file, event_length) || - my_b_safe_write(file, (byte*) buf, (uint) (start-buf)) || - my_b_safe_write(file, (db) ? (byte*) db : (byte*)"", db_len + 1) || - my_b_safe_write(file, (byte*) query, q_len)) ? 1 : 0; + return (my_b_safe_write(file, (byte*) buf, QUERY_HEADER_LEN) || + my_b_safe_write(file, (db) ? (byte*) db : (byte*)"", db_len + 1) || + my_b_safe_write(file, (byte*) query, q_len)) ? -1 : 0; } @@ -1080,162 +875,60 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg, ulong query_length, bool using_trans) :Log_event(thd_arg, !thd_arg->tmp_table_used ? 0 : LOG_EVENT_THREAD_SPECIFIC_F, using_trans), - data_buf(0), query(query_arg), catalog(thd_arg->catalog), + data_buf(0), query(query_arg), db(thd_arg->db), q_len((uint32) query_length), - error_code((thd_arg->killed != THD::NOT_KILLED) ? + error_code(thd_arg->killed ? ((thd_arg->system_thread & SYSTEM_THREAD_DELAYED_INSERT) ? - 0 : thd->killed_errno()) : thd_arg->net.last_errno), + 0 : ER_SERVER_SHUTDOWN) : thd_arg->net.last_errno), thread_id(thd_arg->thread_id), /* save the original thread id; we already know the server id */ - slave_proxy_id(thd_arg->variables.pseudo_thread_id), - flags2_inited(1), sql_mode_inited(1), flags2(0), - sql_mode(thd_arg->variables.sql_mode), - auto_increment_increment(thd_arg->variables.auto_increment_increment), - auto_increment_offset(thd_arg->variables.auto_increment_offset) + slave_proxy_id(thd_arg->variables.pseudo_thread_id) { time_t end_time; time(&end_time); exec_time = (ulong) (end_time - thd->start_time); - catalog_len = (catalog) ? (uint32) strlen(catalog) : 0; - status_vars_len= 1+4+1+8+1+1+catalog_len+1; db_len = (db) ? (uint32) strlen(db) : 0; - /* - If we don't use flags2 for anything else than options contained in - thd->options, it would be more efficient to flags2=thd_arg->options - (OPTIONS_WRITTEN_TO_BINLOG would be used only at reading time). - But it's likely that we don't want to use 32 bits for 3 bits; in the future - we will probably want to reclaim the 29 bits. So we need the &. - */ - flags2= thd_arg->options & OPTIONS_WRITTEN_TO_BIN_LOG; - - DBUG_PRINT("info",("Query_log_event has flags2=%lu sql_mode=%lu",flags2,sql_mode)); } #endif /* MYSQL_CLIENT */ /* Query_log_event::Query_log_event() - This is used by the SQL slave thread to prepare the event before execution. */ -Query_log_event::Query_log_event(const char* buf, uint event_len, - const Format_description_log_event *description_event) - :Log_event(buf, description_event), data_buf(0), query(NullS), catalog(NullS), - db(NullS), catalog_len(0), status_vars_len(0), - flags2_inited(0), sql_mode_inited(0) +Query_log_event::Query_log_event(const char* buf, int event_len, + bool old_format) + :Log_event(buf, old_format),data_buf(0), query(NULL), db(NULL) { ulong data_len; - uint32 tmp; - uint8 common_header_len, post_header_len; - const char *start, *end; - DBUG_ENTER("Query_log_event::Query_log_event(char*,...)"); - - common_header_len= description_event->common_header_len; - post_header_len= description_event->post_header_len[QUERY_EVENT-1]; - DBUG_PRINT("info",("event_len=%ld, common_header_len=%d, post_header_len=%d", - event_len, common_header_len, post_header_len)); - - /* - We test if the event's length is sensible, and if so we compute data_len. - We cannot rely on QUERY_HEADER_LEN here as it would not be format-tolerant. - We use QUERY_HEADER_MINIMAL_LEN which is the same for 3.23, 4.0 & 5.0. - */ - if (event_len < (uint)(common_header_len + post_header_len)) - DBUG_VOID_RETURN; - data_len = event_len - (common_header_len + post_header_len); - buf+= common_header_len; - - slave_proxy_id= thread_id = uint4korr(buf + Q_THREAD_ID_OFFSET); - exec_time = uint4korr(buf + Q_EXEC_TIME_OFFSET); - db_len = (uint)buf[Q_DB_LEN_OFFSET]; - error_code = uint2korr(buf + Q_ERR_CODE_OFFSET); - /* If auto_increment is not set by query_event, they should not be used */ - auto_increment_increment= auto_increment_offset= 1; - - /* - 5.0 format starts here. - Depending on the format, we may or not have affected/warnings etc - The remnent post-header to be parsed has length: - */ - tmp= post_header_len - QUERY_HEADER_MINIMAL_LEN; - if (tmp) + if (old_format) { - status_vars_len= uint2korr(buf + Q_STATUS_VARS_LEN_OFFSET); - data_len-= status_vars_len; - DBUG_PRINT("info", ("Query_log_event has status_vars_len: %u", - (uint) status_vars_len)); - tmp-= 2; + if ((uint)event_len < OLD_HEADER_LEN + QUERY_HEADER_LEN) + return; + data_len = event_len - (QUERY_HEADER_LEN + OLD_HEADER_LEN); + buf += OLD_HEADER_LEN; } - /* we have parsed everything we know in the post header */ -#ifndef DBUG_OFF - if (tmp) /* this is probably a master newer than us */ - DBUG_PRINT("info", ("Query_log_event has longer post header than we know\ - (%d more bytes)", tmp)); -#endif - - /* variable-part: the status vars; only in MySQL 5.0 */ - - start= (char*) (buf+post_header_len); - end= (char*) (start+status_vars_len); - for (const uchar* pos= (const uchar*) start; pos < (const uchar*) end;) - { - switch (*pos++) { - case Q_FLAGS2_CODE: - flags2_inited= 1; - flags2= uint4korr(pos); - DBUG_PRINT("info",("In Query_log_event, read flags2: %lu", flags2)); - pos+= 4; - break; - case Q_SQL_MODE_CODE: - { -#ifndef DBUG_OFF - char buff[22]; -#endif - sql_mode_inited= 1; - sql_mode= (ulong) uint8korr(pos); // QQ: Fix when sql_mode is ulonglong - DBUG_PRINT("info",("In Query_log_event, read sql_mode: %s", - llstr(sql_mode, buff))); - pos+= 8; - break; - } - case Q_CATALOG_CODE: - catalog_len= *pos; - if (catalog_len) - catalog= (char*) pos+1; // Will be copied later - pos+= catalog_len+2; - break; - case Q_AUTO_INCREMENT: - auto_increment_increment= uint2korr(pos); - auto_increment_offset= uint2korr(pos+2); - pos+= 4; - break; - default: - /* That's why you must write status vars in growing order of code */ - DBUG_PRINT("info",("Query_log_event has unknown status vars (first has\ - code: %u), skipping the rest of them", (uint) *(pos-1))); - pos= (const uchar*) end; // Break look - } - } - - /* A 2nd variable part; this is common to all versions */ - - if (!(start= data_buf = (char*) my_malloc(catalog_len + data_len +2, MYF(MY_WME)))) - DBUG_VOID_RETURN; - if (catalog) // If catalog is given + else { - memcpy((char*) start, catalog, catalog_len+1); // Copy name and end \0 - catalog= start; - start+= catalog_len+1; + if ((uint)event_len < QUERY_EVENT_OVERHEAD) + return; + data_len = event_len - QUERY_EVENT_OVERHEAD; + buf += LOG_EVENT_HEADER_LEN; } - memcpy((char*) start, end, data_len); // Copy db and query - ((char*) start)[data_len]= '\0'; // End query with \0 (For safetly) - db= start; - query= start + db_len + 1; - q_len= data_len - db_len -1; - /* This is used to detect wrong parsing. Could be removed in the future. */ - DBUG_PRINT("info", ("catalog: '%s' len: %u db: '%s' len: %u q_len: %lu", - catalog, (uint) catalog_len, db, (uint) db_len,q_len)); - DBUG_VOID_RETURN; + + exec_time = uint4korr(buf + Q_EXEC_TIME_OFFSET); + error_code = uint2korr(buf + Q_ERR_CODE_OFFSET); + + if (!(data_buf = (char*) my_malloc(data_len + 1, MYF(MY_WME)))) + return; + + memcpy(data_buf, buf + Q_DATA_OFFSET, data_len); + slave_proxy_id= thread_id= uint4korr(buf + Q_THREAD_ID_OFFSET); + db = data_buf; + db_len = (uint)buf[Q_DB_LEN_OFFSET]; + query=data_buf + db_len + 1; + q_len = data_len - 1 - db_len; + *((char*)query+q_len) = 0; } @@ -1244,14 +937,9 @@ Query_log_event::Query_log_event(const char* buf, uint event_len, */ #ifdef MYSQL_CLIENT -void Query_log_event::print(FILE* file, bool short_form, - LAST_EVENT_INFO* last_event_info) +void Query_log_event::print(FILE* file, bool short_form, char* last_db) { - // TODO: print the catalog ?? char buff[40],*end; // Enough for SET TIMESTAMP - bool different_db= 1; - uint32 tmp; - if (!short_form) { print_header(file); @@ -1259,10 +947,12 @@ void Query_log_event::print(FILE* file, bool short_form, (ulong) thread_id, (ulong) exec_time, error_code); } - if (db) + bool different_db= 1; + + if (db && last_db) { - if ((different_db = memcmp(last_event_info->db, db, db_len + 1))) - memcpy(last_event_info->db, db, db_len + 1); + if (different_db= memcmp(last_db, db, db_len + 1)) + memcpy(last_db, db, db_len + 1); } if (db && db[0] && different_db) @@ -1273,76 +963,8 @@ void Query_log_event::print(FILE* file, bool short_form, my_fwrite(file, (byte*) buff, (uint) (end-buff),MYF(MY_NABP | MY_WME)); if (flags & LOG_EVENT_THREAD_SPECIFIC_F) fprintf(file,"SET @@session.pseudo_thread_id=%lu;\n",(ulong)thread_id); - /* - Now the session variables; - it's more efficient to pass SQL_MODE as a number instead of a - comma-separated list. - FOREIGN_KEY_CHECKS, SQL_AUTO_IS_NULL, UNIQUE_CHECKS are session-only - variables (they have no global version; they're not listed in sql_class.h), - The tests below work for pure binlogs or pure relay logs. Won't work for - mixed relay logs but we don't create mixed relay logs (that is, there is no - relay log with a format change except within the 3 first events, which - mysqlbinlog handles gracefully). So this code should always be good. - */ - - if (likely(flags2_inited)) /* likely as this will mainly read 5.0 logs */ - { - /* tmp is a bitmask of bits which have changed. */ - if (likely(last_event_info->flags2_inited)) - /* All bits which have changed */ - tmp= (last_event_info->flags2) ^ flags2; - else /* that's the first Query event we read */ - { - last_event_info->flags2_inited= 1; - tmp= ~((uint32)0); /* all bits have changed */ - } - - if (unlikely(tmp)) /* some bits have changed */ - { - bool need_comma= 0; - fprintf(file, "SET "); - print_set_option(file, tmp, OPTION_NO_FOREIGN_KEY_CHECKS, ~flags2, - "@@session.foreign_key_checks", &need_comma); - print_set_option(file, tmp, OPTION_AUTO_IS_NULL, flags2, - "@@session.sql_auto_is_null", &need_comma); - print_set_option(file, tmp, OPTION_RELAXED_UNIQUE_CHECKS, ~flags2, - "@@session.unique_checks", &need_comma); - fprintf(file,";\n"); - last_event_info->flags2= flags2; - } - } - - /* - If flags2_inited==0, this is an event from 3.23 or 4.0; nothing to print - (remember we don't produce mixed relay logs so there cannot be 5.0 events - before that one so there is nothing to reset). - */ - - if (likely(sql_mode_inited)) - { - if (unlikely(!last_event_info->sql_mode_inited)) /* first Query event */ - { - last_event_info->sql_mode_inited= 1; - /* force a difference to force write */ - last_event_info->sql_mode= ~sql_mode; - } - if (unlikely(last_event_info->sql_mode != sql_mode)) - { - fprintf(file,"SET @@session.sql_mode=%lu;\n",(ulong)sql_mode); - last_event_info->sql_mode= sql_mode; - } - } - if (last_event_info->auto_increment_increment != auto_increment_increment || - last_event_info->auto_increment_offset != auto_increment_offset) - { - fprintf(file,"SET @@session.auto_increment_increment=%lu, @@session.auto_increment_offset=%lu;\n", - auto_increment_increment,auto_increment_offset); - last_event_info->auto_increment_increment= auto_increment_increment; - last_event_info->auto_increment_offset= auto_increment_offset; - } - my_fwrite(file, (byte*) query, q_len, MYF(MY_NABP | MY_WME)); - fputs(";\n", file); + fprintf(file, ";\n"); } #endif /* MYSQL_CLIENT */ @@ -1355,73 +977,34 @@ void Query_log_event::print(FILE* file, bool short_form, int Query_log_event::exec_event(struct st_relay_log_info* rli) { int expected_error,actual_error= 0; - /* - Colleagues: please never free(thd->catalog) in MySQL. This would lead to - bugs as here thd->catalog is a part of an alloced block, not an entire - alloced block (see Query_log_event::exec_event()). Same for thd->db. - Thank you. - */ - thd->catalog= (char*) catalog; - thd->db= (char*) rewrite_db(db); // thd->db_length is set later if needed - thd->variables.auto_increment_increment= auto_increment_increment; - thd->variables.auto_increment_offset= auto_increment_offset; + thd->db_length= db_len; + thd->db= (char*) rewrite_db(db, &thd->db_length); /* - InnoDB internally stores the master log position it has executed so far, - i.e. the position just after the COMMIT event. - When InnoDB will want to store, the positions in rli won't have - been updated yet, so group_master_log_* will point to old BEGIN - and event_master_log* will point to the beginning of current COMMIT. - But log_pos of the COMMIT Query event is what we want, i.e. the pos of the - END of the current log event (COMMIT). We save it in rli so that InnoDB can - access it. + InnoDB internally stores the master log position it has processed so far; + position to store is of the END of the current log event. */ +#if MYSQL_VERSION_ID < 50000 + rli->future_group_master_log_pos= log_pos + get_event_len() - + (rli->mi->old_format ? (LOG_EVENT_HEADER_LEN - OLD_HEADER_LEN) : 0); +#else + /* In 5.0 we store the end_log_pos in the relay log so no problem */ rli->future_group_master_log_pos= log_pos; - DBUG_PRINT("info", ("log_pos: %lu", (ulong) log_pos)); - +#endif clear_all_errors(thd, rli); if (db_ok(thd->db, replicate_do_db, replicate_ignore_db)) { thd->set_time((time_t)when); - /* - We cannot use db_len from event to fill thd->db_length, because - rewrite_db() may have changed db. - */ - thd->db_length= thd->db ? strlen(thd->db) : 0; thd->query_length= q_len; thd->query = (char*)query; VOID(pthread_mutex_lock(&LOCK_thread_count)); thd->query_id = query_id++; VOID(pthread_mutex_unlock(&LOCK_thread_count)); thd->variables.pseudo_thread_id= thread_id; // for temp tables + mysql_log.write(thd,COM_QUERY,"%s",thd->query); DBUG_PRINT("query",("%s",thd->query)); - - if (flags2_inited) - /* - all bits of thd->options which are 1 in OPTIONS_WRITTEN_TO_BIN_LOG must - take their value from flags2. - */ - thd->options= flags2|(thd->options & ~(ulong)OPTIONS_WRITTEN_TO_BIN_LOG); - /* - else, we are in a 3.23/4.0 binlog; we previously received a - Rotate_log_event which reset thd->options and sql_mode, so nothing to do. - */ - - /* - We do not replicate IGNORE_DIR_IN_CREATE. That is, if the master is a - slave which runs with SQL_MODE=IGNORE_DIR_IN_CREATE, this should not - force us to ignore the dir too. Imagine you are a ring of machines, and - one has a disk problem so that you temporarily need IGNORE_DIR_IN_CREATE - on this machine; you don't want it to propagate elsewhere (you don't want - all slaves to start ignoring the dirs). - */ - if (sql_mode_inited) - thd->variables.sql_mode= - (ulong) ((thd->variables.sql_mode & MODE_NO_DIR_IN_CREATE) | - (sql_mode & ~(ulong) MODE_NO_DIR_IN_CREATE)); - if (ignored_error_code((expected_error= error_code)) || !check_expected_error(thd,rli,expected_error)) mysql_parse(thd, thd->query, q_len); @@ -1449,35 +1032,35 @@ START SLAVE; . Query: '%s'", expected_error, thd->query); } goto end; } - + /* If we expected a non-zero error code, and we don't get the same error code, and none of them should be ignored. */ DBUG_PRINT("info",("expected_error: %d last_errno: %d", - expected_error, thd->net.last_errno)); + expected_error, thd->net.last_errno)); if ((expected_error != (actual_error= thd->net.last_errno)) && - expected_error && - !ignored_error_code(actual_error) && - !ignored_error_code(expected_error)) + expected_error && + !ignored_error_code(actual_error) && + !ignored_error_code(expected_error)) { slave_print_error(rli, 0, - "\ + "\ Query caused different errors on master and slave. \ Error on master: '%s' (%d), Error on slave: '%s' (%d). \ Default database: '%s'. Query: '%s'", - ER_SAFE(expected_error), - expected_error, - actual_error ? thd->net.last_error: "no error", - actual_error, - print_slave_db_safe(db), query); + ER_SAFE(expected_error), + expected_error, + actual_error ? thd->net.last_error: "no error", + actual_error, + print_slave_db_safe(thd->db), query); thd->query_error= 1; } /* If we get the same error code as expected, or they should be ignored. */ else if (expected_error == actual_error || - ignored_error_code(actual_error)) + ignored_error_code(actual_error)) { DBUG_PRINT("info",("error ignored")); clear_all_errors(thd, rli); @@ -1489,48 +1072,16 @@ Default database: '%s'. Query: '%s'", { slave_print_error(rli,actual_error, "Error '%s' on query. Default database: '%s'. Query: '%s'", - (actual_error ? thd->net.last_error : - "unexpected success or fatal error"), - print_slave_db_safe(db), query); + (actual_error ? thd->net.last_error : + "unexpected success or fatal error"), + print_slave_db_safe(thd->db), query); thd->query_error= 1; } - - /* - TODO: compare the values of "affected rows" around here. Something - like: - if ((uint32) affected_in_event != (uint32) affected_on_slave) - { - sql_print_error("Slave: did not get the expected number of affected \ - rows running query from master - expected %d, got %d (this numbers \ - should have matched modulo 4294967296).", 0, ...); - thd->query_error = 1; - } - We may also want an option to tell the slave to ignore "affected" - mismatch. This mismatch could be implemented with a new ER_ code, and - to ignore it you would use --slave-skip-errors... - - To do the comparison we need to know the value of "affected" which the - above mysql_parse() computed. And we need to know the value of - "affected" in the master's binlog. Both will be implemented later. The - important thing is that we now have the format ready to log the values - of "affected" in the binlog. So we can release 5.0.0 before effectively - logging "affected" and effectively comparing it. - */ } /* End of if (db_ok(... */ end: VOID(pthread_mutex_lock(&LOCK_thread_count)); - /* - Probably we have set thd->query, thd->db, thd->catalog to point to places - in the data_buf of this event. Now the event is going to be deleted - probably, so data_buf will be freed, so the thd->... listed above will be - pointers to freed memory. - So we must set them to 0, so that those bad pointers values are not later - used. Note that "cleanup" queries (automatic DO RELEASE_LOCK() and DROP - TEMPORARY TABLE don't suffer from these assignments to 0 as DROP TEMPORARY - TABLE uses the db.table syntax). - */ - thd->db= thd->catalog= 0; // prevent db from being freed + thd->db= 0; // prevent db from being freed thd->query= 0; // just to be sure thd->query_length= thd->db_length =0; VOID(pthread_mutex_unlock(&LOCK_thread_count)); @@ -1543,30 +1094,22 @@ end: updating query. */ return (thd->query_error ? thd->query_error : - (thd->one_shot_set ? (rli->inc_event_relay_log_pos(),0) : + (thd->one_shot_set ? (rli->inc_event_relay_log_pos(get_event_len()),0) : Log_event::exec_event(rli))); } #endif /************************************************************************** - Start_log_event_v3 methods + Start_log_event methods **************************************************************************/ -#ifndef MYSQL_CLIENT -Start_log_event_v3::Start_log_event_v3() :Log_event(), binlog_version(BINLOG_VERSION), artificial_event(0) -{ - created= when; - memcpy(server_version, ::server_version, ST_SERVER_VER_LEN); -} -#endif - /* - Start_log_event_v3::pack_info() + Start_log_event::pack_info() */ #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) -void Start_log_event_v3::pack_info(Protocol *protocol) +void Start_log_event::pack_info(Protocol *protocol) { char buf[12 + ST_SERVER_VER_LEN + 14 + 22], *pos; pos= strmov(buf, "Server ver: "); @@ -1579,69 +1122,57 @@ void Start_log_event_v3::pack_info(Protocol *protocol) /* - Start_log_event_v3::print() + Start_log_event::print() */ #ifdef MYSQL_CLIENT -void Start_log_event_v3::print(FILE* file, bool short_form, LAST_EVENT_INFO* last_event_info) +void Start_log_event::print(FILE* file, bool short_form, char* last_db) { - if (!short_form) - { - print_header(file); - fprintf(file, "\tStart: binlog v %d, server v %s created ", binlog_version, - server_version); - print_timestamp(file); - if (created) - fprintf(file," at startup"); - fputc('\n', file); - } -#ifdef WHEN_WE_HAVE_THE_RESET_CONNECTION_SQL_COMMAND - /* - This is for mysqlbinlog: like in replication, we want to delete the stale - tmp files left by an unclean shutdown of mysqld (temporary tables). Probably - this can be done with RESET CONNECTION (syntax to be defined). - */ - fprintf(file,"RESET CONNECTION;\n"); -#endif + if (short_form) + return; + + print_header(file); + fprintf(file, "\tStart: binlog v %d, server v %s created ", binlog_version, + server_version); + print_timestamp(file); + if (created) + fprintf(file," at startup"); + fputc('\n', file); fflush(file); } #endif /* MYSQL_CLIENT */ /* - Start_log_event_v3::Start_log_event_v3() + Start_log_event::Start_log_event() */ -Start_log_event_v3::Start_log_event_v3(const char* buf, - const Format_description_log_event* description_event) - :Log_event(buf, description_event) +Start_log_event::Start_log_event(const char* buf, + bool old_format) + :Log_event(buf, old_format) { - buf+= description_event->common_header_len; - binlog_version= uint2korr(buf+ST_BINLOG_VER_OFFSET); + buf += (old_format) ? OLD_HEADER_LEN : LOG_EVENT_HEADER_LEN; + binlog_version = uint2korr(buf+ST_BINLOG_VER_OFFSET); memcpy(server_version, buf+ST_SERVER_VER_OFFSET, ST_SERVER_VER_LEN); - created= uint4korr(buf+ST_CREATED_OFFSET); - /* We use log_pos to mark if this was an artificial event or not */ - artificial_event= (log_pos == 0); + created = uint4korr(buf+ST_CREATED_OFFSET); } /* - Start_log_event_v3::write() + Start_log_event::write_data() */ -bool Start_log_event_v3::write(IO_CACHE* file) +int Start_log_event::write_data(IO_CACHE* file) { - char buff[START_V3_HEADER_LEN]; + char buff[START_HEADER_LEN]; int2store(buff + ST_BINLOG_VER_OFFSET,binlog_version); memcpy(buff + ST_SERVER_VER_OFFSET,server_version,ST_SERVER_VER_LEN); int4store(buff + ST_CREATED_OFFSET,created); - return (write_header(file, sizeof(buff)) || - my_b_safe_write(file, (byte*) buff, sizeof(buff))); + return (my_b_safe_write(file, (byte*) buff, sizeof(buff)) ? -1 : 0); } - /* - Start_log_event_v3::exec_event() + Start_log_event::exec_event() The master started @@ -1660,29 +1191,23 @@ bool Start_log_event_v3::write(IO_CACHE* file) */ #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) -int Start_log_event_v3::exec_event(struct st_relay_log_info* rli) +int Start_log_event::exec_event(struct st_relay_log_info* rli) { - DBUG_ENTER("Start_log_event_v3::exec_event"); + DBUG_ENTER("Start_log_event::exec_event"); + /* If the I/O thread has not started, mi->old_format is BINLOG_FORMAT_CURRENT (that's what the MASTER_INFO constructor does), so the test below is not perfect at all. */ - switch (rli->relay_log.description_event_for_exec->binlog_version) - { - case 3: - case 4: - /* - This can either be 4.x (then a Start_log_event_v3 is only at master - startup so we are sure the master has restarted and cleared his temp - tables; the event always has 'created'>0) or 5.0 (then we have to test - 'created'). + switch (rli->mi->old_format) { + case BINLOG_FORMAT_CURRENT: + /* + This is 4.x, so a Start_log_event is only at master startup, + so we are sure the master has restarted and cleared his temp tables. */ - if (created) - { - close_temporary_tables(thd); - cleanup_load_tmpdir(); - } + close_temporary_tables(thd); + cleanup_load_tmpdir(); /* As a transaction NEVER spans on 2 or more binlogs: if we have an active transaction at this point, the master died while @@ -1690,12 +1215,8 @@ int Start_log_event_v3::exec_event(struct st_relay_log_info* rli) cache to the binlog. As the write was started, the transaction had been committed on the master, so we lack of information to replay this transaction on the slave; all we can do is stop with error. - Note: this event could be sent by the master to inform us of the format - of its binlog; in other words maybe it is not at its original place when - it comes to us; we'll know this by checking log_pos ("artificial" events - have log_pos == 0). */ - if (!artificial_event && (thd->options & OPTION_BEGIN)) + if (thd->options & OPTION_BEGIN) { slave_print_error(rli, 0, "\ Rolling back unfinished transaction (no COMMIT or ROLLBACK) from relay log. \ @@ -1709,274 +1230,33 @@ binary log."); Now the older formats; in that case load_tmpdir is cleaned up by the I/O thread. */ - case 1: - if (strncmp(rli->relay_log.description_event_for_exec->server_version, - "3.23.57",7) >= 0 && created) - { - /* - Can distinguish, based on the value of 'created': this event was - generated at master startup. - */ - close_temporary_tables(thd); - } + case BINLOG_FORMAT_323_LESS_57: /* - Otherwise, can't distinguish a Start_log_event generated at - master startup and one generated by master FLUSH LOGS, so cannot - be sure temp tables have to be dropped. So do nothing. + Cannot distinguish a Start_log_event generated at master startup and + one generated by master FLUSH LOGS, so cannot be sure temp tables + have to be dropped. So do nothing. */ break; - default: - /* this case is impossible */ - DBUG_RETURN(1); - } - DBUG_RETURN(Log_event::exec_event(rli)); -} -#endif /* defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) */ - -/*************************************************************************** - Format_description_log_event methods -****************************************************************************/ - -/* - Format_description_log_event 1st ctor. - - SYNOPSIS - Format_description_log_event::Format_description_log_event - binlog_version the binlog version for which we want to build - an event. Can be 1 (=MySQL 3.23), 3 (=4.0.x - x>=2 and 4.1) or 4 (MySQL 5.0). Note that the - old 4.0 (binlog version 2) is not supported; - it should not be used for replication with - 5.0. - - DESCRIPTION - Ctor. Can be used to create the event to write to the binary log (when the - server starts or when FLUSH LOGS), or to create artificial events to parse - binlogs from MySQL 3.23 or 4.x. - When in a client, only the 2nd use is possible. - - TODO - Update this code with the new event for LOAD DATA, once they are pushed (in - 4.1 or 5.0). If it's in 5.0, only the "case 4" block should be updated. - -*/ - -Format_description_log_event:: -Format_description_log_event(uint8 binlog_ver, - const char* server_ver) - :Start_log_event_v3() -{ - created= when; - binlog_version= binlog_ver; - switch (binlog_ver) { - case 4: /* MySQL 5.0 */ - memcpy(server_version, ::server_version, ST_SERVER_VER_LEN); - common_header_len= LOG_EVENT_HEADER_LEN; - number_of_event_types= LOG_EVENT_TYPES; - /* we'll catch my_malloc() error in is_valid() */ - post_header_len=(uint8*) my_malloc(number_of_event_types*sizeof(uint8), - MYF(0)); + case BINLOG_FORMAT_323_GEQ_57: /* - This long list of assignments is not beautiful, but I see no way to - make it nicer, as the right members are #defines, not array members, so - it's impossible to write a loop. + Can distinguish, based on the value of 'created', + which was generated at master startup. */ - if (post_header_len) - { - post_header_len[START_EVENT_V3-1]= START_V3_HEADER_LEN; - post_header_len[QUERY_EVENT-1]= QUERY_HEADER_LEN; - post_header_len[STOP_EVENT-1]= 0; - post_header_len[ROTATE_EVENT-1]= ROTATE_HEADER_LEN; - post_header_len[INTVAR_EVENT-1]= 0; - post_header_len[LOAD_EVENT-1]= LOAD_HEADER_LEN; - post_header_len[SLAVE_EVENT-1]= 0; - post_header_len[CREATE_FILE_EVENT-1]= CREATE_FILE_HEADER_LEN; - post_header_len[APPEND_BLOCK_EVENT-1]= APPEND_BLOCK_HEADER_LEN; - post_header_len[EXEC_LOAD_EVENT-1]= EXEC_LOAD_HEADER_LEN; - post_header_len[DELETE_FILE_EVENT-1]= DELETE_FILE_HEADER_LEN; - post_header_len[NEW_LOAD_EVENT-1]= post_header_len[LOAD_EVENT-1]; - post_header_len[RAND_EVENT-1]= 0; - post_header_len[USER_VAR_EVENT-1]= 0; - post_header_len[FORMAT_DESCRIPTION_EVENT-1]= FORMAT_DESCRIPTION_HEADER_LEN; - } - break; - - case 1: /* 3.23 */ - case 3: /* 4.0.x x>=2 */ - /* - We build an artificial (i.e. not sent by the master) event, which - describes what those old master versions send. - */ - if (binlog_ver==1) - strmov(server_version, server_ver ? server_ver : "3.23"); - else - strmov(server_version, server_ver ? server_ver : "4.0"); - common_header_len= binlog_ver==1 ? OLD_HEADER_LEN : - LOG_EVENT_MINIMAL_HEADER_LEN; - /* - The first new event in binlog version 4 is Format_desc. So any event type - after that does not exist in older versions. We use the events known by - version 3, even if version 1 had only a subset of them (this is not a - problem: it uses a few bytes for nothing but unifies code; it does not - make the slave detect less corruptions). - */ - number_of_event_types= FORMAT_DESCRIPTION_EVENT - 1; - post_header_len=(uint8*) my_malloc(number_of_event_types*sizeof(uint8), - MYF(0)); - if (post_header_len) - { - post_header_len[START_EVENT_V3-1]= START_V3_HEADER_LEN; - post_header_len[QUERY_EVENT-1]= QUERY_HEADER_MINIMAL_LEN; - post_header_len[STOP_EVENT-1]= 0; - post_header_len[ROTATE_EVENT-1]= (binlog_ver==1) ? 0 : ROTATE_HEADER_LEN; - post_header_len[INTVAR_EVENT-1]= 0; - post_header_len[LOAD_EVENT-1]= LOAD_HEADER_LEN; - post_header_len[SLAVE_EVENT-1]= 0; - post_header_len[CREATE_FILE_EVENT-1]= CREATE_FILE_HEADER_LEN; - post_header_len[APPEND_BLOCK_EVENT-1]= APPEND_BLOCK_HEADER_LEN; - post_header_len[EXEC_LOAD_EVENT-1]= EXEC_LOAD_HEADER_LEN; - post_header_len[DELETE_FILE_EVENT-1]= DELETE_FILE_HEADER_LEN; - post_header_len[NEW_LOAD_EVENT-1]= post_header_len[LOAD_EVENT-1]; - post_header_len[RAND_EVENT-1]= 0; - post_header_len[USER_VAR_EVENT-1]= 0; - } - break; - default: /* Includes binlog version 2 i.e. 4.0.x x<=1 */ - post_header_len= 0; /* will make is_valid() fail */ + if (created) + close_temporary_tables(thd); break; - } -} - - -/* - The problem with this constructor is that the fixed header may have a - length different from this version, but we don't know this length as we - have not read the Format_description_log_event which says it, yet. This - length is in the post-header of the event, but we don't know where the - post-header starts. - So this type of event HAS to: - - either have the header's length at the beginning (in the header, at a - fixed position which will never be changed), not in the post-header. That - would make the header be "shifted" compared to other events. - - or have a header of size LOG_EVENT_MINIMAL_HEADER_LEN (19), in all future - versions, so that we know for sure. - I (Guilhem) chose the 2nd solution. Rotate has the same constraint (because - it is sent before Format_description_log_event). -*/ - -Format_description_log_event:: -Format_description_log_event(const char* buf, - uint event_len, - const - Format_description_log_event* - description_event) - :Start_log_event_v3(buf, description_event) -{ - DBUG_ENTER("Format_description_log_event::Format_description_log_event(char*,...)"); - buf+= LOG_EVENT_MINIMAL_HEADER_LEN; - if ((common_header_len=buf[ST_COMMON_HEADER_LEN_OFFSET]) < OLD_HEADER_LEN) - DBUG_VOID_RETURN; /* sanity check */ - number_of_event_types= - event_len-(LOG_EVENT_MINIMAL_HEADER_LEN+ST_COMMON_HEADER_LEN_OFFSET+1); - DBUG_PRINT("info", ("common_header_len=%d number_of_event_types=%d", - common_header_len, number_of_event_types)); - /* If alloc fails, we'll detect it in is_valid() */ - post_header_len= (uint8*) my_memdup((byte*)buf+ST_COMMON_HEADER_LEN_OFFSET+1, - number_of_event_types* - sizeof(*post_header_len), - MYF(0)); - DBUG_VOID_RETURN; -} - - -bool Format_description_log_event::write(IO_CACHE* file) -{ - /* - We don't call Start_log_event_v3::write() because this would make 2 - my_b_safe_write(). - */ - byte buff[FORMAT_DESCRIPTION_HEADER_LEN]; - int2store(buff + ST_BINLOG_VER_OFFSET,binlog_version); - memcpy((char*) buff + ST_SERVER_VER_OFFSET,server_version,ST_SERVER_VER_LEN); - int4store(buff + ST_CREATED_OFFSET,created); - buff[ST_COMMON_HEADER_LEN_OFFSET]= LOG_EVENT_HEADER_LEN; - memcpy((char*) buff+ST_COMMON_HEADER_LEN_OFFSET+1, (byte*) post_header_len, - LOG_EVENT_TYPES); - return (write_header(file, sizeof(buff)) || - my_b_safe_write(file, buff, sizeof(buff))); -} - -/* - SYNOPSIS - Format_description_log_event::exec_event() - - IMPLEMENTATION - Save the information which describes the binlog's format, to be able to - read all coming events. - Call Start_log_event_v3::exec_event(). -*/ - -#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) -int Format_description_log_event::exec_event(struct st_relay_log_info* rli) -{ - DBUG_ENTER("Format_description_log_event::exec_event"); - - /* save the information describing this binlog */ - delete rli->relay_log.description_event_for_exec; - rli->relay_log.description_event_for_exec= this; - - /* - If this event comes from ourselves, there is no cleaning task to perform, - we don't call Start_log_event_v3::exec_event() (this was just to update the - log's description event). - */ - if (server_id == (uint32) ::server_id) - { - /* - Do not modify rli->group_master_log_pos, as this event did not exist on - the master. That is, just update the *relay log* coordinates; this is - done by passing log_pos=0 to inc_group_relay_log_pos, like we do in - Stop_log_event::exec_event(). - If in a transaction, don't touch group_* coordinates. - */ - if (thd->options & OPTION_BEGIN) - rli->inc_event_relay_log_pos(); - else - { - rli->inc_group_relay_log_pos(0); - flush_relay_log_info(rli); - } - DBUG_RETURN(0); + default: + /* this case is impossible */ + return 1; } - /* - If the event was not requested by the slave i.e. the master sent it while - the slave asked for a position >4, the event will make - rli->group_master_log_pos advance. Say that the slave asked for position - 1000, and the Format_desc event's end is 95. Then in the beginning of - replication rli->group_master_log_pos will be 0, then 95, then jump to first - really asked event (which is >95). So this is ok. - */ - DBUG_RETURN(Start_log_event_v3::exec_event(rli)); + DBUG_RETURN(Log_event::exec_event(rli)); } -#endif +#endif /* defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) */ - /************************************************************************** - Load_log_event methods - General note about Load_log_event: the binlogging of LOAD DATA INFILE is - going to be changed in 5.0 (or maybe in 4.1; not decided yet). - However, the 5.0 slave could still have to read such events (from a 4.x - master), convert them (which just means maybe expand the header, when 5.0 - servers have a UID in events) (remember that whatever is after the header - will be like in 4.x, as this event's format is not modified in 5.0 as we - will use new types of events to log the new LOAD DATA INFILE features). - To be able to read/convert, we just need to not assume that the common - header is of length LOG_EVENT_HEADER_LEN (we must use the description - event). - Note that I (Guilhem) manually tested replication of a big LOAD DATA INFILE - between 3.23 and 5.0, and between 4.0 and 5.0, and it works fine (and the - positions displayed in SHOW SLAVE STATUS then are fine too). - **************************************************************************/ +/************************************************************************** + Load_log_event methods +**************************************************************************/ /* Load_log_event::pack_info() @@ -2083,7 +1363,7 @@ void Load_log_event::pack_info(Protocol *protocol) Load_log_event::write_data_header() */ -bool Load_log_event::write_data_header(IO_CACHE* file) +int Load_log_event::write_data_header(IO_CACHE* file) { char buf[LOAD_HEADER_LEN]; int4store(buf + L_THREAD_ID_OFFSET, slave_proxy_id); @@ -2092,7 +1372,7 @@ bool Load_log_event::write_data_header(IO_CACHE* file) buf[L_TBL_LEN_OFFSET] = (char)table_name_len; buf[L_DB_LEN_OFFSET] = (char)db_len; int4store(buf + L_NUM_FIELDS_OFFSET, num_fields); - return my_b_safe_write(file, (byte*)buf, LOAD_HEADER_LEN) != 0; + return my_b_safe_write(file, (byte*)buf, LOAD_HEADER_LEN); } @@ -2100,7 +1380,7 @@ bool Load_log_event::write_data_header(IO_CACHE* file) Load_log_event::write_data_body() */ -bool Load_log_event::write_data_body(IO_CACHE* file) +int Load_log_event::write_data_body(IO_CACHE* file) { if (sql_ex.write_data(file)) return 1; @@ -2203,7 +1483,6 @@ Load_log_event::Load_log_event(THD *thd_arg, sql_exchange *ex, } #endif /* !MYSQL_CLIENT */ - /* Load_log_event::Load_log_event() @@ -2212,25 +1491,15 @@ Load_log_event::Load_log_event(THD *thd_arg, sql_exchange *ex, constructed event. */ -Load_log_event::Load_log_event(const char *buf, uint event_len, - const Format_description_log_event *description_event) - :Log_event(buf, description_event), num_fields(0), fields(0), - field_lens(0),field_block_len(0), +Load_log_event::Load_log_event(const char *buf, int event_len, + bool old_format) + :Log_event(buf, old_format), num_fields(0), fields(0), + field_lens(0), field_block_len(0), table_name(0), db(0), fname(0), local_fname(FALSE) { DBUG_ENTER("Load_log_event"); - /* - I (Guilhem) manually tested replication of LOAD DATA INFILE for 3.23->5.0, - 4.0->5.0 and 5.0->5.0 and it works. - */ - if (event_len) - copy_log_event(buf, event_len, - ((buf[EVENT_TYPE_OFFSET] == LOAD_EVENT) ? - LOAD_HEADER_LEN + - description_event->common_header_len : - LOAD_HEADER_LEN + LOG_EVENT_HEADER_LEN), - description_event); - /* otherwise it's a derived class, will call copy_log_event() itself */ + if (event_len) // derived class, will call copy_log_event() itself + copy_log_event(buf, event_len, old_format); DBUG_VOID_RETURN; } @@ -2240,14 +1509,14 @@ Load_log_event::Load_log_event(const char *buf, uint event_len, */ int Load_log_event::copy_log_event(const char *buf, ulong event_len, - int body_offset, - const Format_description_log_event *description_event) + bool old_format) { - DBUG_ENTER("Load_log_event::copy_log_event"); uint data_len; char* buf_end = (char*)buf + event_len; - /* this is the beginning of the post-header */ - const char* data_head = buf + description_event->common_header_len; + uint header_len= old_format ? OLD_HEADER_LEN : LOG_EVENT_HEADER_LEN; + const char* data_head = buf + header_len; + DBUG_ENTER("Load_log_event::copy_log_event"); + slave_proxy_id= thread_id= uint4korr(data_head + L_THREAD_ID_OFFSET); exec_time = uint4korr(data_head + L_EXEC_TIME_OFFSET); skip_lines = uint4korr(data_head + L_SKIP_LINES_OFFSET); @@ -2255,17 +1524,21 @@ int Load_log_event::copy_log_event(const char *buf, ulong event_len, db_len = (uint)data_head[L_DB_LEN_OFFSET]; num_fields = uint4korr(data_head + L_NUM_FIELDS_OFFSET); + int body_offset = ((buf[EVENT_TYPE_OFFSET] == LOAD_EVENT) ? + LOAD_HEADER_LEN + header_len : + get_data_body_offset()); + if ((int) event_len < body_offset) DBUG_RETURN(1); /* Sql_ex.init() on success returns the pointer to the first byte after the sql_ex structure, which is the start of field lengths array. */ - if (!(field_lens= (uchar*)sql_ex.init((char*)buf + body_offset, - buf_end, - buf[EVENT_TYPE_OFFSET] != LOAD_EVENT))) + if (!(field_lens=(uchar*)sql_ex.init((char*)buf + body_offset, + buf_end, + buf[EVENT_TYPE_OFFSET] != LOAD_EVENT))) DBUG_RETURN(1); - + data_len = event_len - body_offset; if (num_fields > data_len) // simple sanity check against corruption DBUG_RETURN(1); @@ -2278,12 +1551,6 @@ int Load_log_event::copy_log_event(const char *buf, ulong event_len, fname = db + db_len + 1; fname_len = strlen(fname); // null termination is accomplished by the caller doing buf[event_len]=0 - - /* - In 5.0 this event will have the same format, as we are planning to log LOAD - DATA INFILE in a completely different way (as a plain-text query) since 4.1 - or 5.0 (Dmitri's WL#874) - */ DBUG_RETURN(0); } @@ -2293,13 +1560,13 @@ int Load_log_event::copy_log_event(const char *buf, ulong event_len, */ #ifdef MYSQL_CLIENT -void Load_log_event::print(FILE* file, bool short_form, LAST_EVENT_INFO* last_event_info) +void Load_log_event::print(FILE* file, bool short_form, char* last_db) { - print(file, short_form, last_event_info, 0); + print(file, short_form, last_db, 0); } -void Load_log_event::print(FILE* file, bool short_form, LAST_EVENT_INFO* last_event_info, +void Load_log_event::print(FILE* file, bool short_form, char* last_db, bool commented) { DBUG_ENTER("Load_log_event::print"); @@ -2311,7 +1578,7 @@ void Load_log_event::print(FILE* file, bool short_form, LAST_EVENT_INFO* last_ev } bool different_db= 1; - if (db) + if (db && last_db) { /* If the database is different from the one of the previous statement, we @@ -2319,9 +1586,9 @@ void Load_log_event::print(FILE* file, bool short_form, LAST_EVENT_INFO* last_ev But if commented, the "use" is going to be commented so we should not update the last_db. */ - if ((different_db= memcmp(last_event_info->db, db, db_len + 1)) && + if ((different_db= memcmp(last_db, db, db_len + 1)) && !commented) - memcpy(last_event_info->db, db, db_len + 1); + memcpy(last_db, db, db_len + 1); } if (db && db[0] && different_db) @@ -2435,7 +1702,8 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli, bool use_rli_only_for_errors) { char *load_data_query= 0; - thd->db= (char*) rewrite_db(db); // thd->db_length is set later if needed + thd->db_length= db_len; + thd->db= (char*) rewrite_db(db, &thd->db_length); DBUG_ASSERT(thd->query == 0); thd->query_length= 0; // Should not be needed thd->query_error= 0; @@ -2447,12 +1715,15 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli, mysql_init_query(thd, 0, 0); if (!use_rli_only_for_errors) { - /* Saved for InnoDB, see comment in Query_log_event::exec_event() */ +#if MYSQL_VERSION_ID < 50000 + rli->future_group_master_log_pos= log_pos + get_event_len() - + (rli->mi->old_format ? (LOG_EVENT_HEADER_LEN - OLD_HEADER_LEN) : 0); +#else rli->future_group_master_log_pos= log_pos; - DBUG_PRINT("info", ("log_pos: %lu", (ulong) log_pos)); +#endif } - - /* + + /* We test replicate_*_db rules. Note that we have already prepared the file to load, even if we are going to ignore and delete it now. So it is possible that we did a lot of disk writes for nothing. In other words, a @@ -2467,7 +1738,6 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli, if (db_ok(thd->db, replicate_do_db, replicate_ignore_db)) { thd->set_time((time_t)when); - thd->db_length= thd->db ? strlen(thd->db) : 0; VOID(pthread_mutex_lock(&LOCK_thread_count)); thd->query_id = query_id++; VOID(pthread_mutex_unlock(&LOCK_thread_count)); @@ -2562,7 +1832,7 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli, thd->net.pkt_nr = net->pkt_nr; } if (mysql_load(thd, &ex, &tables, field_list, handle_dup, net != 0, - TL_WRITE, 0)) + TL_WRITE)) thd->query_error = 1; if (thd->cuted_fields) { @@ -2573,7 +1843,7 @@ Slave: load data infile on table '%s' at log position %s in log \ (char*) table_name, llstr(log_pos,llbuff), RPL_LOG_NAME, (ulong) thd->cuted_fields, - print_slave_db_safe(db)); + print_slave_db_safe(thd->db)); } if (net) net->pkt_nr= thd->net.pkt_nr; @@ -2591,8 +1861,9 @@ Slave: load data infile on table '%s' at log position %s in log \ } thd->net.vio = 0; + char *save_db= thd->db; VOID(pthread_mutex_lock(&LOCK_thread_count)); - thd->db= thd->catalog= 0; + thd->db= 0; thd->query= 0; thd->query_length= thd->db_length= 0; VOID(pthread_mutex_unlock(&LOCK_thread_count)); @@ -2613,7 +1884,7 @@ Slave: load data infile on table '%s' at log position %s in log \ } slave_print_error(rli,sql_errno,"\ Error '%s' running LOAD DATA INFILE on table '%s'. Default database: '%s'", - err, (char*)table_name, print_slave_db_safe(db)); + err, (char*)table_name, print_slave_db_safe(save_db)); free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC)); return 1; } @@ -2623,7 +1894,7 @@ Error '%s' running LOAD DATA INFILE on table '%s'. Default database: '%s'", { slave_print_error(rli,ER_UNKNOWN_ERROR, "\ Fatal error running LOAD DATA INFILE on table '%s'. Default database: '%s'", - (char*)table_name, print_slave_db_safe(db)); + (char*)table_name, print_slave_db_safe(save_db)); return 1; } @@ -2659,17 +1930,17 @@ void Rotate_log_event::pack_info(Protocol *protocol) */ #ifdef MYSQL_CLIENT -void Rotate_log_event::print(FILE* file, bool short_form, LAST_EVENT_INFO* last_event_info) +void Rotate_log_event::print(FILE* file, bool short_form, char* last_db) { char buf[22]; - if (short_form) return; + print_header(file); fprintf(file, "\tRotate to "); if (new_log_ident) my_fwrite(file, (byte*) new_log_ident, (uint)ident_len, - MYF(MY_NABP | MY_WME)); + MYF(MY_NABP | MY_WME)); fprintf(file, " pos: %s", llstr(pos, buf)); fputc('\n', file); fflush(file); @@ -2681,22 +1952,31 @@ void Rotate_log_event::print(FILE* file, bool short_form, LAST_EVENT_INFO* last_ Rotate_log_event::Rotate_log_event() */ -Rotate_log_event::Rotate_log_event(const char* buf, uint event_len, - const Format_description_log_event* description_event) - :Log_event(buf, description_event) ,new_log_ident(NULL),alloced(0) +Rotate_log_event::Rotate_log_event(const char* buf, int event_len, + bool old_format) + :Log_event(buf, old_format),new_log_ident(NULL),alloced(0) { - DBUG_ENTER("Rotate_log_event::Rotate_log_event(char*,...)"); // The caller will ensure that event_len is what we have at EVENT_LEN_OFFSET - uint8 header_size= description_event->common_header_len; - uint8 post_header_len= description_event->post_header_len[ROTATE_EVENT-1]; + int header_size = (old_format) ? OLD_HEADER_LEN : LOG_EVENT_HEADER_LEN; uint ident_offset; + DBUG_ENTER("Rotate_log_event"); + if (event_len < header_size) DBUG_VOID_RETURN; + buf += header_size; - pos = post_header_len ? uint8korr(buf + R_POS_OFFSET) : 4; - ident_len = (uint)(event_len - - (header_size+post_header_len)); - ident_offset = post_header_len; + if (old_format) + { + ident_len = (uint)(event_len - OLD_HEADER_LEN); + pos = 4; + ident_offset = 0; + } + else + { + ident_len = (uint)(event_len - ROTATE_EVENT_OVERHEAD); + pos = uint8korr(buf + R_POS_OFFSET); + ident_offset = ROTATE_HEADER_LEN; + } set_if_smaller(ident_len,FN_REFLEN-1); if (!(new_log_ident= my_strdup_with_length((byte*) buf + ident_offset, @@ -2709,31 +1989,29 @@ Rotate_log_event::Rotate_log_event(const char* buf, uint event_len, /* - Rotate_log_event::write() + Rotate_log_event::write_data() */ -bool Rotate_log_event::write(IO_CACHE* file) +int Rotate_log_event::write_data(IO_CACHE* file) { char buf[ROTATE_HEADER_LEN]; int8store(buf + R_POS_OFFSET, pos); - return (write_header(file, ROTATE_HEADER_LEN + ident_len) || - my_b_safe_write(file, (byte*)buf, ROTATE_HEADER_LEN) || - my_b_safe_write(file, (byte*)new_log_ident, (uint) ident_len)); + return (my_b_safe_write(file, (byte*)buf, ROTATE_HEADER_LEN) || + my_b_safe_write(file, (byte*)new_log_ident, (uint) ident_len)); } /* Rotate_log_event::exec_event() - Got a rotate log event from the master + Got a rotate log even from the master IMPLEMENTATION This is mainly used so that we can later figure out the logname and position for the master. - We can't rotate the slave's BINlog as this will cause infinitive rotations + We can't rotate the slave as this will cause infinitive rotations in a A -> B -> A setup. - The NOTES below is a wrong comment which will disappear when 4.1 is merged. RETURN VALUES 0 ok @@ -2745,7 +2023,7 @@ int Rotate_log_event::exec_event(struct st_relay_log_info* rli) DBUG_ENTER("Rotate_log_event::exec_event"); pthread_mutex_lock(&rli->data_lock); - rli->event_relay_log_pos= my_b_tell(rli->cur_log); + rli->event_relay_log_pos += get_event_len(); /* If we are in a transaction: the only normal case is when the I/O thread was copying a big transaction, then it was stopped and restarted: we have this @@ -2757,28 +2035,15 @@ int Rotate_log_event::exec_event(struct st_relay_log_info* rli) COMMIT or ROLLBACK In that case, we don't want to touch the coordinates which correspond to the beginning of the transaction. - Starting from 5.0.0, there also are some rotates from the slave itself, in - the relay log. */ if (!(thd->options & OPTION_BEGIN)) { memcpy(rli->group_master_log_name, new_log_ident, ident_len+1); rli->notify_group_master_log_name_update(); - rli->group_master_log_pos= pos; - rli->group_relay_log_pos= rli->event_relay_log_pos; - DBUG_PRINT("info", ("group_master_log_name: '%s' group_master_log_pos:\ -%lu", - rli->group_master_log_name, + rli->group_master_log_pos = pos; + rli->group_relay_log_pos = rli->event_relay_log_pos; + DBUG_PRINT("info", ("group_master_log_pos: %lu", (ulong) rli->group_master_log_pos)); - /* - Reset thd->options and sql_mode, because this could be the signal of a - master's downgrade from 5.0 to 4.0. - However, no need to reset description_event_for_exec: indeed, if the next - master is 5.0 (even 5.0.1) we will soon get a Format_desc; if the next - master is 4.0 then the events are in the slave's format (conversion). - */ - set_slave_thread_options(thd); - thd->variables.sql_mode= global_system_variables.sql_mode; } pthread_mutex_unlock(&rli->data_lock); pthread_cond_broadcast(&rli->data_cond); @@ -2812,13 +2077,12 @@ void Intvar_log_event::pack_info(Protocol *protocol) Intvar_log_event::Intvar_log_event() */ -Intvar_log_event::Intvar_log_event(const char* buf, - const Format_description_log_event* description_event) - :Log_event(buf, description_event) +Intvar_log_event::Intvar_log_event(const char* buf, bool old_format) + :Log_event(buf, old_format) { - buf+= description_event->common_header_len; - type= buf[I_TYPE_OFFSET]; - val= uint8korr(buf+I_VAL_OFFSET); + buf += (old_format) ? OLD_HEADER_LEN : LOG_EVENT_HEADER_LEN; + type = buf[I_TYPE_OFFSET]; + val = uint8korr(buf+I_VAL_OFFSET); } @@ -2837,16 +2101,15 @@ const char* Intvar_log_event::get_var_type_name() /* - Intvar_log_event::write() + Intvar_log_event::write_data() */ -bool Intvar_log_event::write(IO_CACHE* file) +int Intvar_log_event::write_data(IO_CACHE* file) { - byte buf[9]; - buf[I_TYPE_OFFSET]= (byte) type; + char buf[9]; + buf[I_TYPE_OFFSET] = type; int8store(buf + I_VAL_OFFSET, val); - return (write_header(file, sizeof(buf)) || - my_b_safe_write(file, buf, sizeof(buf))); + return my_b_safe_write(file, (byte*) buf, sizeof(buf)); } @@ -2855,8 +2118,7 @@ bool Intvar_log_event::write(IO_CACHE* file) */ #ifdef MYSQL_CLIENT -void Intvar_log_event::print(FILE* file, bool short_form, - LAST_EVENT_INFO* last_event_info) +void Intvar_log_event::print(FILE* file, bool short_form, char* last_db) { char llbuff[22]; const char *msg; @@ -2899,7 +2161,7 @@ int Intvar_log_event::exec_event(struct st_relay_log_info* rli) thd->next_insert_id = val; break; } - rli->inc_event_relay_log_pos(); + rli->inc_event_relay_log_pos(get_event_len()); return 0; } #endif @@ -2922,28 +2184,26 @@ void Rand_log_event::pack_info(Protocol *protocol) #endif -Rand_log_event::Rand_log_event(const char* buf, - const Format_description_log_event* description_event) - :Log_event(buf, description_event) +Rand_log_event::Rand_log_event(const char* buf, bool old_format) + :Log_event(buf, old_format) { - buf+= description_event->common_header_len; - seed1= uint8korr(buf+RAND_SEED1_OFFSET); - seed2= uint8korr(buf+RAND_SEED2_OFFSET); + buf += (old_format) ? OLD_HEADER_LEN : LOG_EVENT_HEADER_LEN; + seed1 = uint8korr(buf+RAND_SEED1_OFFSET); + seed2 = uint8korr(buf+RAND_SEED2_OFFSET); } -bool Rand_log_event::write(IO_CACHE* file) +int Rand_log_event::write_data(IO_CACHE* file) { - byte buf[16]; + char buf[16]; int8store(buf + RAND_SEED1_OFFSET, seed1); int8store(buf + RAND_SEED2_OFFSET, seed2); - return (write_header(file, sizeof(buf)) || - my_b_safe_write(file, buf, sizeof(buf))); + return my_b_safe_write(file, (byte*) buf, sizeof(buf)); } #ifdef MYSQL_CLIENT -void Rand_log_event::print(FILE* file, bool short_form, LAST_EVENT_INFO* last_event_info) +void Rand_log_event::print(FILE* file, bool short_form, char* last_db) { char llbuff[22],llbuff2[22]; if (!short_form) @@ -2963,7 +2223,7 @@ int Rand_log_event::exec_event(struct st_relay_log_info* rli) { thd->rand.seed1= (ulong) seed1; thd->rand.seed2= (ulong) seed2; - rli->inc_event_relay_log_pos(); + rli->inc_event_relay_log_pos(get_event_len()); return 0; } #endif /* !MYSQL_CLIENT */ @@ -3034,12 +2294,10 @@ void User_var_log_event::pack_info(Protocol* protocol) #endif /* !MYSQL_CLIENT */ -User_var_log_event:: -User_var_log_event(const char* buf, - const Format_description_log_event* description_event) - :Log_event(buf, description_event) +User_var_log_event::User_var_log_event(const char* buf, bool old_format) + :Log_event(buf, old_format) { - buf+= description_event->common_header_len; + buf+= (old_format) ? OLD_HEADER_LEN : LOG_EVENT_HEADER_LEN; name_len= uint4korr(buf); name= (char *) buf + UV_NAME_LEN_SIZE; buf+= UV_NAME_LEN_SIZE + name_len; @@ -3063,14 +2321,13 @@ User_var_log_event(const char* buf, } -bool User_var_log_event::write(IO_CACHE* file) +int User_var_log_event::write_data(IO_CACHE* file) { char buf[UV_NAME_LEN_SIZE]; char buf1[UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE + UV_CHARSET_NUMBER_SIZE + UV_VAL_LEN_SIZE]; char buf2[8], *pos= buf2; uint buf1_length; - ulong event_length; int4store(buf, name_len); @@ -3102,12 +2359,7 @@ bool User_var_log_event::write(IO_CACHE* file) return 0; } } - - /* Length of the whole event */ - event_length= sizeof(buf)+ name_len + buf1_length + val_len; - - return (write_header(file, event_length) || - my_b_safe_write(file, (byte*) buf, sizeof(buf)) || + return (my_b_safe_write(file, (byte*) buf, sizeof(buf)) || my_b_safe_write(file, (byte*) name, name_len) || my_b_safe_write(file, (byte*) buf1, buf1_length) || my_b_safe_write(file, (byte*) pos, val_len)); @@ -3119,7 +2371,7 @@ bool User_var_log_event::write(IO_CACHE* file) */ #ifdef MYSQL_CLIENT -void User_var_log_event::print(FILE* file, bool short_form, LAST_EVENT_INFO* last_event_info) +void User_var_log_event::print(FILE* file, bool short_form, char* last_db) { if (!short_form) { @@ -3252,7 +2504,7 @@ int User_var_log_event::exec_event(struct st_relay_log_info* rli) e.update_hash(val, val_len, type, charset, DERIVATION_NONE); free_root(thd->mem_root,0); - rli->inc_event_relay_log_pos(); + rli->inc_event_relay_log_pos(get_event_len()); return 0; } #endif /* !MYSQL_CLIENT */ @@ -3264,7 +2516,7 @@ int User_var_log_event::exec_event(struct st_relay_log_info* rli) #ifdef HAVE_REPLICATION #ifdef MYSQL_CLIENT -void Unknown_log_event::print(FILE* file, bool short_form, LAST_EVENT_INFO* last_event_info) +void Unknown_log_event::print(FILE* file, bool short_form, char* last_db) { if (short_form) return; @@ -3294,7 +2546,7 @@ void Slave_log_event::pack_info(Protocol *protocol) #ifndef MYSQL_CLIENT Slave_log_event::Slave_log_event(THD* thd_arg, struct st_relay_log_info* rli) - :Log_event(thd_arg, 0, 0) , mem_pool(0), master_host(0) + :Log_event(thd_arg, 0, 0), mem_pool(0), master_host(0) { DBUG_ENTER("Slave_log_event"); if (!rli->inited) // QQ When can this happen ? @@ -3335,7 +2587,7 @@ Slave_log_event::~Slave_log_event() #ifdef MYSQL_CLIENT -void Slave_log_event::print(FILE* file, bool short_form, LAST_EVENT_INFO* last_event_info) +void Slave_log_event::print(FILE* file, bool short_form, char* last_db) { char llbuff[22]; if (short_form) @@ -3355,15 +2607,12 @@ int Slave_log_event::get_data_size() } -bool Slave_log_event::write(IO_CACHE* file) +int Slave_log_event::write_data(IO_CACHE* file) { - ulong event_length= get_data_size(); int8store(mem_pool + SL_MASTER_POS_OFFSET, master_pos); int2store(mem_pool + SL_MASTER_PORT_OFFSET, master_port); // log and host are already there - - return (write_header(file, event_length) || - my_b_safe_write(file, (byte*) mem_pool, event_length)); + return my_b_safe_write(file, (byte*)mem_pool, get_data_size()); } @@ -3384,13 +2633,12 @@ void Slave_log_event::init_from_mem_pool(int data_size) } -/* This code is not used, so has not been updated to be format-tolerant */ -Slave_log_event::Slave_log_event(const char* buf, uint event_len) - :Log_event(buf,0) /*unused event*/ ,mem_pool(0),master_host(0) +Slave_log_event::Slave_log_event(const char* buf, int event_len) + :Log_event(buf,0),mem_pool(0),master_host(0) { - if (event_len < LOG_EVENT_HEADER_LEN) - return; event_len -= LOG_EVENT_HEADER_LEN; + if (event_len < 0) + return; if (!(mem_pool = (char*) my_malloc(event_len + 1, MYF(MY_WME)))) return; memcpy(mem_pool, buf + LOG_EVENT_HEADER_LEN, event_len); @@ -3418,7 +2666,7 @@ int Slave_log_event::exec_event(struct st_relay_log_info* rli) */ #ifdef MYSQL_CLIENT -void Stop_log_event::print(FILE* file, bool short_form, LAST_EVENT_INFO* last_event_info) +void Stop_log_event::print(FILE* file, bool short_form, char* last_db) { if (short_form) return; @@ -3440,7 +2688,7 @@ void Stop_log_event::print(FILE* file, bool short_form, LAST_EVENT_INFO* last_ev We used to clean up slave_load_tmpdir, but this is useless as it has been cleared at the end of LOAD DATA INFILE. So we have nothing to do here. - The place were we must do this cleaning is in Start_log_event_v3::exec_event(), + The place were we must do this cleaning is in Start_log_event::exec_event(), not here. Because if we come here, the master was sane. */ @@ -3454,13 +2702,8 @@ int Stop_log_event::exec_event(struct st_relay_log_info* rli) could give false triggers in MASTER_POS_WAIT() that we have reached the target position when in fact we have not. */ - if (thd->options & OPTION_BEGIN) - rli->inc_event_relay_log_pos(); - else - { - rli->inc_group_relay_log_pos(0); - flush_relay_log_info(rli); - } + rli->inc_group_relay_log_pos(get_event_len(), 0); + flush_relay_log_info(rli); return 0; } #endif /* !MYSQL_CLIENT */ @@ -3497,13 +2740,13 @@ Create_file_log_event(THD* thd_arg, sql_exchange* ex, Create_file_log_event::write_data_body() */ -bool Create_file_log_event::write_data_body(IO_CACHE* file) +int Create_file_log_event::write_data_body(IO_CACHE* file) { - bool res; - if ((res= Load_log_event::write_data_body(file)) || fake_base) + int res; + if ((res = Load_log_event::write_data_body(file)) || fake_base) return res; return (my_b_safe_write(file, (byte*) "", 1) || - my_b_safe_write(file, (byte*) block, block_len)); + my_b_safe_write(file, (byte*) block, block_len)); } @@ -3511,14 +2754,14 @@ bool Create_file_log_event::write_data_body(IO_CACHE* file) Create_file_log_event::write_data_header() */ -bool Create_file_log_event::write_data_header(IO_CACHE* file) +int Create_file_log_event::write_data_header(IO_CACHE* file) { - bool res; - byte buf[CREATE_FILE_HEADER_LEN]; - if ((res= Load_log_event::write_data_header(file)) || fake_base) + int res; + if ((res = Load_log_event::write_data_header(file)) || fake_base) return res; + byte buf[CREATE_FILE_HEADER_LEN]; int4store(buf + CF_FILE_ID_OFFSET, file_id); - return my_b_safe_write(file, buf, CREATE_FILE_HEADER_LEN) != 0; + return my_b_safe_write(file, buf, CREATE_FILE_HEADER_LEN); } @@ -3526,12 +2769,12 @@ bool Create_file_log_event::write_data_header(IO_CACHE* file) Create_file_log_event::write_base() */ -bool Create_file_log_event::write_base(IO_CACHE* file) +int Create_file_log_event::write_base(IO_CACHE* file) { - bool res; - fake_base= 1; // pretend we are Load event - res= write(file); - fake_base= 0; + int res; + fake_base = 1; // pretend we are Load event + res = write(file); + fake_base = 0; return res; } @@ -3540,43 +2783,28 @@ bool Create_file_log_event::write_base(IO_CACHE* file) Create_file_log_event ctor */ -Create_file_log_event::Create_file_log_event(const char* buf, uint len, - const Format_description_log_event* description_event) - :Load_log_event(buf,0,description_event),fake_base(0),block(0),inited_from_old(0) +Create_file_log_event::Create_file_log_event(const char* buf, int len, + bool old_format) + :Load_log_event(buf,0,old_format),fake_base(0),block(0),inited_from_old(0) { - DBUG_ENTER("Create_file_log_event::Create_file_log_event(char*,...)"); - uint block_offset; - uint header_len= description_event->common_header_len; - uint8 load_header_len= description_event->post_header_len[LOAD_EVENT-1]; - uint8 create_file_header_len= description_event->post_header_len[CREATE_FILE_EVENT-1]; + int block_offset; + DBUG_ENTER("Create_file_log_event"); + + /* + We must make copy of 'buf' as this event may have to live over a + rotate log entry when used in mysqlbinlog + */ if (!(event_buf= my_memdup((byte*) buf, len, MYF(MY_WME))) || - copy_log_event(event_buf,len, - ((buf[EVENT_TYPE_OFFSET] == LOAD_EVENT) ? - load_header_len + header_len : - (fake_base ? (header_len+load_header_len) : - (header_len+load_header_len) + - create_file_header_len)), - description_event)) + (copy_log_event(event_buf, len, old_format))) DBUG_VOID_RETURN; - if (description_event->binlog_version!=1) + + if (!old_format) { - file_id= uint4korr(buf + - header_len + - load_header_len + CF_FILE_ID_OFFSET); - /* - Note that it's ok to use get_data_size() below, because it is computed - with values we have already read from this event (because we called - copy_log_event()); we are not using slave's format info to decode - master's format, we are really using master's format info. - Anyway, both formats should be identical (except the common_header_len) - as these Load events are not changed between 4.0 and 5.0 (as logging of - LOAD DATA INFILE does not use Load_log_event in 5.0). - - The + 1 is for \0 terminating fname - */ - block_offset= (description_event->common_header_len + - Load_log_event::get_data_size() + - create_file_header_len + 1); + file_id = uint4korr(buf + LOG_EVENT_HEADER_LEN + + + LOAD_HEADER_LEN + CF_FILE_ID_OFFSET); + // + 1 for \0 terminating fname + block_offset = (LOG_EVENT_HEADER_LEN + Load_log_event::get_data_size() + + CREATE_FILE_HEADER_LEN + 1); if (len < block_offset) return; block = (char*)buf + block_offset; @@ -3597,18 +2825,18 @@ Create_file_log_event::Create_file_log_event(const char* buf, uint len, #ifdef MYSQL_CLIENT void Create_file_log_event::print(FILE* file, bool short_form, - LAST_EVENT_INFO* last_event_info, bool enable_local) + char* last_db, bool enable_local) { if (short_form) { if (enable_local && check_fname_outside_temp_buf()) - Load_log_event::print(file, 1, last_event_info); + Load_log_event::print(file, 1, last_db); return; } if (enable_local) { - Load_log_event::print(file, 1, last_event_info, !check_fname_outside_temp_buf()); + Load_log_event::print(file, 1, last_db, !check_fname_outside_temp_buf()); /* That one is for "file_id: etc" below: in mysqlbinlog we want the #, in SHOW BINLOG EVENTS we don't. @@ -3621,9 +2849,9 @@ void Create_file_log_event::print(FILE* file, bool short_form, void Create_file_log_event::print(FILE* file, bool short_form, - LAST_EVENT_INFO* last_event_info) + char* last_db) { - print(file,short_form,last_event_info,0); + print(file,short_form,last_db,0); } #endif /* MYSQL_CLIENT */ @@ -3740,34 +2968,28 @@ Append_block_log_event::Append_block_log_event(THD* thd_arg, const char* db_arg, Append_block_log_event ctor */ -Append_block_log_event::Append_block_log_event(const char* buf, uint len, - const Format_description_log_event* description_event) - :Log_event(buf, description_event),block(0) +Append_block_log_event::Append_block_log_event(const char* buf, int len) + :Log_event(buf, 0),block(0) { - DBUG_ENTER("Append_block_log_event::Append_block_log_event(char*,...)"); - uint8 common_header_len= description_event->common_header_len; - uint8 append_block_header_len= - description_event->post_header_len[APPEND_BLOCK_EVENT-1]; - uint total_header_len= common_header_len+append_block_header_len; - if (len < total_header_len) + DBUG_ENTER("Append_block_log_event"); + if ((uint)len < APPEND_BLOCK_EVENT_OVERHEAD) DBUG_VOID_RETURN; - file_id= uint4korr(buf + common_header_len + AB_FILE_ID_OFFSET); - block= (char*)buf + total_header_len; - block_len= len - total_header_len; + file_id = uint4korr(buf + LOG_EVENT_HEADER_LEN + AB_FILE_ID_OFFSET); + block = (char*)buf + APPEND_BLOCK_EVENT_OVERHEAD; + block_len = len - APPEND_BLOCK_EVENT_OVERHEAD; DBUG_VOID_RETURN; } /* - Append_block_log_event::write() + Append_block_log_event::write_data() */ -bool Append_block_log_event::write(IO_CACHE* file) +int Append_block_log_event::write_data(IO_CACHE* file) { byte buf[APPEND_BLOCK_HEADER_LEN]; int4store(buf + AB_FILE_ID_OFFSET, file_id); - return (write_header(file, APPEND_BLOCK_HEADER_LEN + block_len) || - my_b_safe_write(file, buf, APPEND_BLOCK_HEADER_LEN) || + return (my_b_safe_write(file, buf, APPEND_BLOCK_HEADER_LEN) || my_b_safe_write(file, (byte*) block, block_len)); } @@ -3778,7 +3000,7 @@ bool Append_block_log_event::write(IO_CACHE* file) #ifdef MYSQL_CLIENT void Append_block_log_event::print(FILE* file, bool short_form, - LAST_EVENT_INFO* last_event_info) + char* last_db) { if (short_form) return; @@ -3864,28 +3086,24 @@ Delete_file_log_event::Delete_file_log_event(THD *thd_arg, const char* db_arg, Delete_file_log_event ctor */ -Delete_file_log_event::Delete_file_log_event(const char* buf, uint len, - const Format_description_log_event* description_event) - :Log_event(buf, description_event),file_id(0) +Delete_file_log_event::Delete_file_log_event(const char* buf, int len) + :Log_event(buf, 0),file_id(0) { - uint8 common_header_len= description_event->common_header_len; - uint8 delete_file_header_len= description_event->post_header_len[DELETE_FILE_EVENT-1]; - if (len < (uint)(common_header_len + delete_file_header_len)) + if ((uint)len < DELETE_FILE_EVENT_OVERHEAD) return; - file_id= uint4korr(buf + common_header_len + DF_FILE_ID_OFFSET); + file_id = uint4korr(buf + LOG_EVENT_HEADER_LEN + AB_FILE_ID_OFFSET); } /* - Delete_file_log_event::write() + Delete_file_log_event::write_data() */ -bool Delete_file_log_event::write(IO_CACHE* file) +int Delete_file_log_event::write_data(IO_CACHE* file) { byte buf[DELETE_FILE_HEADER_LEN]; int4store(buf + DF_FILE_ID_OFFSET, file_id); - return (write_header(file, sizeof(buf)) || - my_b_safe_write(file, buf, sizeof(buf))); + return my_b_safe_write(file, buf, DELETE_FILE_HEADER_LEN); } @@ -3895,7 +3113,7 @@ bool Delete_file_log_event::write(IO_CACHE* file) #ifdef MYSQL_CLIENT void Delete_file_log_event::print(FILE* file, bool short_form, - LAST_EVENT_INFO* last_event_info) + char* last_db) { if (short_form) return; @@ -3958,28 +3176,24 @@ Execute_load_log_event::Execute_load_log_event(THD *thd_arg, const char* db_arg, Execute_load_log_event ctor */ -Execute_load_log_event::Execute_load_log_event(const char* buf, uint len, - const Format_description_log_event* description_event) - :Log_event(buf, description_event), file_id(0) +Execute_load_log_event::Execute_load_log_event(const char* buf, int len) + :Log_event(buf, 0), file_id(0) { - uint8 common_header_len= description_event->common_header_len; - uint8 exec_load_header_len= description_event->post_header_len[EXEC_LOAD_EVENT-1]; - if (len < (uint)(common_header_len+exec_load_header_len)) + if ((uint)len < EXEC_LOAD_EVENT_OVERHEAD) return; - file_id= uint4korr(buf + common_header_len + EL_FILE_ID_OFFSET); + file_id = uint4korr(buf + LOG_EVENT_HEADER_LEN + EL_FILE_ID_OFFSET); } /* - Execute_load_log_event::write() + Execute_load_log_event::write_data() */ -bool Execute_load_log_event::write(IO_CACHE* file) +int Execute_load_log_event::write_data(IO_CACHE* file) { byte buf[EXEC_LOAD_HEADER_LEN]; int4store(buf + EL_FILE_ID_OFFSET, file_id); - return (write_header(file, sizeof(buf)) || - my_b_safe_write(file, buf, sizeof(buf))); + return my_b_safe_write(file, buf, EXEC_LOAD_HEADER_LEN); } @@ -3989,7 +3203,7 @@ bool Execute_load_log_event::write(IO_CACHE* file) #ifdef MYSQL_CLIENT void Execute_load_log_event::print(FILE* file, bool short_form, - LAST_EVENT_INFO* last_event_info) + char* last_db) { if (short_form) return; @@ -4036,8 +3250,8 @@ int Execute_load_log_event::exec_event(struct st_relay_log_info* rli) goto err; } if (!(lev = (Load_log_event*)Log_event::read_log_event(&file, - (pthread_mutex_t*)0, - rli->relay_log.description_event_for_exec)) || + (pthread_mutex_t*)0, + (bool)0)) || lev->get_type_code() != NEW_LOAD_EVENT) { slave_print_error(rli,0, "Error in Exec_load event: file '%s' appears corrupted", fname); @@ -4052,7 +3266,15 @@ int Execute_load_log_event::exec_event(struct st_relay_log_info* rli) mysql_load()). */ - rli->future_group_master_log_pos= log_pos; +#if MYSQL_VERSION_ID < 40100 + rli->future_master_log_pos= log_pos + get_event_len() - + (rli->mi->old_format ? (LOG_EVENT_HEADER_LEN - OLD_HEADER_LEN) : 0); +#elif MYSQL_VERSION_ID < 50000 + rli->future_group_master_log_pos= log_pos + get_event_len() - + (rli->mi->old_format ? (LOG_EVENT_HEADER_LEN - OLD_HEADER_LEN) : 0); +#else + rli->future_group_master_log_pos= log_pos; +#endif if (lev->exec_event(0,rli,1)) { /* @@ -4110,15 +3332,15 @@ err: sql_ex_info::write_data() */ -bool sql_ex_info::write_data(IO_CACHE* file) +int sql_ex_info::write_data(IO_CACHE* file) { if (new_format()) { - return (write_str(file, field_term, (uint) field_term_len) || - write_str(file, enclosed, (uint) enclosed_len) || - write_str(file, line_term, (uint) line_term_len) || - write_str(file, line_start, (uint) line_start_len) || - write_str(file, escaped, (uint) escaped_len) || + return (write_str(file, field_term, field_term_len) || + write_str(file, enclosed, enclosed_len) || + write_str(file, line_term, line_term_len) || + write_str(file, line_start, line_start_len) || + write_str(file, escaped, escaped_len) || my_b_safe_write(file,(byte*) &opt_flags,1)); } else @@ -4131,7 +3353,7 @@ bool sql_ex_info::write_data(IO_CACHE* file) old_ex.escaped= *escaped; old_ex.opt_flags= opt_flags; old_ex.empty_flags=empty_flags; - return my_b_safe_write(file, (byte*) &old_ex, sizeof(old_ex)) != 0; + return my_b_safe_write(file, (byte*) &old_ex, sizeof(old_ex)); } } @@ -4153,11 +3375,11 @@ char* sql_ex_info::init(char* buf,char* buf_end,bool use_new_format) the case when we have old format because we will be reusing net buffer to read the actual file before we write out the Create_file event. */ - if (read_str(&buf, buf_end, &field_term, &field_term_len) || - read_str(&buf, buf_end, &enclosed, &enclosed_len) || - read_str(&buf, buf_end, &line_term, &line_term_len) || - read_str(&buf, buf_end, &line_start, &line_start_len) || - read_str(&buf, buf_end, &escaped, &escaped_len)) + if (read_str(buf, buf_end, field_term, field_term_len) || + read_str(buf, buf_end, enclosed, enclosed_len) || + read_str(buf, buf_end, line_term, line_term_len) || + read_str(buf, buf_end, line_start, line_start_len) || + read_str(buf, buf_end, escaped, escaped_len)) return 0; opt_flags = *buf++; } diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 196b7af46b1..675f57c4ea5 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -543,7 +543,7 @@ static void close_connections(void) struct timespec abstime; int error; LINT_INIT(error); - DBUG_PRINT("info",("Waiting for select_thread")); + DBUG_PRINT("info",("Waiting for select thread")); #ifndef DONT_USE_THR_ALARM if (pthread_kill(select_thread,THR_CLIENT_ALARM)) diff --git a/sql/slave.cc b/sql/slave.cc index 88dffbd8411..b25bdb7e926 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1150,7 +1150,7 @@ bool net_request_file(NET* net, const char* fname) } -const char *rewrite_db(const char* db) +const char *rewrite_db(const char* db, uint *new_len) { if (replicate_rewrite_db.is_empty() || !db) return db; @@ -1160,7 +1160,10 @@ const char *rewrite_db(const char* db) while ((tmp=it++)) { if (!strcmp(tmp->key, db)) + { + *new_len= strlen(tmp->val); return tmp->val; + } } return db; } @@ -1174,7 +1177,7 @@ const char *rewrite_db(const char* db) const char *print_slave_db_safe(const char* db) { - return (db ? rewrite_db(db) : ""); + return (db ? db : ""); } /* @@ -2829,7 +2832,7 @@ static int request_dump(MYSQL* mysql, MASTER_INFO* mi, DBUG_ENTER("request_dump"); // TODO if big log files: Change next to int8store() - int4store(buf, (longlong) mi->master_log_pos); + int4store(buf, (ulong) mi->master_log_pos); int2store(buf + 4, binlog_flags); int4store(buf + 6, server_id); len = (uint) strlen(logname); diff --git a/sql/slave.h b/sql/slave.h index 2a9b96b75a1..b8ff86cf301 100644 --- a/sql/slave.h +++ b/sql/slave.h @@ -508,8 +508,8 @@ int add_table_rule(HASH* h, const char* table_spec); int add_wild_table_rule(DYNAMIC_ARRAY* a, const char* table_spec); void init_table_rule_hash(HASH* h, bool* h_inited); void init_table_rule_array(DYNAMIC_ARRAY* a, bool* a_inited); -const char *rewrite_db(const char* db); -const char *print_slave_db_safe(const char* db); +const char *rewrite_db(const char* db, uint *new_db_len); +const char *print_slave_db_safe(const char *db); int check_expected_error(THD* thd, RELAY_LOG_INFO* rli, int error_code); void skip_load_data_infile(NET* net); void slave_print_error(RELAY_LOG_INFO* rli, int err_code, const char* msg, ...); diff --git a/sql/sql_class.h b/sql/sql_class.h index f820f8b9cb9..85a18b10671 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -153,7 +153,7 @@ public: DBUG_VOID_RETURN; } void set_max_size(ulong max_size_arg); - void signal_update() { pthread_cond_broadcast(&update_cond);} + void signal_update(); void wait_for_update(THD* thd, bool master_or_slave); void set_need_start_event() { need_start_event = 1; } void init(enum_log_type log_type_arg, diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 7a100d05b93..ad74bb8f833 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -31,11 +31,6 @@ const char *del_exts[]= {".frm", ".BAK", ".TMD",".opt", NullS}; static TYPELIB deletable_extentions= {array_elements(del_exts)-1,"del_exts", del_exts, NULL}; -const char *known_exts[]= -{".ISM",".ISD",".ISM",".MRG",".MYI",".MYD",".db", ".ibd", NullS}; -static TYPELIB known_extentions= -{array_elements(known_exts)-1,"known_exts", known_exts, NULL}; - static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db, const char *path, uint level); @@ -755,7 +750,7 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db, extension= fn_ext(file->name); if (find_type(extension, &deletable_extentions,1+2) <= 0) { - if (find_type(extension, &known_extentions,1+2) <= 0) + if (find_type(extension, ha_known_exts(),1+2) <= 0) found_other_files++; continue; } diff --git a/sql/sql_lex.h b/sql/sql_lex.h index c8b4faa47c2..fd1c1dee0b7 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -706,7 +706,7 @@ typedef struct st_lex uint uint_geom_type; uint grant, grant_tot_col, which_columns; uint fk_delete_opt, fk_update_opt, fk_match_option; - uint slave_thd_opt; + uint slave_thd_opt, start_transaction_opt; uint8 describe; uint8 derived_tables; uint8 create_view_algorithm; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index a14a3da8391..9d755731cb7 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -26,9 +26,6 @@ #include "ha_innodb.h" #endif -#include "sp_head.h" -#include "sp.h" - #ifdef HAVE_OPENSSL /* Without SSL the handshake consists of one packet. This packet @@ -47,15 +44,6 @@ #define MIN_HANDSHAKE_SIZE 6 #endif /* HAVE_OPENSSL */ -/* Used in error handling only */ -#define SP_TYPE_STRING(LP) \ - ((LP)->sphead->m_type == TYPE_ENUM_FUNCTION ? "FUNCTION" : "PROCEDURE") -#define SP_COM_STRING(LP) \ - ((LP)->sql_command == SQLCOM_CREATE_SPFUNCTION || \ - (LP)->sql_command == SQLCOM_ALTER_FUNCTION || \ - (LP)->sql_command == SQLCOM_DROP_FUNCTION ? \ - "FUNCTION" : "PROCEDURE") - #ifdef SOLARIS extern "C" int gethostname(char *name, int namelen); #endif @@ -69,7 +57,6 @@ static void remove_escape(char *name); static void refresh_status(void); static bool append_file_to_dir(THD *thd, const char **filename_ptr, const char *table_name); -static bool check_sp_definer_access(THD *thd, sp_head *sp); const char *any_db="*any*"; // Special symbol for check_access @@ -79,7 +66,7 @@ const char *command_name[]={ "Connect","Kill","Debug","Ping","Time","Delayed insert","Change user", "Binlog Dump","Table Dump", "Connect Out", "Register Slave", "Prepare", "Prepare Execute", "Long Data", "Close stmt", - "Reset stmt", "Set option", "Fetch", + "Reset stmt", "Set option", "Error" // Last command number }; @@ -109,7 +96,7 @@ static void unlock_locked_tables(THD *thd) if (thd->locked_tables) { thd->lock=thd->locked_tables; - thd->locked_tables=0; // Will be automatically closed + thd->locked_tables=0; // Will be automaticly closed close_thread_tables(thd); // Free tables } } @@ -206,13 +193,13 @@ end: command originator of the check: now check_user is called during connect and change user procedures; used for logging. - passwd scrambled password received from client + passwd scrambled password recieved from client passwd_len length of scrambled password db database name to connect to, may be NULL check_count dont know exactly Note, that host, user and passwd may point to communication buffer. - Current implementation does not depend on that, but future changes + Current implementation does not depened on that, but future changes should be done with this in mind; 'thd' is INOUT, all other params are 'IN'. @@ -270,7 +257,7 @@ int check_user(THD *thd, enum enum_server_command command, /* Clear thd->db as it points to something, that will be freed when - connection is closed. We don't want to accidentally free a wrong pointer + connection is closed. We don't want to accidently free a wrong pointer if connect failed. Also in case of 'CHANGE USER' failure, current database will be switched to 'no database selected'. */ @@ -297,10 +284,9 @@ int check_user(THD *thd, enum enum_server_command command, thd->user, thd->host_or_ip); DBUG_RETURN(-1); } - /* We have to read very specific packet size */ if (send_old_password_request(thd) || - my_net_read(net) != SCRAMBLE_LENGTH_323 + 1) - { + my_net_read(net) != SCRAMBLE_LENGTH_323 + 1) // We have to read very + { // specific packet size inc_host_errors(&thd->remote.sin_addr); DBUG_RETURN(ER_HANDSHAKE_ERROR); } @@ -312,7 +298,7 @@ int check_user(THD *thd, enum enum_server_command command, /* here res is always >= 0 */ if (res == 0) { - if (!(thd->master_access & NO_ACCESS)) // authentication is OK + if (!(thd->master_access & NO_ACCESS)) // authentification is OK { DBUG_PRINT("info", ("Capabilities: %d packet_length: %ld Host: '%s' " @@ -547,8 +533,6 @@ void init_update_queries(void) uc_update_queries[SQLCOM_DELETE_MULTI]=1; uc_update_queries[SQLCOM_DROP_INDEX]=1; uc_update_queries[SQLCOM_UPDATE_MULTI]=1; - uc_update_queries[SQLCOM_CREATE_VIEW]=1; - uc_update_queries[SQLCOM_DROP_VIEW]=1; } bool is_update_query(enum enum_sql_command command) @@ -637,9 +621,8 @@ static void reset_mqh(THD *thd, LEX_USER *lu, bool get_them= 0) uc->conn_per_hour=0; } } - else + else // for FLUSH PRIVILEGES and FLUSH USER_RESOURCES { - /* for FLUSH PRIVILEGES and FLUSH USER_RESOURCES */ for (uint idx=0;idx < hash_user_connections.records; idx++) { USER_CONN *uc=(struct user_conn *) hash_element(&hash_user_connections, @@ -738,7 +721,7 @@ static int check_connection(THD *thd) #endif /* HAVE_COMPRESS */ #ifdef HAVE_OPENSSL if (ssl_acceptor_fd) - client_flags |= CLIENT_SSL; /* Wow, SSL is available! */ + client_flags |= CLIENT_SSL; /* Wow, SSL is avalaible! */ #endif /* HAVE_OPENSSL */ end= strnmov(buff, server_version, SERVER_VERSION_LENGTH) + 1; @@ -965,7 +948,7 @@ pthread_handler_decl(handle_one_connection,arg) pthread_detach_this_thread(); #if !defined( __WIN__) && !defined(OS2) // Win32 calls this in pthread_create - /* The following calls needs to be done before we call DBUG_ macros */ + // The following calls needs to be done before we call DBUG_ macros if (!(test_flags & TEST_NO_THREADS) & my_thread_init()) { close_connection(thd, ER_OUT_OF_RESOURCES, 1); @@ -984,7 +967,7 @@ pthread_handler_decl(handle_one_connection,arg) */ DBUG_PRINT("info", ("handle_one_connection called by thread %d\n", thd->thread_id)); - /* now that we've called my_thread_init(), it is safe to call DBUG_* */ + // now that we've called my_thread_init(), it is safe to call DBUG_* #if defined(__WIN__) init_signals(); // IRENA; testing ? @@ -1030,28 +1013,24 @@ pthread_handler_decl(handle_one_connection,arg) thd->proc_info= 0; thd->set_time(); thd->init_for_queries(); - if (sys_init_connect.value_length && !(thd->master_access & SUPER_ACL)) { execute_init_command(thd, &sys_init_connect, &LOCK_sys_init_connect); if (thd->query_error) - thd->killed= THD::KILL_CONNECTION; + thd->killed= 1; } - - thd->proc_info=0; - thd->set_time(); - thd->init_for_queries(); - while (!net->error && net->vio != 0 && !(thd->killed == THD::KILL_CONNECTION)) + while (!net->error && net->vio != 0 && !thd->killed) { if (do_command(thd)) break; } if (thd->user_connect) decrease_user_connections(thd->user_connect); + free_root(thd->mem_root,MYF(0)); if (net->error && net->vio != 0 && net->report_error) { if (!thd->killed && thd->variables.log_warnings > 1) - sql_print_warning(ER(ER_NEW_ABORTING_CONNECTION), + sql_print_warning(ER(ER_NEW_ABORTING_CONNECTION), thd->thread_id,(thd->db ? thd->db : "unconnected"), thd->user ? thd->user : "unauthenticated", thd->host_or_ip, @@ -1137,10 +1116,6 @@ extern "C" pthread_handler_decl(handle_bootstrap,arg) thd->query_length=length; thd->query= thd->memdup_w_gap(buff, length+1, thd->db_length+1); thd->query[length] = '\0'; - /* - We don't need to obtain LOCK_thread_count here because in bootstrap - mode we have only one thread. - */ thd->query_id=query_id++; if (mqh_used && thd->user_connect && check_mqh(thd, SQLCOM_END)) { @@ -1174,10 +1149,8 @@ end: void free_items(Item *item) { - DBUG_ENTER("free_items"); for (; item ; item=item->next) item->delete_self(); - DBUG_VOID_RETURN; } /* This works because items are allocated with sql_alloc() */ @@ -1197,10 +1170,10 @@ int mysql_table_dump(THD* thd, char* db, char* tbl_name, int fd) db = (db && db[0]) ? db : thd->db; if (!(table_list = (TABLE_LIST*) thd->calloc(sizeof(TABLE_LIST)))) DBUG_RETURN(1); // out of memory - table_list->db= db; - table_list->real_name= table_list->alias= tbl_name; - table_list->lock_type= TL_READ_NO_INSERT; - table_list->prev_global= &table_list; // can be removed after merge with 4.1 + table_list->db = db; + table_list->real_name = table_list->alias = tbl_name; + table_list->lock_type = TL_READ_NO_INSERT; + table_list->next = 0; if (!db || check_db_name(db)) { @@ -1264,7 +1237,7 @@ bool do_command(THD *thd) packet=0; old_timeout=net->read_timeout; - /* Wait max for 8 hours */ + // Wait max for 8 hours net->read_timeout=(uint) thd->variables.net_wait_timeout; thd->clear_error(); // Clear error message @@ -1286,9 +1259,6 @@ bool do_command(THD *thd) } else { - if (thd->killed == THD::KILL_QUERY || thd->killed == THD::KILL_BAD_DATA) - thd->killed= THD::NOT_KILLED; - packet=(char*) net->read_pos; command = (enum enum_server_command) (uchar) packet[0]; if (command >= COM_END) @@ -1340,7 +1310,6 @@ bool dispatch_command(enum enum_server_command command, THD *thd, this so that they will not get logged to the slow query log */ thd->slow_command=FALSE; - thd->lex->sql_command= SQLCOM_END; /* to avoid confusing VIEW detectors */ thd->set_time(); VOID(pthread_mutex_lock(&LOCK_thread_count)); thd->query_id=query_id; @@ -1356,8 +1325,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, case COM_INIT_DB: { LEX_STRING tmp; - statistic_increment(thd->status_var.com_stat[SQLCOM_CHANGE_DB], - &LOCK_status); + statistic_increment(com_stat[SQLCOM_CHANGE_DB],&LOCK_status); thd->convert_string(&tmp, system_charset_info, packet, strlen(packet), thd->charset()); if (!mysql_change_db(thd, tmp.str)) @@ -1378,7 +1346,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, uint db_len= *(uchar*) packet; uint tbl_len= *(uchar*) (packet + db_len + 1); - statistic_increment(thd->status_var.com_other, &LOCK_status); + statistic_increment(com_other, &LOCK_status); thd->slow_command= TRUE; db= thd->alloc(db_len + tbl_len + 2); tbl_name= strmake(db, packet + 1, db_len)+1; @@ -1392,7 +1360,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, thd->change_user(); thd->clear_error(); // if errors from rollback - statistic_increment(thd->status_var.com_other, &LOCK_status); + statistic_increment(com_other, &LOCK_status); char *user= (char*) packet; char *passwd= strend(user)+1; /* @@ -1406,7 +1374,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, *passwd++ : strlen(passwd); db+= passwd_len + 1; #ifndef EMBEDDED_LIBRARY - /* Small check for incoming packet */ + /* Small check for incomming packet */ if ((uint) ((uchar*) db - net->read_pos) > packet_length) { send_error(thd, ER_UNKNOWN_COM_ERROR); @@ -1442,7 +1410,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, if (res) { - /* authentication failure, we shall restore old user */ + /* authentification failure, we shall restore old user */ if (res > 0) send_error(thd, ER_UNKNOWN_COM_ERROR); x_free(thd->user); @@ -1469,11 +1437,6 @@ bool dispatch_command(enum enum_server_command command, THD *thd, mysql_stmt_execute(thd, packet, packet_length); break; } - case COM_FETCH: - { - mysql_stmt_fetch(thd, packet, packet_length); - break; - } case COM_LONG_DATA: { mysql_stmt_get_longdata(thd, packet, packet_length); @@ -1560,20 +1523,20 @@ bool dispatch_command(enum enum_server_command command, THD *thd, TABLE_LIST table_list; LEX_STRING conv_name; - statistic_increment(thd->status_var.com_stat[SQLCOM_SHOW_FIELDS], - &LOCK_status); + statistic_increment(com_stat[SQLCOM_SHOW_FIELDS],&LOCK_status); bzero((char*) &table_list,sizeof(table_list)); if (!(table_list.db=thd->db)) { send_error(thd,ER_NO_DB_ERROR); break; } + thd->free_list=0; pend= strend(packet); thd->convert_string(&conv_name, system_charset_info, packet, (uint) (pend-packet), thd->charset()); table_list.alias= table_list.real_name= conv_name.str; packet= pend+1; - /* command not cachable => no gap for data base name */ + // command not cachable => no gap for data base name if (!(thd->query=fields=thd->memdup(packet,thd->query_length+1))) break; mysql_log.write(thd,command,"%s %s",table_list.real_name,fields); @@ -1587,18 +1550,9 @@ bool dispatch_command(enum enum_server_command command, THD *thd, if (grant_option && check_grant(thd, SELECT_ACL, &table_list, 2, UINT_MAX, 0)) break; - /* init structures for VIEW processing */ - table_list.select_lex= &(thd->lex->select_lex); - mysql_init_query(thd, (uchar*)"", 0); - thd->lex-> - select_lex.table_list.link_in_list((byte*) &table_list, - (byte**) &table_list.next_local); - - /* switch on VIEW optimisation: do not fill temporary tables */ - thd->lex->sql_command= SQLCOM_SHOW_FIELDS; mysqld_list_fields(thd,&table_list,fields); - thd->lex->unit.cleanup(); - thd->cleanup_after_query(); + free_items(thd->free_list); + thd->free_list= 0; break; } #endif @@ -1614,8 +1568,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, char *db=thd->strdup(packet), *alias; HA_CREATE_INFO create_info; - statistic_increment(thd->status_var.com_stat[SQLCOM_CREATE_DB], - &LOCK_status); + statistic_increment(com_stat[SQLCOM_CREATE_DB],&LOCK_status); // null test to handle EOM if (!db || !(alias= thd->strdup(db)) || check_db_name(db)) { @@ -1633,10 +1586,9 @@ bool dispatch_command(enum enum_server_command command, THD *thd, } case COM_DROP_DB: // QQ: To be removed { - statistic_increment(thd->status_var.com_stat[SQLCOM_DROP_DB], - &LOCK_status); + statistic_increment(com_stat[SQLCOM_DROP_DB],&LOCK_status); char *db=thd->strdup(packet), *alias; - /* null test to handle EOM */ + // null test to handle EOM if (!db || !(alias= thd->strdup(db)) || check_db_name(db)) { net_printf(thd,ER_WRONG_DB_NAME, db ? db : "NULL"); @@ -1658,15 +1610,15 @@ bool dispatch_command(enum enum_server_command command, THD *thd, #ifndef EMBEDDED_LIBRARY case COM_BINLOG_DUMP: { - statistic_increment(thd->status_var.com_other,&LOCK_status); + ulong pos; + ushort flags; + uint32 slave_server_id; + + statistic_increment(com_other,&LOCK_status); thd->slow_command = TRUE; if (check_global_access(thd, REPL_SLAVE_ACL)) break; - mysql_log.write(thd,command, 0); - ulong pos; - ushort flags; - uint32 slave_server_id; /* TODO: The following has to be changed to an 8 byte integer */ pos = uint4korr(packet); flags = uint2korr(packet + 4); @@ -1674,9 +1626,12 @@ bool dispatch_command(enum enum_server_command command, THD *thd, if ((slave_server_id= uint4korr(packet+6))) // mysqlbinlog.server_id==0 kill_zombie_dump_threads(slave_server_id); thd->server_id = slave_server_id; + + mysql_log.write(thd, command, "Log: '%s' Pos: %ld", packet+10, + (long) pos); mysql_binlog_send(thd, thd->strdup(packet + 10), (my_off_t) pos, flags); unregister_slave(thd,1,1); - /* fake COM_QUIT -- if we get here, the thread needs to terminate */ + // fake COM_QUIT -- if we get here, the thread needs to terminate error = TRUE; net->error = 0; break; @@ -1684,8 +1639,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, #endif case COM_REFRESH: { - statistic_increment(thd->status_var.com_stat[SQLCOM_FLUSH], - &LOCK_status); + statistic_increment(com_stat[SQLCOM_FLUSH],&LOCK_status); ulong options= (ulong) (uchar) packet[0]; if (check_global_access(thd,RELOAD_ACL)) break; @@ -1699,7 +1653,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, #ifndef EMBEDDED_LIBRARY case COM_SHUTDOWN: { - statistic_increment(thd->status_var.com_other, &LOCK_status); + statistic_increment(com_other,&LOCK_status); if (check_global_access(thd,SHUTDOWN_ACL)) break; /* purecov: inspected */ /* @@ -1730,6 +1684,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd, #endif close_connection(thd, 0, 1); close_thread_tables(thd); // Free before kill + free_root(thd->mem_root,MYF(0)); + free_root(&thd->transaction.mem_root,MYF(0)); kill_mysql(); error=TRUE; break; @@ -1738,8 +1694,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, case COM_STATISTICS: { mysql_log.write(thd,command,NullS); - statistic_increment(thd->status_var.com_stat[SQLCOM_SHOW_STATUS], - &LOCK_status); + statistic_increment(com_stat[SQLCOM_SHOW_STATUS],&LOCK_status); #ifndef EMBEDDED_LIBRARY char buff[200]; #else @@ -1749,8 +1704,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd, sprintf((char*) buff, "Uptime: %ld Threads: %d Questions: %lu Slow queries: %ld Opens: %ld Flush tables: %ld Open tables: %u Queries per second avg: %.3f", uptime, - (int) thread_count,thd->query_id,thd->status_var.long_query_count, - thd->status_var.opened_tables,refresh_version, cached_tables(), + (int) thread_count,thd->query_id,long_query_count, + opened_tables,refresh_version, cached_tables(), uptime ? (float)thd->query_id/(float)uptime : 0); #ifdef SAFEMALLOC if (sf_malloc_cur_memory) // Using SAFEMALLOC @@ -1765,12 +1720,11 @@ bool dispatch_command(enum enum_server_command command, THD *thd, break; } case COM_PING: - statistic_increment(thd->status_var.com_other, &LOCK_status); + statistic_increment(com_other,&LOCK_status); send_ok(thd); // Tell client we are alive break; case COM_PROCESS_INFO: - statistic_increment(thd->status_var.com_stat[SQLCOM_SHOW_PROCESSLIST], - &LOCK_status); + statistic_increment(com_stat[SQLCOM_SHOW_PROCESSLIST],&LOCK_status); if (!thd->priv_user[0] && check_global_access(thd,PROCESS_ACL)) break; mysql_log.write(thd,command,NullS); @@ -1780,15 +1734,14 @@ bool dispatch_command(enum enum_server_command command, THD *thd, break; case COM_PROCESS_KILL: { - statistic_increment(thd->status_var.com_stat[SQLCOM_KILL], &LOCK_status); + statistic_increment(com_stat[SQLCOM_KILL],&LOCK_status); ulong id=(ulong) uint4korr(packet); - kill_one_thread(thd,id,false); + kill_one_thread(thd,id); break; } case COM_SET_OPTION: { - statistic_increment(thd->status_var.com_stat[SQLCOM_SET_OPTION], - &LOCK_status); + statistic_increment(com_stat[SQLCOM_SET_OPTION], &LOCK_status); enum_mysql_set_option command= (enum_mysql_set_option) uint2korr(packet); switch (command) { case MYSQL_OPTION_MULTI_STATEMENTS_ON: @@ -1806,7 +1759,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, break; } case COM_DEBUG: - statistic_increment(thd->status_var.com_other, &LOCK_status); + statistic_increment(com_other,&LOCK_status); if (check_global_access(thd, SUPER_ACL)) break; /* purecov: inspected */ mysql_print_status(thd); @@ -1845,7 +1798,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, (SERVER_QUERY_NO_INDEX_USED | SERVER_QUERY_NO_GOOD_INDEX_USED)) && (specialflag & SPECIAL_LOG_QUERIES_NOT_USING_INDEXES))) { - thd->status_var.long_query_count++; + long_query_count++; mysql_slow_log.write(thd, thd->query, thd->query_length, start_of_query); } } @@ -1858,7 +1811,6 @@ bool dispatch_command(enum enum_server_command command, THD *thd, thread_running--; VOID(pthread_mutex_unlock(&LOCK_thread_count)); thd->packet.shrink(thd->variables.net_buffer_length); // Reclaim some memory - free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC)); DBUG_RETURN(error); } @@ -1918,54 +1870,23 @@ bool alloc_query(THD *thd, char *packet, ulong packet_length) ** Execute command saved in thd and current_lex->sql_command ****************************************************************************/ -int +void mysql_execute_command(THD *thd) { int res= 0; LEX *lex= thd->lex; - /* first SELECT_LEX (have special meaning for many of non-SELECTcommands) */ SELECT_LEX *select_lex= &lex->select_lex; - /* first table of first SELECT_LEX */ - TABLE_LIST *first_table= (TABLE_LIST*) select_lex->table_list.first; - /* list of all tables in query */ - TABLE_LIST *all_tables; - /* most outer SELECT_LEX_UNIT of query */ + TABLE_LIST *tables= (TABLE_LIST*) select_lex->table_list.first; SELECT_LEX_UNIT *unit= &lex->unit; DBUG_ENTER("mysql_execute_command"); /* - In many cases first table of main SELECT_LEX have special meaning => - check that it is first table in global list and relink it first in - queries_tables list if it is necessary (we need such relinking only - for queries with subqueries in select list, in this case tables of - subqueries will go to global list first) - - all_tables will differ from first_table only if most upper SELECT_LEX - do not contain tables. - - Because of above in place where should be at least one table in most - outer SELECT_LEX we have following check: - DBUG_ASSERT(first_table == all_tables); - DBUG_ASSERT(first_table == all_tables && first_table != 0); - */ - lex->first_lists_tables_same(); - /* should be assigned after making first tables same */ - all_tables= lex->query_tables; - - if (lex->sql_command != SQLCOM_CREATE_PROCEDURE && - lex->sql_command != SQLCOM_CREATE_SPFUNCTION) - { - if (sp_cache_functions(thd, lex)) - DBUG_RETURN(-1); - } - - /* Reset warning count for each query that uses tables A better approach would be to reset this for any commands that is not a SHOW command or a select that only access local variables, but for now this is probably good enough. */ - if (all_tables || &lex->select_lex != lex->all_selects_list) + if (tables || &lex->select_lex != lex->all_selects_list) mysql_reset_errors(thd); #ifdef HAVE_REPLICATION @@ -1975,11 +1896,11 @@ mysql_execute_command(THD *thd) Skip if we are in the slave thread, some table rules have been given and the table list says the query should not be replicated */ - if (all_tables_not_ok(thd, all_tables)) + if (all_tables_not_ok(thd,tables)) { /* we warn the slave SQL thread */ my_error(ER_SLAVE_IGNORED_TABLE, MYF(0)); - DBUG_RETURN(0); + DBUG_VOID_RETURN; } #ifndef TO_BE_DELETED /* @@ -1995,20 +1916,10 @@ mysql_execute_command(THD *thd) #endif } #endif /* !HAVE_REPLICATION */ - - if (lex->time_zone_tables_used) - { - TABLE_LIST *tmp; - if ((tmp= my_tz_get_table_list(thd, &lex->query_tables_last)) == - &fake_time_zone_tables_list) - { - send_error(thd, 0); - DBUG_RETURN(-1); - } - lex->time_zone_tables_used= tmp; - if (!all_tables) - all_tables= tmp; - } + if ((&lex->select_lex != lex->all_selects_list || + lex->time_zone_tables_used) && + lex->unit.create_total_list(thd, lex, &tables)) + DBUG_VOID_RETURN; /* When option readonly is set deny operations which change tables. @@ -2019,11 +1930,10 @@ mysql_execute_command(THD *thd) (uc_update_queries[lex->sql_command] > 0)) { net_printf(thd, ER_OPTION_PREVENTS_STATEMENT, "--read-only"); - DBUG_RETURN(-1); + DBUG_VOID_RETURN; } - statistic_increment(thd->status_var.com_stat[lex->sql_command], - &LOCK_status); + statistic_increment(com_stat[lex->sql_command],&LOCK_status); switch (lex->sql_command) { case SQLCOM_SELECT: { @@ -2035,31 +1945,42 @@ mysql_execute_command(THD *thd) } select_result *result=lex->result; - if (all_tables) + if (tables) { - res= check_table_access(thd, - lex->exchange ? SELECT_ACL | FILE_ACL : - SELECT_ACL, - all_tables, 0); + res=check_table_access(thd, + lex->exchange ? SELECT_ACL | FILE_ACL : + SELECT_ACL, + tables,0); } else - res= check_access(thd, - lex->exchange ? SELECT_ACL | FILE_ACL : SELECT_ACL, - any_db, 0, 0, 0); + res=check_access(thd, lex->exchange ? SELECT_ACL | FILE_ACL : SELECT_ACL, + any_db,0,0,0); if (res) { res=0; break; // Error message is given } + /* + In case of single SELECT unit->global_parameters points on first SELECT + TODO: move counters to SELECT_LEX + */ + unit->offset_limit_cnt= (ha_rows) unit->global_parameters->offset_limit; + unit->select_limit_cnt= (ha_rows) (unit->global_parameters->select_limit+ + unit->global_parameters->offset_limit); + if (unit->select_limit_cnt < + (ha_rows) unit->global_parameters->select_limit) + unit->select_limit_cnt= HA_POS_ERROR; // no limit + if (unit->select_limit_cnt == HA_POS_ERROR && !select_lex->next_select()) + select_lex->options&= ~OPTION_FOUND_ROWS; - if (!(res= open_and_lock_tables(thd, all_tables))) + if (!(res=open_and_lock_tables(thd,tables))) { if (lex->describe) { if (!(result= new select_send())) { send_error(thd, ER_OUT_OF_RESOURCES); - goto error; + DBUG_VOID_RETURN; } else thd->send_explain_fields(result); @@ -2084,7 +2005,7 @@ mysql_execute_command(THD *thd) res= -1; break; } - query_cache_store_query(thd, all_tables); + query_cache_store_query(thd, tables); res= handle_select(thd, lex, result); if (result != lex->result) delete result; @@ -2206,9 +2127,8 @@ mysql_execute_command(THD *thd) break; } case SQLCOM_DO: - if (all_tables && - ((res= check_table_access(thd, SELECT_ACL, all_tables, 0)) || - (res= open_and_lock_tables(thd, all_tables)))) + if (tables && ((res= check_table_access(thd, SELECT_ACL, tables,0)) || + (res= open_and_lock_tables(thd,tables)))) break; res= mysql_do(thd, *lex->insert_list); @@ -2229,7 +2149,7 @@ mysql_execute_command(THD *thd) { if (check_global_access(thd, SUPER_ACL)) goto error; - /* PURGE MASTER LOGS TO 'file' */ + // PURGE MASTER LOGS TO 'file' res = purge_master_logs(thd, lex->to_log); break; } @@ -2237,7 +2157,7 @@ mysql_execute_command(THD *thd) { if (check_global_access(thd, SUPER_ACL)) goto error; - /* PURGE MASTER LOGS BEFORE 'data' */ + // PURGE MASTER LOGS BEFORE 'data' res = purge_master_logs_before_date(thd, lex->purge_time); break; } @@ -2290,45 +2210,41 @@ mysql_execute_command(THD *thd) case SQLCOM_BACKUP_TABLE: { - DBUG_ASSERT(first_table == all_tables && first_table != 0); - if (check_db_used(thd, all_tables) || - check_table_access(thd, SELECT_ACL, all_tables, 0) || + if (check_db_used(thd,tables) || + check_table_access(thd,SELECT_ACL, tables,0) || check_global_access(thd, FILE_ACL)) goto error; /* purecov: inspected */ thd->slow_command=TRUE; - res = mysql_backup_table(thd, first_table); + res = mysql_backup_table(thd, tables); break; } case SQLCOM_RESTORE_TABLE: { - DBUG_ASSERT(first_table == all_tables && first_table != 0); - if (check_db_used(thd, all_tables) || - check_table_access(thd, INSERT_ACL, all_tables, 0) || + if (check_db_used(thd,tables) || + check_table_access(thd, INSERT_ACL, tables,0) || check_global_access(thd, FILE_ACL)) goto error; /* purecov: inspected */ thd->slow_command=TRUE; - res = mysql_restore_table(thd, first_table); + res = mysql_restore_table(thd, tables); break; } case SQLCOM_ASSIGN_TO_KEYCACHE: { - DBUG_ASSERT(first_table == all_tables && first_table != 0); - if (check_db_used(thd, all_tables) || - check_access(thd, INDEX_ACL, first_table->db, - &first_table->grant.privilege, 0, 0)) + if (check_db_used(thd, tables) || + check_access(thd, INDEX_ACL, tables->db, + &tables->grant.privilege, 0, 0)) goto error; - res= mysql_assign_to_keycache(thd, first_table, &lex->name_and_length); + res= mysql_assign_to_keycache(thd, tables, &lex->name_and_length); break; } case SQLCOM_PRELOAD_KEYS: { - DBUG_ASSERT(first_table == all_tables && first_table != 0); - if (check_db_used(thd, all_tables) || - check_access(thd, INDEX_ACL, first_table->db, - &first_table->grant.privilege, 0, 0)) + if (check_db_used(thd, tables) || + check_access(thd, INDEX_ACL, tables->db, + &tables->grant.privilege, 0, 0)) goto error; - res = mysql_preload_keys(thd, first_table); + res = mysql_preload_keys(thd, tables); break; } #ifdef HAVE_REPLICATION @@ -2381,21 +2297,19 @@ mysql_execute_command(THD *thd) #ifdef HAVE_REPLICATION case SQLCOM_LOAD_MASTER_TABLE: { - DBUG_ASSERT(first_table == all_tables && first_table != 0); - if (!first_table->db) - first_table->db= thd->db; - if (check_access(thd, CREATE_ACL, first_table->db, - &first_table->grant.privilege, 0, 0)) + if (!tables->db) + tables->db=thd->db; + if (check_access(thd,CREATE_ACL,tables->db,&tables->grant.privilege,0,0)) goto error; /* purecov: inspected */ if (grant_option) { /* Check that the first table has CREATE privilege */ - if (check_grant(thd, CREATE_ACL, all_tables, 0, 1, 0)) + if (check_grant(thd, CREATE_ACL, tables, 0, 1, 0)) goto error; } - if (strlen(first_table->real_name) > NAME_LEN) + if (strlen(tables->real_name) > NAME_LEN) { - net_printf(thd, ER_WRONG_TABLE_NAME, first_table->real_name); + net_printf(thd,ER_WRONG_TABLE_NAME, tables->real_name); break; } pthread_mutex_lock(&LOCK_active_mi); @@ -2403,7 +2317,7 @@ mysql_execute_command(THD *thd) fetch_master_table will send the error to the client on failure. Give error if the table already exists. */ - if (!fetch_master_table(thd, first_table->db, first_table->real_name, + if (!fetch_master_table(thd, tables->db, tables->real_name, active_mi, 0, 0)) { send_ok(thd); @@ -2415,13 +2329,12 @@ mysql_execute_command(THD *thd) case SQLCOM_CREATE_TABLE: { - DBUG_ASSERT(first_table == all_tables && first_table != 0); - bool link_to_local; - // Skip first table, which is the table we are creating - TABLE_LIST *create_table= lex->unlink_first_table(&link_to_local); - TABLE_LIST *select_tables= lex->query_tables; + /* Skip first table, which is the table we are creating */ + TABLE_LIST *create_table, *create_table_local; + tables= lex->unlink_first_table(tables, &create_table, + &create_table_local); - if ((res= create_table_precheck(thd, select_tables, create_table))) + if ((res= create_table_precheck(thd, tables, create_table))) goto unsent_create_error; #ifndef HAVE_READLINK @@ -2430,7 +2343,7 @@ mysql_execute_command(THD *thd) /* Fix names if symlinked tables */ if (append_file_to_dir(thd, &lex->create_info.data_file_name, create_table->real_name) || - append_file_to_dir(thd, &lex->create_info.index_file_name, + append_file_to_dir(thd,&lex->create_info.index_file_name, create_table->real_name)) { res=-1; @@ -2438,7 +2351,7 @@ mysql_execute_command(THD *thd) } #endif /* - If we are using SET CHARSET without DEFAULT, add an implicit + If we are using SET CHARSET without DEFAULT, add an implicite DEFAULT to not confuse old users. (This may change). */ if ((lex->create_info.used_fields & @@ -2455,42 +2368,21 @@ mysql_execute_command(THD *thd) select_result *result; select_lex->options|= SELECT_NO_UNLOCK; - unit->set_limit(select_lex, select_lex); + unit->offset_limit_cnt= select_lex->offset_limit; + unit->select_limit_cnt= select_lex->select_limit+ + select_lex->offset_limit; + if (unit->select_limit_cnt < select_lex->select_limit) + unit->select_limit_cnt= HA_POS_ERROR; // No limit - if (!(res= open_and_lock_tables(thd, select_tables))) + if (!(res=open_and_lock_tables(thd,tables))) { - /* - Is table which we are changing used somewhere in other parts - of query - */ - if (!(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) && - unique_table(create_table, select_tables)) - { - net_printf(thd, ER_UPDATE_TABLE_USED, create_table->real_name); - goto create_error; - } - /* If we create merge table, we have to test tables in merge, too */ - if (lex->create_info.used_fields & HA_CREATE_USED_UNION) - { - TABLE_LIST *tab; - for (tab= (TABLE_LIST*) lex->create_info.merge_list.first; - tab; - tab= tab->next_local) - { - if (unique_table(tab, select_tables)) - { - net_printf(thd, ER_UPDATE_TABLE_USED, tab->real_name); - goto create_error; - } - } - } - - if ((result= new select_create(create_table, - &lex->create_info, - lex->create_list, - lex->key_list, - select_lex->item_list, - lex->duplicates))) + res= -1; // If error + if ((result=new select_create(create_table->db, + create_table->real_name, + &lex->create_info, + lex->create_list, + lex->key_list, + select_lex->item_list,lex->duplicates))) { /* CREATE from SELECT give its SELECT_LEX for SELECT, @@ -2499,48 +2391,49 @@ mysql_execute_command(THD *thd) select_lex->resolve_mode= SELECT_LEX::SELECT_MODE; res=handle_select(thd, lex, result); select_lex->resolve_mode= SELECT_LEX::NOMATTER_MODE; - delete result; } - /* reset for PS */ + //reset for PS lex->create_list.empty(); lex->key_list.empty(); } } - else + else // regular create { - /* regular create */ if (lex->name) res= mysql_create_like_table(thd, create_table, &lex->create_info, (Table_ident *)lex->name); else { - res= mysql_create_table(thd, create_table->db, - create_table->real_name, &lex->create_info, - lex->create_list, - lex->key_list, 0, 0); + res= mysql_create_table(thd,create_table->db, + create_table->real_name, &lex->create_info, + lex->create_list, + lex->key_list,0,0); } if (!res) send_ok(thd); } - lex->link_first_table_back(create_table, link_to_local); + + // put tables back for PS rexecuting + tables= lex->link_first_table_back(tables, create_table, + create_table_local); break; create_error: - res= 1; //error reported + res= 1; //error reported unsent_create_error: - /* put tables back for PS rexecuting */ - lex->link_first_table_back(create_table, link_to_local); + // put tables back for PS rexecuting + tables= lex->link_first_table_back(tables, create_table, + create_table_local); break; } case SQLCOM_CREATE_INDEX: - DBUG_ASSERT(first_table == all_tables && first_table != 0); - if (check_one_table_access(thd, INDEX_ACL, all_tables)) + if (check_one_table_access(thd, INDEX_ACL, tables)) goto error; /* purecov: inspected */ thd->slow_command=TRUE; if (end_active_trans(thd)) res= -1; else - res = mysql_create_index(thd, first_table, lex->key_list); + res = mysql_create_index(thd, tables, lex->key_list); break; #ifdef HAVE_REPLICATION @@ -2568,7 +2461,7 @@ unsent_create_error: if (thd->locked_tables || thd->active_transaction()) { send_error(thd,ER_LOCK_OR_ACTIVE_TRANSACTION); - goto error; + break; } { pthread_mutex_lock(&LOCK_active_mi); @@ -2579,10 +2472,9 @@ unsent_create_error: #endif /* HAVE_REPLICATION */ case SQLCOM_ALTER_TABLE: - DBUG_ASSERT(first_table == all_tables && first_table != 0); #if defined(DONT_ALLOW_SHOW_COMMANDS) send_error(thd,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */ - goto error; + break; #else { ulong priv=0; @@ -2593,17 +2485,16 @@ unsent_create_error: break; } if (!select_lex->db) - select_lex->db= first_table->db; - if (check_access(thd, ALTER_ACL, first_table->db, - &first_table->grant.privilege, 0, 0) || + select_lex->db=tables->db; + if (check_access(thd,ALTER_ACL,tables->db,&tables->grant.privilege,0,0) || check_access(thd,INSERT_ACL | CREATE_ACL,select_lex->db,&priv,0,0)|| - check_merge_table_access(thd, first_table->db, + check_merge_table_access(thd, tables->db, (TABLE_LIST *) lex->create_info.merge_list.first)) goto error; /* purecov: inspected */ if (grant_option) { - if (check_grant(thd, ALTER_ACL, all_tables, 0, UINT_MAX, 0)) + if (check_grant(thd, ALTER_ACL, tables, 0, UINT_MAX, 0)) goto error; if (lex->name && !test_all_bits(priv,INSERT_ACL | CREATE_ACL)) { // Rename of table @@ -2627,7 +2518,7 @@ unsent_create_error: thd->slow_command=TRUE; res= mysql_alter_table(thd, select_lex->db, lex->name, &lex->create_info, - first_table, lex->create_list, + tables, lex->create_list, lex->key_list, select_lex->order_list.elements, (ORDER *) select_lex->order_list.first, @@ -2638,37 +2529,38 @@ unsent_create_error: #endif /*DONT_ALLOW_SHOW_COMMANDS*/ case SQLCOM_RENAME_TABLE: { - DBUG_ASSERT(first_table == all_tables && first_table != 0); TABLE_LIST *table; - if (check_db_used(thd, all_tables)) + if (check_db_used(thd,tables)) goto error; - for (table= first_table; table; table= table->next_local->next_local) + for (table=tables ; table ; table=table->next->next) { if (check_access(thd, ALTER_ACL | DROP_ACL, table->db, &table->grant.privilege,0,0) || - check_access(thd, INSERT_ACL | CREATE_ACL, table->next_local->db, - &table->next_local->grant.privilege, 0, 0)) + check_access(thd, INSERT_ACL | CREATE_ACL, table->next->db, + &table->next->grant.privilege,0,0)) goto error; if (grant_option) { - TABLE_LIST old_list, new_list; + TABLE_LIST old_list,new_list; /* we do not need initialize old_list and new_list because we will come table[0] and table->next[0] there */ - old_list= table[0]; - new_list= table->next_local[0]; - if (check_grant(thd, ALTER_ACL, &old_list, 0, 1, 0) || - (!test_all_bits(table->next_local->grant.privilege, + old_list=table[0]; + new_list=table->next[0]; + old_list.next=new_list.next=0; + if (check_grant(thd, ALTER_ACL, &old_list, 0, UINT_MAX, 0) || + (!test_all_bits(table->next->grant.privilege, INSERT_ACL | CREATE_ACL) && - check_grant(thd, INSERT_ACL | CREATE_ACL, &new_list, 0, 1, 0))) + check_grant(thd, INSERT_ACL | CREATE_ACL, &new_list, 0, + UINT_MAX, 0))) goto error; } } - query_cache_invalidate3(thd, first_table, 0); + query_cache_invalidate3(thd, tables, 0); if (end_active_trans(thd)) res= -1; - else if (mysql_rename_tables(thd, first_table)) + else if (mysql_rename_tables(thd,tables)) res= -1; break; } @@ -2676,7 +2568,7 @@ unsent_create_error: case SQLCOM_SHOW_BINLOGS: #ifdef DONT_ALLOW_SHOW_COMMANDS send_error(thd,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */ - goto error; + DBUG_VOID_RETURN; #else { if (check_global_access(thd, SUPER_ACL)) @@ -2687,40 +2579,38 @@ unsent_create_error: #endif #endif /* EMBEDDED_LIBRARY */ case SQLCOM_SHOW_CREATE: - DBUG_ASSERT(first_table == all_tables && first_table != 0); #ifdef DONT_ALLOW_SHOW_COMMANDS send_error(thd,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */ - goto error; + DBUG_VOID_RETURN; #else { - if (check_db_used(thd, all_tables) || - check_access(thd, SELECT_ACL | EXTRA_ACL, first_table->db, - &first_table->grant.privilege, 0, 0)) + if (check_db_used(thd, tables) || + check_access(thd, SELECT_ACL | EXTRA_ACL, tables->db, + &tables->grant.privilege,0,0)) goto error; - res = mysqld_show_create(thd, first_table); + res = mysqld_show_create(thd, tables); break; } #endif case SQLCOM_CHECKSUM: { - DBUG_ASSERT(first_table == all_tables && first_table != 0); - if (check_db_used(thd, all_tables) || - check_table_access(thd, SELECT_ACL | EXTRA_ACL, all_tables, 0)) + if (check_db_used(thd,tables) || + check_table_access(thd, SELECT_ACL | EXTRA_ACL , tables,0)) goto error; /* purecov: inspected */ - res = mysql_checksum_table(thd, first_table, &lex->check_opt); + res = mysql_checksum_table(thd, tables, &lex->check_opt); break; } case SQLCOM_REPAIR: { - DBUG_ASSERT(first_table == all_tables && first_table != 0); - if (check_db_used(thd, all_tables) || - check_table_access(thd, SELECT_ACL | INSERT_ACL, all_tables, 0)) + if (check_db_used(thd,tables) || + check_table_access(thd,SELECT_ACL | INSERT_ACL, tables,0)) goto error; /* purecov: inspected */ thd->slow_command=TRUE; - res= mysql_repair_table(thd, first_table, &lex->check_opt); + res = mysql_repair_table(thd, tables, &lex->check_opt); /* ! we write after unlocking the table */ if (!res && !lex->no_write_to_binlog) { + mysql_update_log.write(thd, thd->query, thd->query_length); if (mysql_bin_log.is_open()) { thd->clear_error(); // No binlog error generated @@ -2732,25 +2622,24 @@ unsent_create_error: } case SQLCOM_CHECK: { - DBUG_ASSERT(first_table == all_tables && first_table != 0); - if (check_db_used(thd, all_tables) || - check_table_access(thd, SELECT_ACL | EXTRA_ACL , all_tables, 0)) + if (check_db_used(thd,tables) || + check_table_access(thd, SELECT_ACL | EXTRA_ACL , tables,0)) goto error; /* purecov: inspected */ thd->slow_command=TRUE; - res = mysql_check_table(thd, first_table, &lex->check_opt); + res = mysql_check_table(thd, tables, &lex->check_opt); break; } case SQLCOM_ANALYZE: { - DBUG_ASSERT(first_table == all_tables && first_table != 0); - if (check_db_used(thd, all_tables) || - check_table_access(thd, SELECT_ACL | INSERT_ACL, all_tables, 0)) + if (check_db_used(thd,tables) || + check_table_access(thd,SELECT_ACL | INSERT_ACL, tables,0)) goto error; /* purecov: inspected */ thd->slow_command=TRUE; - res = mysql_analyze_table(thd, first_table, &lex->check_opt); + res = mysql_analyze_table(thd, tables, &lex->check_opt); /* ! we write after unlocking the table */ if (!res && !lex->no_write_to_binlog) { + mysql_update_log.write(thd, thd->query, thd->query_length); if (mysql_bin_log.is_open()) { thd->clear_error(); // No binlog error generated @@ -2763,17 +2652,17 @@ unsent_create_error: case SQLCOM_OPTIMIZE: { - DBUG_ASSERT(first_table == all_tables && first_table != 0); - if (check_db_used(thd, all_tables) || - check_table_access(thd, SELECT_ACL | INSERT_ACL, all_tables, 0)) + if (check_db_used(thd,tables) || + check_table_access(thd,SELECT_ACL | INSERT_ACL, tables,0)) goto error; /* purecov: inspected */ thd->slow_command=TRUE; res= (specialflag & (SPECIAL_SAFE_MODE | SPECIAL_NO_NEW_FUNC)) ? - mysql_recreate_table(thd, first_table, 1) : - mysql_optimize_table(thd, first_table, &lex->check_opt); + mysql_recreate_table(thd, tables, 1) : + mysql_optimize_table(thd, tables, &lex->check_opt); /* ! we write after unlocking the table */ if (!res && !lex->no_write_to_binlog) { + mysql_update_log.write(thd, thd->query, thd->query_length); if (mysql_bin_log.is_open()) { thd->clear_error(); // No binlog error generated @@ -2784,10 +2673,9 @@ unsent_create_error: break; } case SQLCOM_UPDATE: - DBUG_ASSERT(first_table == all_tables && first_table != 0); - if (update_precheck(thd, all_tables)) + if (update_precheck(thd, tables)) break; - res= mysql_update(thd, all_tables, + res= mysql_update(thd,tables, select_lex->item_list, lex->value_list, select_lex->where, @@ -2800,10 +2688,9 @@ unsent_create_error: break; case SQLCOM_UPDATE_MULTI: { - DBUG_ASSERT(first_table == all_tables && first_table != 0); - if ((res= multi_update_precheck(thd, all_tables))) + if ((res= multi_update_precheck(thd, tables))) break; - res= mysql_multi_update(thd, all_tables, + res= mysql_multi_update(thd,tables, &select_lex->item_list, &lex->value_list, select_lex->where, @@ -2814,81 +2701,67 @@ unsent_create_error: case SQLCOM_REPLACE: case SQLCOM_INSERT: { - DBUG_ASSERT(first_table == all_tables && first_table != 0); - if ((res= insert_precheck(thd, all_tables))) + if ((res= insert_precheck(thd, tables))) break; - res= mysql_insert(thd, all_tables, lex->field_list, lex->many_values, - select_lex->item_list, lex->value_list, - (lex->value_list.elements ? - DUP_UPDATE : lex->duplicates)); + res = mysql_insert(thd,tables,lex->field_list,lex->many_values, + select_lex->item_list, lex->value_list, + lex->duplicates); if (thd->net.report_error) res= -1; - if (first_table->view && !first_table->contain_auto_increment) - thd->last_insert_id= 0; // do not show last insert ID if VIEW have not it break; } case SQLCOM_REPLACE_SELECT: case SQLCOM_INSERT_SELECT: { - DBUG_ASSERT(first_table == all_tables && first_table != 0); - if ((res= insert_select_precheck(thd, all_tables))) + TABLE_LIST *first_local_table= (TABLE_LIST *) select_lex->table_list.first; + if ((res= insert_select_precheck(thd, tables))) break; /* Fix lock for first table */ - if (first_table->lock_type == TL_WRITE_DELAYED) - first_table->lock_type= TL_WRITE; + if (tables->lock_type == TL_WRITE_DELAYED) + tables->lock_type= TL_WRITE; /* Don't unlock tables until command is written to binary log */ select_lex->options|= SELECT_NO_UNLOCK; select_result *result; - unit->set_limit(select_lex, select_lex); + unit->offset_limit_cnt= select_lex->offset_limit; + unit->select_limit_cnt= select_lex->select_limit+select_lex->offset_limit; + if (unit->select_limit_cnt < select_lex->select_limit) + unit->select_limit_cnt= HA_POS_ERROR; // No limit - if (!(res= open_and_lock_tables(thd, all_tables))) + if (find_real_table_in_list(tables->next, tables->db, tables->real_name)) { + /* Using same table for INSERT and SELECT */ + select_lex->options |= OPTION_BUFFER_RESULT; + } + + + if (!(res= open_and_lock_tables(thd, tables)) && + (result= new select_insert(tables->table, &lex->field_list, + lex->duplicates))) + { + /* Skip first table, which is the table we are inserting in */ + lex->select_lex.table_list.first= (byte*) first_local_table->next; /* - Is table which we are changing used somewhere in other parts of - query + insert/replace from SELECT give its SELECT_LEX for SELECT, + and item_list belong to SELECT */ - if (unique_table(first_table, all_tables->next_global)) - { - /* Using same table for INSERT and SELECT */ - select_lex->options |= OPTION_BUFFER_RESULT; - } - - if ((res= mysql_insert_select_prepare(thd))) - break; - if ((result= new select_insert(first_table, first_table->table, - &lex->field_list, lex->duplicates, - lex->duplicates == DUP_IGNORE))) - { - /* Skip first table, which is the table we are inserting in */ - lex->select_lex.table_list.first= (byte*) first_table->next_local; - /* - insert/replace from SELECT give its SELECT_LEX for SELECT, - and item_list belong to SELECT - */ - lex->select_lex.resolve_mode= SELECT_LEX::SELECT_MODE; - res= handle_select(thd, lex, result); - /* revert changes for SP */ - lex->select_lex.table_list.first= (byte*) first_table; - lex->select_lex.resolve_mode= SELECT_LEX::INSERT_MODE; - delete result; - } + lex->select_lex.resolve_mode= SELECT_LEX::SELECT_MODE; + res= handle_select(thd, lex, result); + /* revert changes for SP */ + lex->select_lex.table_list.first= (byte*) first_local_table; + lex->select_lex.resolve_mode= SELECT_LEX::INSERT_MODE; + delete result; if (thd->net.report_error) res= -1; } else res= -1; - - if (first_table->view && !first_table->contain_auto_increment) - thd->last_insert_id= 0; // do not show last insert ID if VIEW have not it - break; } case SQLCOM_TRUNCATE: - DBUG_ASSERT(first_table == all_tables && first_table != 0); - if (check_one_table_access(thd, DELETE_ACL, all_tables)) + if (check_one_table_access(thd, DELETE_ACL, tables)) goto error; /* Don't allow this within a transaction because we want to use @@ -2899,15 +2772,13 @@ unsent_create_error: send_error(thd,ER_LOCK_OR_ACTIVE_TRANSACTION,NullS); goto error; } - - res= mysql_truncate(thd, first_table, 0); + res=mysql_truncate(thd, tables, 0); break; case SQLCOM_DELETE: { - DBUG_ASSERT(first_table == all_tables && first_table != 0); - if ((res= delete_precheck(thd, all_tables))) + if ((res= delete_precheck(thd, tables))) break; - res = mysql_delete(thd, all_tables, select_lex->where, + res = mysql_delete(thd,tables, select_lex->where, &select_lex->order_list, select_lex->select_limit, select_lex->options); if (thd->net.report_error) @@ -2916,13 +2787,13 @@ unsent_create_error: } case SQLCOM_DELETE_MULTI: { - DBUG_ASSERT(first_table == all_tables && first_table != 0); TABLE_LIST *aux_tables= (TABLE_LIST *)thd->lex->auxilliary_table_list.first; + TABLE_LIST *target_tbl; uint table_count; multi_delete *result; - if ((res= multi_delete_precheck(thd, all_tables, &table_count))) + if ((res= multi_delete_precheck(thd, tables, &table_count))) break; /* condition will be TRUE on SP re-excuting */ @@ -2935,9 +2806,28 @@ unsent_create_error: } thd->proc_info="init"; - if ((res= open_and_lock_tables(thd, all_tables)) || - (res= mysql_multi_delete_prepare(thd))) + if ((res=open_and_lock_tables(thd,tables))) break; + /* Fix tables-to-be-deleted-from list to point at opened tables */ + for (target_tbl= (TABLE_LIST*) aux_tables; + target_tbl; + target_tbl= target_tbl->next) + { + TABLE_LIST *orig= target_tbl->table_list; + target_tbl->table= orig->table; + /* + Multi-delete can't be constructed over-union => we always have + single SELECT on top and have to check underlying SELECTs of it + */ + if (lex->select_lex.check_updateable_in_subqueries(orig->db, + orig->real_name)) + { + my_error(ER_UPDATE_TABLE_USED, MYF(0), + orig->real_name); + res= -1; + break; + } + } if (!thd->is_fatal_error && (result= new multi_delete(thd,aux_tables, table_count))) @@ -2963,10 +2853,9 @@ unsent_create_error: } case SQLCOM_DROP_TABLE: { - DBUG_ASSERT(first_table == all_tables && first_table != 0); if (!lex->drop_temporary) { - if (check_table_access(thd, DROP_ACL, all_tables, 0)) + if (check_table_access(thd,DROP_ACL,tables,0)) goto error; /* purecov: inspected */ if (end_active_trans(thd)) { @@ -2987,23 +2876,21 @@ unsent_create_error: if (thd->slave_thread) lex->drop_if_exists= 1; } - res= mysql_rm_table(thd, first_table, lex->drop_if_exists, - lex->drop_temporary); + res= mysql_rm_table(thd,tables,lex->drop_if_exists, lex->drop_temporary); } break; case SQLCOM_DROP_INDEX: - DBUG_ASSERT(first_table == all_tables && first_table != 0); - if (check_one_table_access(thd, INDEX_ACL, all_tables)) + if (check_one_table_access(thd, INDEX_ACL, tables)) goto error; /* purecov: inspected */ if (end_active_trans(thd)) res= -1; else - res = mysql_drop_index(thd, first_table, &lex->alter_info); + res = mysql_drop_index(thd, tables, &lex->alter_info); break; case SQLCOM_SHOW_DATABASES: #if defined(DONT_ALLOW_SHOW_COMMANDS) send_error(thd,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */ - goto error; + DBUG_VOID_RETURN; #else if ((specialflag & SPECIAL_SKIP_SHOW_DB) && check_global_access(thd, SHOW_DB_ACL)) @@ -3028,28 +2915,18 @@ unsent_create_error: res= mysqld_show_column_types(thd); break; case SQLCOM_SHOW_STATUS: - STATUS_VAR tmp; - if (lex->option_type == OPT_GLOBAL) - { - pthread_mutex_lock(&LOCK_status); - calc_sum_of_all_status(&tmp); - } - res= mysqld_show(thd, (lex->wild ? lex->wild->ptr() : NullS), - status_vars, OPT_GLOBAL, &LOCK_status, - (lex->option_type == OPT_GLOBAL ? - &tmp: &thd->status_var)); - if (lex->option_type == OPT_GLOBAL) - pthread_mutex_unlock(&LOCK_status); + res= mysqld_show(thd,(lex->wild ? lex->wild->ptr() : NullS),status_vars, + OPT_GLOBAL, &LOCK_status); break; case SQLCOM_SHOW_VARIABLES: res= mysqld_show(thd, (lex->wild ? lex->wild->ptr() : NullS), init_vars, lex->option_type, - &LOCK_global_system_variables, 0); + &LOCK_global_system_variables); break; case SQLCOM_SHOW_LOGS: #ifdef DONT_ALLOW_SHOW_COMMANDS send_error(thd,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */ - goto error; + DBUG_VOID_RETURN; #else { if (grant_option && check_access(thd, FILE_ACL, any_db,0,0,0)) @@ -3062,13 +2939,13 @@ unsent_create_error: /* FALL THROUGH */ #ifdef DONT_ALLOW_SHOW_COMMANDS send_error(thd,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */ - goto error; + DBUG_VOID_RETURN; #else { char *db=select_lex->db ? select_lex->db : thd->db; if (!db) { - send_error(thd,ER_NO_DB_ERROR); /* purecov: inspected */ + send_error(thd,ER_NO_DB_ERROR); /* purecov: inspected */ goto error; /* purecov: inspected */ } remove_escape(db); // Fix escaped '_' @@ -3092,9 +2969,8 @@ unsent_create_error: res= mysqld_extend_show_tables(thd,db, (lex->wild ? lex->wild->ptr() : NullS)); else - res= mysqld_show_tables(thd, db, - (lex->wild ? lex->wild->ptr() : NullS), - lex->verbose); + res= mysqld_show_tables(thd,db, + (lex->wild ? lex->wild->ptr() : NullS)); break; } #endif @@ -3108,42 +2984,40 @@ unsent_create_error: res= mysqld_show_collations(thd,(lex->wild ? lex->wild->ptr() : NullS)); break; case SQLCOM_SHOW_FIELDS: - DBUG_ASSERT(first_table == all_tables && first_table != 0); #ifdef DONT_ALLOW_SHOW_COMMANDS send_error(thd,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */ - goto error; + DBUG_VOID_RETURN; #else { - char *db= first_table->db; + char *db=tables->db; remove_escape(db); // Fix escaped '_' - remove_escape(first_table->real_name); + remove_escape(tables->real_name); if (check_access(thd,SELECT_ACL | EXTRA_ACL,db, - &first_table->grant.privilege, 0, 0)) + &tables->grant.privilege, 0, 0)) goto error; /* purecov: inspected */ - if (grant_option && check_grant(thd, SELECT_ACL, first_table, 2, UINT_MAX, 0)) + if (grant_option && check_grant(thd, SELECT_ACL, tables, 2, UINT_MAX, 0)) goto error; - res= mysqld_show_fields(thd, first_table, + res= mysqld_show_fields(thd,tables, (lex->wild ? lex->wild->ptr() : NullS), lex->verbose); break; } #endif case SQLCOM_SHOW_KEYS: - DBUG_ASSERT(first_table == all_tables && first_table != 0); #ifdef DONT_ALLOW_SHOW_COMMANDS send_error(thd,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */ - goto error; + DBUG_VOID_RETURN; #else { - char *db= first_table->db; + char *db=tables->db; remove_escape(db); // Fix escaped '_' - remove_escape(first_table->real_name); + remove_escape(tables->real_name); if (check_access(thd,SELECT_ACL | EXTRA_ACL,db, - &first_table->grant.privilege, 0, 0)) + &tables->grant.privilege, 0, 0)) goto error; /* purecov: inspected */ - if (grant_option && check_grant(thd, SELECT_ACL, all_tables, 2, UINT_MAX, 0)) + if (grant_option && check_grant(thd, SELECT_ACL, tables, 2, UINT_MAX, 0)) goto error; - res= mysqld_show_keys(thd, first_table); + res= mysqld_show_keys(thd,tables); break; } #endif @@ -3153,13 +3027,12 @@ unsent_create_error: case SQLCOM_LOAD: { - DBUG_ASSERT(first_table == all_tables && first_table != 0); uint privilege= (lex->duplicates == DUP_REPLACE ? INSERT_ACL | DELETE_ACL : INSERT_ACL); if (!lex->local_file) { - if (check_access(thd, privilege | FILE_ACL, first_table->db, 0, 0, 0)) + if (check_access(thd,privilege | FILE_ACL,tables->db,0,0,0)) goto error; } else @@ -3170,21 +3043,19 @@ unsent_create_error: send_error(thd,ER_NOT_ALLOWED_COMMAND); goto error; } - if (check_one_table_access(thd, privilege, all_tables)) + if (check_one_table_access(thd, privilege, tables)) goto error; } - res= mysql_load(thd, lex->exchange, first_table, lex->field_list, - lex->duplicates, (bool) lex->local_file, - lex->lock_option, lex->duplicates == DUP_IGNORE); + res=mysql_load(thd, lex->exchange, tables, lex->field_list, + lex->duplicates, (bool) lex->local_file, lex->lock_option); break; } case SQLCOM_SET_OPTION: { List<set_var_base> *lex_var_list= &lex->var_list; - if (all_tables && - ((res= check_table_access(thd, SELECT_ACL, all_tables, 0)) || - (res= open_and_lock_tables(thd, all_tables)))) + if (tables && ((res= check_table_access(thd, SELECT_ACL, tables,0)) || + (res= open_and_lock_tables(thd,tables)))) break; if (lex->one_shot_set && not_all_support_one_shot(lex_var_list)) { @@ -3208,6 +3079,12 @@ purposes internal to the MySQL server", MYF(0)); } case SQLCOM_UNLOCK_TABLES: + /* + It is critical for mysqldump --single-transaction --master-data that + UNLOCK TABLES does not implicitely commit a connection which has only + done FLUSH TABLES WITH READ LOCK + BEGIN. If this assumption becomes + false, mysqldump will not work. + */ unlock_locked_tables(thd); if (thd->options & OPTION_TABLE_LOCK) { @@ -3220,18 +3097,17 @@ purposes internal to the MySQL server", MYF(0)); break; case SQLCOM_LOCK_TABLES: unlock_locked_tables(thd); - if (check_db_used(thd, all_tables) || end_active_trans(thd)) + if (check_db_used(thd,tables) || end_active_trans(thd)) goto error; - if (check_table_access(thd, LOCK_TABLES_ACL | SELECT_ACL, all_tables, 0)) + if (check_table_access(thd, LOCK_TABLES_ACL | SELECT_ACL, tables,0)) goto error; thd->in_lock_tables=1; thd->options|= OPTION_TABLE_LOCK; - - if (!(res= open_and_lock_tables(thd, all_tables))) + if (!(res= open_and_lock_tables(thd, tables))) { #ifdef HAVE_QUERY_CACHE if (thd->variables.query_cache_wlock_invalidate) - query_cache.invalidate_locked_for_write(first_table); + query_cache.invalidate_locked_for_write(tables); #endif /*HAVE_QUERY_CACHE*/ thd->locked_tables=thd->lock; thd->lock=0; @@ -3356,24 +3232,26 @@ purposes internal to the MySQL server", MYF(0)); res=mysqld_show_create_db(thd,lex->name,&lex->create_info); break; } - case SQLCOM_CREATE_FUNCTION: // UDF function - { - sp_head *sph; + case SQLCOM_CREATE_FUNCTION: if (check_access(thd,INSERT_ACL,"mysql",0,1,0)) break; #ifdef HAVE_DLOPEN - if ((sph= sp_find_function(thd, lex->spname))) - { - net_printf(thd, ER_UDF_EXISTS, lex->spname->m_name.str); - goto error; - } if (!(res = mysql_create_function(thd,&lex->udf))) send_ok(thd); #else res= -1; #endif break; - } + case SQLCOM_DROP_FUNCTION: + if (check_access(thd,DELETE_ACL,"mysql",0,1,0)) + break; +#ifdef HAVE_DLOPEN + if (!(res = mysql_drop_function(thd,&lex->udf.name))) + send_ok(thd); +#else + res= -1; +#endif + break; #ifndef NO_EMBEDDED_ACCESS_CHECKS case SQLCOM_DROP_USER: { @@ -3381,6 +3259,7 @@ purposes internal to the MySQL server", MYF(0)); break; if (!(res= mysql_drop_user(thd, lex->users_list))) { + mysql_update_log.write(thd, thd->query, thd->query_length); if (mysql_bin_log.is_open()) { Query_log_event qinfo(thd, thd->query, thd->query_length, 0); @@ -3396,6 +3275,7 @@ purposes internal to the MySQL server", MYF(0)); break; if (!(res = mysql_revoke_all(thd, lex->users_list))) { + mysql_update_log.write(thd, thd->query, thd->query_length); if (mysql_bin_log.is_open()) { Query_log_event qinfo(thd, thd->query, thd->query_length, 0); @@ -3409,12 +3289,34 @@ purposes internal to the MySQL server", MYF(0)); case SQLCOM_GRANT: { if (check_access(thd, lex->grant | lex->grant_tot_col | GRANT_ACL, - ((first_table && first_table->db) ? - first_table->db : select_lex->db), - first_table ? &first_table->grant.privilege : 0, - first_table ? 0 : 1, 0)) + tables && tables->db ? tables->db : select_lex->db, + tables ? &tables->grant.privilege : 0, + tables ? 0 : 1,0)) goto error; + /* + Check that the user isn't trying to change a password for another + user if he doesn't have UPDATE privilege to the MySQL database + */ + + if (thd->user) // If not replication + { + LEX_USER *user; + List_iterator <LEX_USER> user_list(lex->users_list); + while ((user=user_list++)) + { + if (user->password.str && + (strcmp(thd->user,user->user.str) || + user->host.str && + my_strcasecmp(&my_charset_latin1, + user->host.str, thd->host_or_ip))) + { + if (check_access(thd, UPDATE_ACL, "mysql",0,1,0)) + goto error; + break; // We are allowed to do changes + } + } + } if (specialflag & SPECIAL_NO_RESOLVE) { LEX_USER *user; @@ -3428,21 +3330,24 @@ purposes internal to the MySQL server", MYF(0)); user->host.str); } } - if (first_table) + if (tables) { if (grant_option && check_grant(thd, (lex->grant | lex->grant_tot_col | GRANT_ACL), - all_tables, 0, UINT_MAX, 0)) + tables, 0, UINT_MAX, 0)) goto error; - if (!(res = mysql_table_grant(thd, all_tables, lex->users_list, - lex->columns, lex->grant, - lex->sql_command == SQLCOM_REVOKE)) && - mysql_bin_log.is_open()) + if (!(res = mysql_table_grant(thd,tables,lex->users_list, lex->columns, + lex->grant, + lex->sql_command == SQLCOM_REVOKE))) { - thd->clear_error(); - Query_log_event qinfo(thd, thd->query, thd->query_length, 0); - mysql_bin_log.write(&qinfo); + mysql_update_log.write(thd, thd->query, thd->query_length); + if (mysql_bin_log.is_open()) + { + thd->clear_error(); + Query_log_event qinfo(thd, thd->query, thd->query_length, 0); + mysql_bin_log.write(&qinfo); + } } } else @@ -3457,6 +3362,7 @@ purposes internal to the MySQL server", MYF(0)); lex->sql_command == SQLCOM_REVOKE); if (!res) { + mysql_update_log.write(thd, thd->query, thd->query_length); if (mysql_bin_log.is_open()) { thd->clear_error(); @@ -3483,14 +3389,14 @@ purposes internal to the MySQL server", MYF(0)); lex->no_write_to_binlog= 1; case SQLCOM_FLUSH: { - if (check_global_access(thd,RELOAD_ACL) || check_db_used(thd, all_tables)) + if (check_global_access(thd,RELOAD_ACL) || check_db_used(thd, tables)) goto error; /* reload_acl_and_cache() will tell us if we are allowed to write to the binlog or not. */ bool write_to_binlog; - if (reload_acl_and_cache(thd, lex->type, first_table, &write_to_binlog)) + if (reload_acl_and_cache(thd, lex->type, tables, &write_to_binlog)) send_error(thd, 0); else { @@ -3500,6 +3406,7 @@ purposes internal to the MySQL server", MYF(0)); */ if (!lex->no_write_to_binlog && write_to_binlog) { + mysql_update_log.write(thd, thd->query, thd->query_length); if (mysql_bin_log.is_open()) { Query_log_event qinfo(thd, thd->query, thd->query_length, 0); @@ -3511,7 +3418,7 @@ purposes internal to the MySQL server", MYF(0)); break; } case SQLCOM_KILL: - kill_one_thread(thd,lex->thread_id, lex->type & ONLY_KILL_QUERY); + kill_one_thread(thd,lex->thread_id); break; #ifndef NO_EMBEDDED_ACCESS_CHECKS case SQLCOM_SHOW_GRANTS: @@ -3525,37 +3432,34 @@ purposes internal to the MySQL server", MYF(0)); break; #endif case SQLCOM_HA_OPEN: - DBUG_ASSERT(first_table == all_tables && first_table != 0); - if (check_db_used(thd, all_tables) || - check_table_access(thd, SELECT_ACL, all_tables, 0)) + if (check_db_used(thd,tables) || + check_table_access(thd,SELECT_ACL, tables,0)) goto error; - res= mysql_ha_open(thd, first_table); + res = mysql_ha_open(thd, tables); break; case SQLCOM_HA_CLOSE: - DBUG_ASSERT(first_table == all_tables && first_table != 0); - if (check_db_used(thd, all_tables)) + if (check_db_used(thd,tables)) goto error; - res= mysql_ha_close(thd, first_table); + res = mysql_ha_close(thd, tables); break; case SQLCOM_HA_READ: - DBUG_ASSERT(first_table == all_tables && first_table != 0); /* There is no need to check for table permissions here, because if a user has no permissions to read a table, he won't be able to open it (with SQLCOM_HA_OPEN) in the first place. */ - if (check_db_used(thd, all_tables)) + if (check_db_used(thd,tables)) goto error; - res= mysql_ha_read(thd, first_table, lex->ha_read_mode, lex->backup_dir, - lex->insert_list, lex->ha_rkey_mode, select_lex->where, - select_lex->select_limit, select_lex->offset_limit); + res = mysql_ha_read(thd, tables, lex->ha_read_mode, lex->backup_dir, + lex->insert_list, lex->ha_rkey_mode, select_lex->where, + select_lex->select_limit, select_lex->offset_limit); break; case SQLCOM_BEGIN: if (thd->locked_tables) { thd->lock=thd->locked_tables; - thd->locked_tables=0; // Will be automatically closed + thd->locked_tables=0; // Will be automaticly closed close_thread_tables(thd); // Free tables } if (end_active_trans(thd)) @@ -3567,7 +3471,9 @@ purposes internal to the MySQL server", MYF(0)); thd->options= ((thd->options & (ulong) ~(OPTION_STATUS_NO_TRANS_UPDATE)) | OPTION_BEGIN); thd->server_status|= SERVER_STATUS_IN_TRANS; - send_ok(thd); + if (!(lex->start_transaction_opt & MYSQL_START_TRANS_OPT_WITH_CONS_SNAPSHOT) || + !(res= ha_start_consistent_snapshot(thd))) + send_ok(thd); } break; case SQLCOM_COMMIT: @@ -3626,353 +3532,11 @@ purposes internal to the MySQL server", MYF(0)); else res= -1; break; - case SQLCOM_CREATE_PROCEDURE: - case SQLCOM_CREATE_SPFUNCTION: - { - uint namelen; - char *name; - - if (!lex->sphead) - { - res= -1; // Shouldn't happen - break; - } - - if (! lex->sphead->m_db.str) - { - send_error(thd,ER_NO_DB_ERROR); - delete lex->sphead; - lex->sphead= 0; - goto error; - } - - name= lex->sphead->name(&namelen); -#ifdef HAVE_DLOPEN - if (lex->sphead->m_type == TYPE_ENUM_FUNCTION) - { - udf_func *udf = find_udf(name, namelen); - - if (udf) - { - net_printf(thd, ER_UDF_EXISTS, name); - delete lex->sphead; - lex->sphead= 0; - goto error; - } - } -#endif - if (lex->sphead->m_type == TYPE_ENUM_FUNCTION && - !lex->sphead->m_has_return) - { - net_printf(thd, ER_SP_NORETURN, name); - delete lex->sphead; - lex->sphead= 0; - goto error; - } - - res= lex->sphead->create(thd); - switch (res) { - case SP_OK: - send_ok(thd); - lex->unit.cleanup(); - delete lex->sphead; - lex->sphead= 0; - break; - case SP_WRITE_ROW_FAILED: - net_printf(thd, ER_SP_ALREADY_EXISTS, SP_TYPE_STRING(lex), name); - lex->unit.cleanup(); - delete lex->sphead; - lex->sphead= 0; - goto error; - case SP_NO_DB_ERROR: - net_printf(thd, ER_BAD_DB_ERROR, lex->sphead->m_db.str); - lex->unit.cleanup(); - delete lex->sphead; - lex->sphead= 0; - goto error; - default: - net_printf(thd, ER_SP_STORE_FAILED, SP_TYPE_STRING(lex), name); - lex->unit.cleanup(); - delete lex->sphead; - lex->sphead= 0; - goto error; - } - break; - } - case SQLCOM_CALL: - { - sp_head *sp; - - if (!(sp= sp_find_procedure(thd, lex->spname))) - { - net_printf(thd, ER_SP_DOES_NOT_EXIST, "PROCEDURE", - lex->spname->m_qname.str); - goto error; - } - else - { -#ifndef NO_EMBEDDED_ACCESS_CHECKS - st_sp_security_context save_ctx; -#endif - ha_rows select_limit; - uint smrx; - LINT_INIT(smrx); - - /* In case the arguments are subselects... */ - if (all_tables && - ((res= check_table_access(thd, SELECT_ACL, all_tables, 0)) || - (res= open_and_lock_tables(thd, all_tables)))) - { - break; - } - -#ifndef EMBEDDED_LIBRARY - /* - When executing substatements, they're assumed to send_error when - it happens, but not to send_ok. - */ - my_bool nsok= thd->net.no_send_ok; - thd->net.no_send_ok= TRUE; -#endif - if (sp->m_multi_results) - { - if (! (thd->client_capabilities & CLIENT_MULTI_RESULTS)) - { - send_error(thd, ER_SP_BADSELECT); -#ifndef EMBEDDED_LIBRARY - thd->net.no_send_ok= nsok; -#endif - goto error; - } - smrx= thd->server_status & SERVER_MORE_RESULTS_EXISTS; - thd->server_status |= SERVER_MORE_RESULTS_EXISTS; - } - -#ifndef NO_EMBEDDED_ACCESS_CHECKS - sp_change_security_context(thd, sp, &save_ctx); -#endif - select_limit= thd->variables.select_limit; - thd->variables.select_limit= HA_POS_ERROR; - - thd->row_count_func= 0; - res= sp->execute_procedure(thd, &lex->value_list); - - thd->variables.select_limit= select_limit; -#ifndef NO_EMBEDDED_ACCESS_CHECKS - sp_restore_security_context(thd, sp, &save_ctx); -#endif - -#ifndef EMBEDDED_LIBRARY - thd->net.no_send_ok= nsok; -#endif - if (sp->m_multi_results) - { - if (! smrx) - thd->server_status &= ~SERVER_MORE_RESULTS_EXISTS; - } - - if (res == 0) - send_ok(thd, (ulong) (thd->row_count_func < 0 ? 0 : thd->row_count_func)); - else - goto error; // Substatement should already have sent error - } - break; - } - case SQLCOM_ALTER_PROCEDURE: - case SQLCOM_ALTER_FUNCTION: - { - sp_head *sp; - st_sp_chistics chistics; - - memcpy(&chistics, &lex->sp_chistics, sizeof(chistics)); - if (lex->sql_command == SQLCOM_ALTER_PROCEDURE) - sp= sp_find_procedure(thd, lex->spname); - else - sp= sp_find_function(thd, lex->spname); - mysql_reset_errors(thd); - if (! sp) - res= SP_KEY_NOT_FOUND; - else - { - if (check_sp_definer_access(thd, sp)) - { - res= -1; - break; - } - memcpy(&lex->sp_chistics, &chistics, sizeof(lex->sp_chistics)); - if (lex->sql_command == SQLCOM_ALTER_PROCEDURE) - res= sp_update_procedure(thd, lex->spname, &lex->sp_chistics); - else - res= sp_update_function(thd, lex->spname, &lex->sp_chistics); - } - switch (res) - { - case SP_OK: - send_ok(thd); - break; - case SP_KEY_NOT_FOUND: - net_printf(thd, ER_SP_DOES_NOT_EXIST, SP_COM_STRING(lex), - lex->spname->m_qname.str); - goto error; - default: - net_printf(thd, ER_SP_CANT_ALTER, SP_COM_STRING(lex), - lex->spname->m_qname.str); - goto error; - } - break; - } - case SQLCOM_DROP_PROCEDURE: - case SQLCOM_DROP_FUNCTION: - { - sp_head *sp; - - if (lex->sql_command == SQLCOM_DROP_PROCEDURE) - sp= sp_find_procedure(thd, lex->spname); - else - sp= sp_find_function(thd, lex->spname); - mysql_reset_errors(thd); - if (! sp) - res= SP_KEY_NOT_FOUND; - else - { - if (check_sp_definer_access(thd, sp)) - { - res= -1; - break; - } - if (lex->sql_command == SQLCOM_DROP_PROCEDURE) - res= sp_drop_procedure(thd, lex->spname); - else - { - res= sp_drop_function(thd, lex->spname); -#ifdef HAVE_DLOPEN - if (res == SP_KEY_NOT_FOUND) - { - udf_func *udf = find_udf(lex->spname->m_name.str, - lex->spname->m_name.length); - if (udf) - { - if (check_access(thd, DELETE_ACL, "mysql", 0, 1, 0)) - goto error; - if (!(res = mysql_drop_function(thd,&lex->spname->m_name))) - { - send_ok(thd); - break; - } - } - } -#endif - } - } - switch (res) - { - case SP_OK: - send_ok(thd); - break; - case SP_KEY_NOT_FOUND: - if (lex->drop_if_exists) - { - push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, - ER_SP_DOES_NOT_EXIST, ER(ER_SP_DOES_NOT_EXIST), - SP_COM_STRING(lex), lex->spname->m_name.str); - res= 0; - send_ok(thd); - break; - } - net_printf(thd, ER_SP_DOES_NOT_EXIST, SP_COM_STRING(lex), - lex->spname->m_qname.str); - goto error; - default: - net_printf(thd, ER_SP_DROP_FAILED, SP_COM_STRING(lex), - lex->spname->m_qname.str); - goto error; - } - break; - } - case SQLCOM_SHOW_CREATE_PROC: - { - res= -1; - if (lex->spname->m_name.length > NAME_LEN) - { - net_printf(thd, ER_TOO_LONG_IDENT, lex->spname->m_name.str); - goto error; - } - res= sp_show_create_procedure(thd, lex->spname); - if (res != SP_OK) - { /* We don't distinguish between errors for now */ - net_printf(thd, ER_SP_DOES_NOT_EXIST, - SP_COM_STRING(lex), lex->spname->m_name.str); - res= 0; - goto error; - } - break; - } - case SQLCOM_SHOW_CREATE_FUNC: - { - if (lex->spname->m_name.length > NAME_LEN) - { - net_printf(thd, ER_TOO_LONG_IDENT, lex->spname->m_name.str); - goto error; - } - res= sp_show_create_function(thd, lex->spname); - if (res != SP_OK) - { /* We don't distinguish between errors for now */ - net_printf(thd, ER_SP_DOES_NOT_EXIST, - SP_COM_STRING(lex), lex->spname->m_name.str); - res= 0; - goto error; - } - res= 0; - break; - } - case SQLCOM_SHOW_STATUS_PROC: - { - res= sp_show_status_procedure(thd, (lex->wild ? - lex->wild->ptr() : NullS)); - break; - } - case SQLCOM_SHOW_STATUS_FUNC: - { - res= sp_show_status_function(thd, (lex->wild ? - lex->wild->ptr() : NullS)); - break; - } - case SQLCOM_CREATE_VIEW: - { - res= mysql_create_view(thd, thd->lex->create_view_mode); - break; - } - case SQLCOM_DROP_VIEW: - { - if (check_table_access(thd, DROP_ACL, all_tables, 0)) - goto error; - if (end_active_trans(thd)) - { - res= -1; - break; - } - res= mysql_drop_view(thd, first_table, thd->lex->drop_mode); - break; - } - case SQLCOM_CREATE_TRIGGER: - { - /* We don't care much about trigger body at that point */ - delete lex->sphead; - lex->sphead= 0; - - res= mysql_create_or_drop_trigger(thd, all_tables, 1); - break; - } - case SQLCOM_DROP_TRIGGER: - { - res= mysql_create_or_drop_trigger(thd, all_tables, 0); - break; - } default: /* Impossible */ send_ok(thd); break; } - thd->proc_info="query end"; + thd->proc_info="query end"; // QQ if (thd->one_shot_set) { /* @@ -3997,38 +3561,11 @@ purposes internal to the MySQL server", MYF(0)); thd->one_shot_set= 0; } } - - /* - The return value for ROW_COUNT() is "implementation dependent" if - the statement is not DELETE, INSERT or UPDATE (or a CALL executing - such a statement), but -1 is what JDBC and ODBC wants. - */ - switch (lex->sql_command) { - case SQLCOM_UPDATE: - case SQLCOM_UPDATE_MULTI: - case SQLCOM_REPLACE: - case SQLCOM_INSERT: - case SQLCOM_REPLACE_SELECT: - case SQLCOM_INSERT_SELECT: - case SQLCOM_DELETE: - case SQLCOM_DELETE_MULTI: - case SQLCOM_CALL: - break; - default: - thd->row_count_func= -1; - } - - /* - We end up here if res == 0 and send_ok() has been done, - or res != 0 and no send_error() has yet been done. - */ if (res < 0) - send_error(thd,thd->killed_errno()); - DBUG_RETURN(res); + send_error(thd,thd->killed ? ER_SERVER_SHUTDOWN : 0); error: - /* We end up here if send_error() has already been done. */ - DBUG_RETURN(-1); + DBUG_VOID_RETURN; } @@ -4039,29 +3576,28 @@ error: SYNOPSIS check_one_table_access() thd Thread handler - privilege requested privilege - all_tables global table list of query + privilege requested privelage + tables table list of command RETURN 0 - OK 1 - access denied, error is sent to client */ -bool check_one_table_access(THD *thd, ulong privilege, TABLE_LIST *all_tables) +int check_one_table_access(THD *thd, ulong privilege, TABLE_LIST *tables) { - if (check_access(thd, privilege, all_tables->db, - &all_tables->grant.privilege, 0, 0)) + if (check_access(thd, privilege, tables->db, &tables->grant.privilege,0,0)) return 1; /* Show only 1 table for check_grant */ - if (grant_option && check_grant(thd, privilege, all_tables, 0, 1, 0)) + if (grant_option && check_grant(thd, privilege, tables, 0, 1, 0)) return 1; /* Check rights on tables of subselect (if exists) */ TABLE_LIST *subselects_tables; - if ((subselects_tables= all_tables->next_global)) + if ((subselects_tables= tables->next)) { - if ((check_table_access(thd, SELECT_ACL, subselects_tables, 0))) + if ((check_table_access(thd, SELECT_ACL, subselects_tables,0))) return 1; } return 0; @@ -4091,13 +3627,13 @@ bool check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv, bool dont_check_global_grants, bool no_errors) { + DBUG_ENTER("check_access"); + DBUG_PRINT("enter",("db: '%s' want_access: %lu master_access: %lu", + db ? db : "", want_access, thd->master_access)); #ifndef NO_EMBEDDED_ACCESS_CHECKS ulong db_access; #endif ulong dummy; - DBUG_ENTER("check_access"); - DBUG_PRINT("enter",("db: %s want_access: %lu master_access: %lu", - db ? db : "", want_access, thd->master_access)); if (save_priv) *save_priv=0; else @@ -4105,9 +3641,8 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv, if ((!db || !db[0]) && !thd->db && !dont_check_global_grants) { - DBUG_PRINT("error",("No database")); if (!no_errors) - send_error(thd,ER_NO_DB_ERROR); /* purecov: tested */ + send_error(thd,ER_NO_DB_ERROR); /* purecov: tested */ DBUG_RETURN(TRUE); /* purecov: tested */ } @@ -4132,7 +3667,6 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv, if (((want_access & ~thd->master_access) & ~(DB_ACLS | EXTRA_ACL)) || ! db && dont_check_global_grants) { // We can never grant this - DBUG_PRINT("error",("No possible access")); if (!no_errors) net_printf(thd,ER_ACCESS_DENIED_ERROR, thd->priv_user, @@ -4152,17 +3686,13 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv, DBUG_PRINT("info",("db_access: %lu", db_access)); /* Remove SHOW attribute and access rights we already have */ want_access &= ~(thd->master_access | EXTRA_ACL); - DBUG_PRINT("info",("db_access: %lu want_access: %lu", - db_access, want_access)); db_access= ((*save_priv=(db_access | thd->master_access)) & want_access); /* grant_option is set if there exists a single table or column grant */ if (db_access == want_access || - (grant_option && !dont_check_global_grants && + ((grant_option && !dont_check_global_grants) && !(want_access & ~(db_access | TABLE_ACLS)))) DBUG_RETURN(FALSE); /* Ok */ - - DBUG_PRINT("error",("Access denied")); if (!no_errors) net_printf(thd,ER_DBACCESS_DENIED_ERROR, thd->priv_user, @@ -4182,7 +3712,7 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv, want_access Use should have any of these global rights WARNING - One gets access right if one has ANY of the rights in want_access + One gets access rigth if one has ANY of the rights in want_access This is useful as one in most cases only need one global right, but in some case we want to check if the user has SUPER or REPL_CLIENT_ACL rights. @@ -4220,7 +3750,7 @@ check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables, uint found=0; ulong found_access=0; TABLE_LIST *org_tables=tables; - for (; tables; tables= tables->next_global) + for (; tables ; tables=tables->next) { if (tables->derived || (tables->table && (int)tables->table->tmp_table) || @@ -4253,42 +3783,6 @@ check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables, return FALSE; } - -/* - Check if the given table has any of the asked privileges - - SYNOPSIS - check_some_access() - thd Thread handler - want_access Bitmap of possible privileges to check for - - RETURN - 0 ok - 1 error -*/ - - -bool check_some_access(THD *thd, ulong want_access, TABLE_LIST *table) -{ - ulong access; - DBUG_ENTER("check_some_access"); - - /* This loop will work as long as we have less than 32 privileges */ - for (access= 1; access < want_access ; access<<= 1) - { - if (access & want_access) - { - if (!check_access(thd, access, table->db, - &table->grant.privilege, 0, 1) && - !grant_option || !check_grant(thd, access, table, 0, 1, 1)) - DBUG_RETURN(0); - } - } - DBUG_PRINT("exit",("no matching access rights")); - DBUG_RETURN(1); -} - - bool check_merge_table_access(THD *thd, char *db, TABLE_LIST *table_list) { @@ -4297,7 +3791,7 @@ bool check_merge_table_access(THD *thd, char *db, { /* Check that all tables use the current database */ TABLE_LIST *tmp; - for (tmp= table_list; tmp; tmp= tmp->next_local) + for (tmp=table_list; tmp ; tmp=tmp->next) { if (!tmp->db || !tmp->db[0]) tmp->db=db; @@ -4311,7 +3805,7 @@ bool check_merge_table_access(THD *thd, char *db, static bool check_db_used(THD *thd,TABLE_LIST *tables) { - for (; tables; tables= tables->next_global) + for (; tables ; tables=tables->next) { if (!tables->db) { @@ -4325,41 +3819,6 @@ static bool check_db_used(THD *thd,TABLE_LIST *tables) return FALSE; } - -/* - Check if the given SP is owned by thd->priv_user/host, or priv_user is root. - QQ This is not quite complete, but it will do as a basic security check - for now. The question is exactly which rights should 'root' have? - Should root have access regardless of host for instance? - - SYNOPSIS - check_sp_definer_access() - thd Thread handler - sp The SP pointer - - RETURN - 0 ok - 1 error Error message has been sent -*/ - -static bool -check_sp_definer_access(THD *thd, sp_head *sp) -{ - LEX_STRING *usr, *hst; - - if (strcmp("root", thd->priv_user) == 0) - return FALSE; /* QQ Any root is ok now */ - usr= &sp->m_definer_user; - hst= &sp->m_definer_host; - if (strncmp(thd->priv_user, usr->str, usr->length) == 0 && - strncmp(thd->priv_host, hst->str, hst->length) == 0) - return FALSE; /* Both user and host must match */ - - my_error(ER_SP_ACCESS_DENIED_ERROR, MYF(0), sp->m_qname.str); - return TRUE; /* Not definer or root */ -} - - /**************************************************************************** Check stack size; Send error if there isn't enough stack to continue ****************************************************************************/ @@ -4424,7 +3883,6 @@ bool my_yyoverflow(short **yyss, YYSTYPE **yyvs, ulong *yystacksize) return 0; } - /**************************************************************************** Initialize global thd variables needed for query ****************************************************************************/ @@ -4457,13 +3915,13 @@ void mysql_reset_thd_for_next_command(THD *thd) DBUG_ENTER("mysql_reset_thd_for_next_command"); thd->free_list= 0; thd->select_number= 1; - thd->total_warn_count=0; // Warnings for this query + thd->total_warn_count= 0; // Warnings for this query thd->last_insert_id_used= thd->query_start_used= thd->insert_id_used=0; thd->sent_row_count= thd->examined_row_count= 0; thd->is_fatal_error= thd->rand_used= thd->time_zone_used= 0; thd->server_status&= ~ (SERVER_MORE_RESULTS_EXISTS | - SERVER_QUERY_NO_INDEX_USED | - SERVER_QUERY_NO_GOOD_INDEX_USED); + SERVER_QUERY_NO_INDEX_USED | + SERVER_QUERY_NO_GOOD_INDEX_USED); thd->tmp_table_used= 0; if (opt_bin_log) reset_dynamic(&thd->user_var_events); @@ -4482,6 +3940,7 @@ mysql_init_select(LEX *lex) { DBUG_ASSERT(lex->result == 0); lex->exchange= 0; + lex->proc_list.first= 0; } } @@ -4495,7 +3954,6 @@ mysql_new_select(LEX *lex, bool move_down) select_lex->select_number= ++lex->thd->select_number; select_lex->init_query(); select_lex->init_select(); - select_lex->parent_lex= lex; if (move_down) { /* first select_lex of subselect or derived table */ @@ -4511,15 +3969,10 @@ mysql_new_select(LEX *lex, bool move_down) unit->link_prev= 0; unit->return_to= lex->current_select; select_lex->include_down(unit); - /* TODO: assign resolve_mode for fake subquery after merging with new tree */ + // TODO: assign resolve_mode for fake subquery after merging with new tree } else { - if (lex->current_select->order_list.first && !lex->current_select->braces) - { - net_printf(lex->thd, ER_WRONG_USAGE, "UNION", "ORDER BY"); - return 1; - } select_lex->include_neighbour(lex->current_select); SELECT_LEX_UNIT *unit= select_lex->master_unit(); SELECT_LEX *fake= unit->fake_select_lex; @@ -4587,8 +4040,6 @@ void mysql_init_multi_delete(LEX *lex) lex->select_lex.select_limit= lex->unit.select_limit_cnt= HA_POS_ERROR; lex->select_lex.table_list.save_and_clear(&lex->auxilliary_table_list); - lex->query_tables= 0; - lex->query_tables_last= &lex->query_tables; } @@ -4617,42 +4068,22 @@ void mysql_parse(THD *thd, char *inBuf, uint length) #endif { if (thd->net.report_error) - { send_error(thd, 0, NullS); - if (thd->lex->sphead) - { - if (lex != thd->lex) - thd->lex->sphead->restore_lex(thd); - delete thd->lex->sphead; - thd->lex->sphead= NULL; - } - } else { mysql_execute_command(thd); query_cache_end_of_result(thd); } } - lex->unit.cleanup(); } else { DBUG_PRINT("info",("Command aborted. Fatal_error: %d", thd->is_fatal_error)); query_cache_abort(&thd->net); - lex->unit.cleanup(); - if (thd->lex->sphead) - { - /* Clean up after failed stored procedure/function */ - if (lex != thd->lex) - thd->lex->sphead->restore_lex(thd); - delete thd->lex->sphead; - thd->lex->sphead= NULL; - } } thd->proc_info="freeing items"; thd->end_statement(); - thd->cleanup_after_query(); DBUG_ASSERT(thd->change_list.is_empty()); } DBUG_VOID_RETURN; @@ -4673,20 +4104,17 @@ bool mysql_test_parse_for_slave(THD *thd, char *inBuf, uint length) { LEX *lex= thd->lex; bool error= 0; - DBUG_ENTER("mysql_test_parse_for_slave"); mysql_init_query(thd, (uchar*) inBuf, length); if (!yyparse((void*) thd) && ! thd->is_fatal_error && all_tables_not_ok(thd,(TABLE_LIST*) lex->select_lex.table_list.first)) - error= 1; /* Ignore question */ + error= 1; /* Ignore question */ thd->end_statement(); - thd->cleanup_after_query(); - DBUG_RETURN(error); + return error; } #endif - /* Calculate interval lengths. Strip trailing spaces from all strings. @@ -4728,7 +4156,6 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type, register create_field *new_field; LEX *lex= thd->lex; uint allowed_type_modifier=0; - uint sign_len; char warn_buff[MYSQL_ERRMSG_SIZE]; DBUG_ENTER("add_field_to_list"); @@ -4820,19 +4247,9 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type, new_field->comment.str= (char*) comment->str; new_field->comment.length=comment->length; } - /* - Set flag if this field doesn't have a default value - Enum values has always the first value as a default (set in - make_empty_rec(). - */ - if (!default_value && !(type_modifier & AUTO_INCREMENT_FLAG) && - (type_modifier & NOT_NULL_FLAG) && type != FIELD_TYPE_TIMESTAMP && - type != FIELD_TYPE_ENUM) - new_field->flags|= NO_DEFAULT_VALUE_FLAG; - if (length && !(new_field->length= (uint) atoi(length))) length=0; /* purecov: inspected */ - sign_len=type_modifier & UNSIGNED_FLAG ? 0 : 1; + uint sign_len=type_modifier & UNSIGNED_FLAG ? 0 : 1; if (new_field->length && new_field->decimals && new_field->length < new_field->decimals+1 && @@ -4885,7 +4302,7 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type, new_field->sql_type= FIELD_TYPE_BLOB; sprintf(warn_buff, ER(ER_AUTO_CONVERT), field_name, "CHAR", (cs == &my_charset_bin) ? "BLOB" : "TEXT"); - push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_AUTO_CONVERT, + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_AUTO_CONVERT, warn_buff); /* fall through */ case FIELD_TYPE_BLOB: @@ -5006,11 +4423,11 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type, If we have TIMESTAMP NULL column without explicit DEFAULT value we treat it as having DEFAULT NULL attribute. */ - new_field->unireg_check= (on_update_value ? - Field::TIMESTAMP_UN_FIELD : - (new_field->flags & NOT_NULL_FLAG ? - Field::TIMESTAMP_OLD_FIELD: - Field::NONE)); + new_field->unireg_check= on_update_value ? + Field::TIMESTAMP_UN_FIELD : + (new_field->flags & NOT_NULL_FLAG ? + Field::TIMESTAMP_OLD_FIELD: + Field::NONE); } break; case FIELD_TYPE_DATE: // Old date type @@ -5184,7 +4601,6 @@ bool add_to_list(THD *thd, SQL_LIST &list,Item *item,bool asc) order->asc = asc; order->free_me=0; order->used=0; - order->counter_used= 0; list.link_in_list((byte*) order,(byte**) &order->next); DBUG_RETURN(0); } @@ -5220,7 +4636,6 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd, { register TABLE_LIST *ptr; char *alias_str; - LEX *lex= thd->lex; DBUG_ENTER("add_table_to_list"); if (!table) @@ -5274,7 +4689,6 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd, ptr->force_index= test(table_options & TL_OPTION_FORCE_INDEX); ptr->ignore_leaves= test(table_options & TL_OPTION_IGNORE_LEAVES); ptr->derived= table->sel; - ptr->select_lex= lex->current_select; ptr->cacheable_table= 1; if (use_index_arg) ptr->use_index=(List<String> *) thd->memdup((gptr) use_index_arg, @@ -5288,7 +4702,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd, { for (TABLE_LIST *tables=(TABLE_LIST*) table_list.first ; tables ; - tables=tables->next_local) + tables=tables->next) { if (!my_strcasecmp(table_alias_charset, alias_str, tables->alias) && !strcmp(ptr->db, tables->db)) @@ -5298,246 +4712,12 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd, } } } - /* Link table in local list (list for current select) */ - table_list.link_in_list((byte*) ptr, (byte**) &ptr->next_local); - /* Link table in global list (all used tables) */ - lex->add_to_query_tables(ptr); - DBUG_RETURN(ptr); -} - - -/* - Initialize a new table list for a nested join - - SYNOPSIS - init_table_list() - thd current thread - - DESCRIPTION - The function initializes a structure of the TABLE_LIST type - for a nested join. It sets up its nested join list as empty. - The created structure is added to the front of the current - join list in the st_select_lex object. Then the function - changes the current nest level for joins to refer to the newly - created empty list after having saved the info on the old level - in the initialized structure. - - RETURN VALUE - 0, if success - 1, otherwise -*/ - -bool st_select_lex::init_nested_join(THD *thd) -{ - TABLE_LIST *ptr; - NESTED_JOIN *nested_join; - DBUG_ENTER("init_nested_join"); - - if (!(ptr = (TABLE_LIST *) thd->calloc(sizeof(TABLE_LIST))) || - !(nested_join= ptr->nested_join= - (NESTED_JOIN *) thd->calloc(sizeof(NESTED_JOIN)))) - DBUG_RETURN(1); - join_list->push_front(ptr); - ptr->embedding= embedding; - ptr->join_list= join_list; - embedding= ptr; - join_list= &nested_join->join_list; - join_list->empty(); - DBUG_RETURN(0); -} - - -/* - End a nested join table list - - SYNOPSIS - end_nested_join() - thd current thread - - DESCRIPTION - The function returns to the previous join nest level. - If the current level contains only one member, the function - moves it one level up, eliminating the nest. - - RETURN VALUE - Pointer to TABLE_LIST element added to the total table list, if success - 0, otherwise -*/ - -TABLE_LIST *st_select_lex::end_nested_join(THD *thd) -{ - TABLE_LIST *ptr; - DBUG_ENTER("end_nested_join"); - ptr= embedding; - join_list= ptr->join_list; - embedding= ptr->embedding; - NESTED_JOIN *nested_join= ptr->nested_join; - if (nested_join->join_list.elements == 1) - { - TABLE_LIST *embedded= nested_join->join_list.head(); - join_list->pop(); - embedded->join_list= join_list; - embedded->embedding= embedding; - join_list->push_front(embedded); - ptr= embedded; - } - DBUG_RETURN(ptr); -} - - -/* - Nest last join operation - - SYNOPSIS - nest_last_join() - thd current thread - - DESCRIPTION - The function nest last join operation as if it was enclosed in braces. - - RETURN VALUE - Pointer to TABLE_LIST element created for the new nested join, if success - 0, otherwise -*/ - -TABLE_LIST *st_select_lex::nest_last_join(THD *thd) -{ - TABLE_LIST *ptr; - NESTED_JOIN *nested_join; - DBUG_ENTER("nest_last_join"); - - if (!(ptr = (TABLE_LIST *) thd->calloc(sizeof(TABLE_LIST))) || - !(nested_join= ptr->nested_join= - (NESTED_JOIN *) thd->calloc(sizeof(NESTED_JOIN)))) - DBUG_RETURN(0); - ptr->embedding= embedding; - ptr->join_list= join_list; - List<TABLE_LIST> *embedded_list= &nested_join->join_list; - embedded_list->empty(); - for (int i=0; i < 2; i++) - { - TABLE_LIST *table= join_list->pop(); - table->join_list= embedded_list; - table->embedding= ptr; - embedded_list->push_back(table); - } - join_list->push_front(ptr); - nested_join->used_tables= nested_join->not_null_tables= (table_map) 0; + table_list.link_in_list((byte*) ptr, (byte**) &ptr->next); DBUG_RETURN(ptr); } /* - Save names for a join with using clause - - SYNOPSIS - save_names_for_using_list - tab1 left table in join - tab2 right table in join - - DESCRIPTION - The function saves the full names of the tables in st_select_lex - to be able to build later an on expression to replace the using clause. - - RETURN VALUE - None -*/ - -void st_select_lex::save_names_for_using_list(TABLE_LIST *tab1, - TABLE_LIST *tab2) -{ - while (tab1->nested_join) - { - tab1= tab1->nested_join->join_list.head(); - } - db1= tab1->db; - table1= tab1->alias; - while (tab2->nested_join) - { - TABLE_LIST *next; - List_iterator_fast<TABLE_LIST> it(tab2->nested_join->join_list); - tab2= it++; - while ((next= it++)) - tab2= next; - } - db2= tab2->db; - table2= tab2->alias; -} - - -/* - Add a table to the current join list - - SYNOPSIS - add_joined_table() - table the table to add - - DESCRIPTION - The function puts a table in front of the current join list - of st_select_lex object. - Thus, joined tables are put into this list in the reverse order - (the most outer join operation follows first). - - RETURN VALUE - None -*/ - -void st_select_lex::add_joined_table(TABLE_LIST *table) -{ - DBUG_ENTER("add_joined_table"); - join_list->push_front(table); - table->join_list= join_list; - table->embedding= embedding; - DBUG_VOID_RETURN; -} - - -/* - Convert a right join into equivalent left join - - SYNOPSIS - convert_right_join() - thd current thread - - DESCRIPTION - The function takes the current join list t[0],t[1] ... and - effectively converts it into the list t[1],t[0] ... - Although the outer_join flag for the new nested table contains - JOIN_TYPE_RIGHT, it will be handled as the inner table of a left join - operation. - - EXAMPLES - SELECT * FROM t1 RIGHT JOIN t2 ON on_expr => - SELECT * FROM t2 LEFT JOIN t1 ON on_expr - - SELECT * FROM t1,t2 RIGHT JOIN t3 ON on_expr => - SELECT * FROM t1,t3 LEFT JOIN t2 ON on_expr - - SELECT * FROM t1,t2 RIGHT JOIN (t3,t4) ON on_expr => - SELECT * FROM t1,(t3,t4) LEFT JOIN t2 ON on_expr - - SELECT * FROM t1 LEFT JOIN t2 ON on_expr1 RIGHT JOIN t3 ON on_expr2 => - SELECT * FROM t3 LEFT JOIN (t1 LEFT JOIN t2 ON on_expr2) ON on_expr1 - - RETURN - Pointer to the table representing the inner table, if success - 0, otherwise -*/ - -TABLE_LIST *st_select_lex::convert_right_join() -{ - TABLE_LIST *tab2= join_list->pop(); - TABLE_LIST *tab1= join_list->pop(); - DBUG_ENTER("convert_right_join"); - - join_list->push_front(tab2); - join_list->push_front(tab1); - tab1->outer_join|= JOIN_TYPE_RIGHT; - - DBUG_RETURN(tab1); -} - -/* Set lock for all tables in current select level SYNOPSIS: @@ -5557,9 +4737,9 @@ void st_select_lex::set_lock_for_tables(thr_lock_type lock_type) DBUG_PRINT("enter", ("lock_type: %d for_update: %d", lock_type, for_update)); - for (TABLE_LIST *tables= (TABLE_LIST*) table_list.first; - tables; - tables= tables->next_local) + for (TABLE_LIST *tables= (TABLE_LIST*) table_list.first ; + tables ; + tables=tables->next) { tables->lock_type= lock_type; tables->updating= for_update; @@ -5576,7 +4756,7 @@ void add_join_on(TABLE_LIST *b,Item *expr) b->on_expr=expr; else { - /* This only happens if you have both a right and left join */ + // This only happens if you have both a right and left join b->on_expr=new Item_cond_and(b->on_expr,expr); } b->on_expr->top_level_item(); @@ -5591,7 +4771,7 @@ void add_join_on(TABLE_LIST *b,Item *expr) add_join_natural() a Table to do normal join with b Do normal join with this table - + IMPLEMENTATION This function just marks that table b should be joined with a. The function setup_cond() will create in b->on_expr a list @@ -5656,6 +4836,7 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables, */ tmp_write_to_binlog= 0; mysql_log.new_file(1); + mysql_update_log.new_file(1); mysql_bin_log.new_file(1); mysql_slow_log.new_file(1); #ifdef HAVE_REPLICATION @@ -5678,7 +4859,7 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables, if (options & REFRESH_QUERY_CACHE_FREE) { query_cache.pack(); // FLUSH QUERY CACHE - options &= ~REFRESH_QUERY_CACHE; // Don't flush cache, just free memory + options &= ~REFRESH_QUERY_CACHE; //don't flush all cache, just free memory } if (options & (REFRESH_TABLES | REFRESH_QUERY_CACHE)) { @@ -5758,7 +4939,7 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables, This is written such that we have a short lock on LOCK_thread_count */ -void kill_one_thread(THD *thd, ulong id, bool only_kill_query) +void kill_one_thread(THD *thd, ulong id) { THD *tmp; uint error=ER_NO_SUCH_THREAD; @@ -5778,7 +4959,7 @@ void kill_one_thread(THD *thd, ulong id, bool only_kill_query) if ((thd->master_access & SUPER_ACL) || !strcmp(thd->user,tmp->user)) { - tmp->awake(only_kill_query ? THD::KILL_QUERY : THD::KILL_CONNECTION); + tmp->awake(1 /*prepare to die*/); error=0; } else @@ -5812,13 +4993,6 @@ static void refresh_status(void) (char*) &dflt_key_cache_var)); *(ulong*) value= 0; } - else if (ptr->type == SHOW_LONG_STATUS) - { - THD *thd= current_thd; - /* We must update the global status before cleaning up the thread */ - add_to_status(&global_status_var, &thd->status_var); - bzero((char*) &thd->status_var, sizeof(thd->status_var)); - } } pthread_mutex_unlock(&LOCK_status); } @@ -5963,6 +5137,7 @@ int mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys) List<create_field> fields; ALTER_INFO alter_info; alter_info.flags= ALTER_ADD_INDEX; + alter_info.is_simple= 0; HA_CREATE_INFO create_info; DBUG_ENTER("mysql_create_index"); bzero((char*) &create_info,sizeof(create_info)); @@ -5986,6 +5161,7 @@ int mysql_drop_index(THD *thd, TABLE_LIST *table_list, ALTER_INFO *alter_info) create_info.default_table_charset= thd->variables.collation_database; alter_info->clear(); alter_info->flags= ALTER_DROP_INDEX; + alter_info->is_simple= 0; DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->real_name, &create_info, table_list, fields, keys, 0, (ORDER*)0, @@ -5999,7 +5175,7 @@ int mysql_drop_index(THD *thd, TABLE_LIST *table_list, ALTER_INFO *alter_info) SYNOPSIS multi_update_precheck() thd Thread handler - tables Global/local table list (have to be the same) + tables Global table list RETURN VALUE 0 OK @@ -6009,11 +5185,12 @@ int mysql_drop_index(THD *thd, TABLE_LIST *table_list, ALTER_INFO *alter_info) int multi_update_precheck(THD *thd, TABLE_LIST *tables) { + DBUG_ENTER("multi_update_precheck"); const char *msg= 0; TABLE_LIST *table; LEX *lex= thd->lex; SELECT_LEX *select_lex= &lex->select_lex; - DBUG_ENTER("multi_update_precheck"); + TABLE_LIST *update_list= (TABLE_LIST*)select_lex->table_list.first; if (select_lex->item_list.elements != lex->value_list.elements) { @@ -6024,7 +5201,7 @@ int multi_update_precheck(THD *thd, TABLE_LIST *tables) Ensure that we have UPDATE or SELECT privilege for each table The exact privilege is checked in mysql_multi_update() */ - for (table= tables; table; table= table->next_local) + for (table= update_list; table; table= table->next) { if (table->derived) table->grant.privilege= SELECT_ACL; @@ -6032,12 +5209,17 @@ int multi_update_precheck(THD *thd, TABLE_LIST *tables) &table->grant.privilege, 0, 1) || grant_option && check_grant(thd, UPDATE_ACL, table, 0, 1, 1)) && - (check_access(thd, SELECT_ACL, table->db, - &table->grant.privilege, 0, 0) || - grant_option && check_grant(thd, SELECT_ACL, table, 0, 1, 0))) + (check_access(thd, SELECT_ACL, table->db, + &table->grant.privilege, 0, 0) || + grant_option && check_grant(thd, SELECT_ACL, table, 0, 1, 0))) DBUG_RETURN(1); - table->table_in_first_from_clause= 1; + /* + We assign following flag only to copy of table, because it will + be checked only if query contains subqueries i.e. only if copy exists + */ + if (table->table_list) + table->table_list->table_in_update_from_clause= 1; } /* Is there tables of subqueries? @@ -6045,9 +5227,19 @@ int multi_update_precheck(THD *thd, TABLE_LIST *tables) if (&lex->select_lex != lex->all_selects_list) { DBUG_PRINT("info",("Checking sub query list")); - for (table= tables; table; table= table->next_global) + for (table= tables; table; table= table->next) { - if (!table->table_in_first_from_clause && table->derived) + if (table->table_in_update_from_clause) + { + /* + If we check table by local TABLE_LIST copy then we should copy + grants to global table list, because it will be used for table + opening. + */ + if (table->table_list) + table->grant= table->table_list->grant; + } + else if (!table->derived) { if (check_access(thd, SELECT_ACL, table->db, &table->grant.privilege, 0, 0) || @@ -6076,7 +5268,7 @@ int multi_update_precheck(THD *thd, TABLE_LIST *tables) SYNOPSIS multi_delete_precheck() thd Thread handler - tables Global/local table list + tables Global table list table_count Pointer to table counter RETURN VALUE @@ -6086,11 +5278,12 @@ int multi_update_precheck(THD *thd, TABLE_LIST *tables) */ int multi_delete_precheck(THD *thd, TABLE_LIST *tables, uint *table_count) { + DBUG_ENTER("multi_delete_precheck"); SELECT_LEX *select_lex= &thd->lex->select_lex; TABLE_LIST *aux_tables= (TABLE_LIST *)thd->lex->auxilliary_table_list.first; + TABLE_LIST *delete_tables= (TABLE_LIST *)select_lex->table_list.first; TABLE_LIST *target_tbl; - DBUG_ENTER("multi_delete_precheck"); *table_count= 0; @@ -6105,12 +5298,12 @@ int multi_delete_precheck(THD *thd, TABLE_LIST *tables, uint *table_count) my_error(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE, MYF(0)); DBUG_RETURN(-1); } - for (target_tbl= aux_tables; target_tbl; target_tbl= target_tbl->next_local) + for (target_tbl= aux_tables; target_tbl; target_tbl= target_tbl->next) { (*table_count)++; /* All tables in aux_tables must be found in FROM PART */ TABLE_LIST *walk; - for (walk= tables; walk; walk= walk->next_local) + for (walk= delete_tables; walk; walk= walk->next) { if (!my_strcasecmp(table_alias_charset, target_tbl->alias, walk->alias) && @@ -6123,8 +5316,14 @@ int multi_delete_precheck(THD *thd, TABLE_LIST *tables, uint *table_count) "MULTI DELETE"); DBUG_RETURN(-1); } + if (walk->derived) + { + my_error(ER_NON_UPDATABLE_TABLE, MYF(0), target_tbl->real_name, + "DELETE"); + DBUG_RETURN(-1); + } walk->lock_type= target_tbl->lock_type; - target_tbl->correspondent_table= walk; // Remember corresponding table + target_tbl->table_list= walk; // Remember corresponding table } DBUG_RETURN(0); } @@ -6228,9 +5427,9 @@ int insert_precheck(THD *thd, TABLE_LIST *tables) LEX *lex= thd->lex; DBUG_ENTER("insert_precheck"); - ulong privilege= (INSERT_ACL | - (lex->duplicates == DUP_REPLACE ? DELETE_ACL : 0) | - (lex->value_list.elements ? UPDATE_ACL : 0)); + ulong privilege= INSERT_ACL | + (lex->duplicates == DUP_REPLACE ? DELETE_ACL : 0) | + (lex->duplicates == DUP_UPDATE ? UPDATE_ACL : 0); if (check_one_table_access(thd, privilege, tables)) DBUG_RETURN(1); @@ -6285,24 +5484,33 @@ int create_table_precheck(THD *thd, TABLE_LIST *tables, /* Check permissions for used tables in CREATE TABLE ... SELECT */ /* - Only do the check for PS, becasue we on execute we have to check that - against the opened tables to ensure we don't use a table that is part - of the view (which can only be done after the table has been opened). + For temporary tables or PREPARED STATEMETNS we don't have to check + if the created table exists */ - if (thd->current_arena->is_stmt_prepare()) + if (!(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) && + ! thd->current_arena->is_stmt_prepare() && + find_real_table_in_list(tables, create_table->db, + create_table->real_name)) { - /* - For temporary tables we don't have to check if the created table exists - */ - if (!(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) && - find_table_in_global_list(tables, create_table->db, - create_table->real_name)) - { - net_printf(thd,ER_UPDATE_TABLE_USED, create_table->real_name); + net_printf(thd,ER_UPDATE_TABLE_USED, create_table->real_name); - goto err; - } + goto err; } + if (lex->create_info.used_fields & HA_CREATE_USED_UNION) + { + TABLE_LIST *tab; + for (tab= tables; tab; tab= tab->next) + { + if (find_real_table_in_list((TABLE_LIST*) lex->create_info. + merge_list.first, + tables->db, tab->real_name)) + { + net_printf(thd, ER_UPDATE_TABLE_USED, tab->real_name); + goto err; + } + } + } + if (tables && check_table_access(thd, SELECT_ACL, tables,0)) goto err; } @@ -6318,7 +5526,7 @@ err: SYNOPSIS negate_expression() - thd thread handler + thd therad handler expr expression for negation RETURN diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 309a9249d0e..d842b4b66bb 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -35,10 +35,6 @@ #include "sql_acl.h" #include "lex_symbol.h" #include "item_create.h" -#include "sp_head.h" -#include "sp_pcontext.h" -#include "sp_rcontext.h" -#include "sp.h" #include <myisam.h> #include <myisammrg.h> @@ -87,14 +83,10 @@ inline Item *or_or_concat(THD *thd, Item* A, Item* B) enum Item_udftype udf_type; CHARSET_INFO *charset; thr_lock_type lock_type; - interval_type interval, interval_time_st; + interval_type interval; timestamp_type date_time_type; st_select_lex *select_lex; chooser_compare_func_creator boolfunc2creator; - struct sp_cond_type *spcondtype; - struct { int vars, conds, hndlrs, curs; } spblock; - sp_name *spname; - struct st_lex *lex; } %{ @@ -135,18 +127,16 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token AVG_SYM %token BEGIN_SYM %token BINLOG_SYM -%token CALL_SYM %token CHANGE %token CLIENT_SYM %token COMMENT_SYM %token COMMIT_SYM +%token CONSISTENT_SYM %token COUNT_SYM %token CREATE %token CROSS %token CUBE_SYM -%token DEFINER_SYM %token DELETE_SYM -%token DETERMINISTIC_SYM %token DUAL_SYM %token DO_SYM %token DROP @@ -176,7 +166,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token SELECT_SYM %token SHOW %token SLAVE -%token SQL_SYM +%token SNAPSHOT_SYM %token SQL_THREAD %token START_SYM %token STD_SYM @@ -192,7 +182,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token ACTION %token AGGREGATE_SYM -%token ALGORITHM_SYM %token ALL %token AND_SYM %token AS @@ -211,7 +200,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token BYTE_SYM %token CACHE_SYM %token CASCADE -%token CASCADED %token CAST_SYM %token CHARSET %token CHECKSUM_SYM @@ -222,16 +210,11 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token COLUMNS %token COLUMN_SYM %token CONCURRENT -%token CONDITION_SYM -%token CONNECTION_SYM %token CONSTRAINT -%token CONTAINS_SYM -%token CONTINUE_SYM %token CONVERT_SYM %token CURRENT_USER %token DATABASES %token DATA_SYM -%token DECLARE_SYM %token DEFAULT %token DELAYED_SYM %token DELAY_KEY_WRITE_SYM @@ -243,24 +226,20 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token DISTINCT %token DUPLICATE_SYM %token DYNAMIC_SYM -%token EACH_SYM %token ENABLE_SYM %token ENCLOSED %token ESCAPED %token DIRECTORY_SYM %token ESCAPE_SYM %token EXISTS -%token EXIT_SYM %token EXTENDED_SYM %token FALSE_SYM -%token FETCH_SYM %token FILE_SYM %token FIRST_SYM %token FIXED_SYM %token FLOAT_NUM %token FORCE_SYM %token FOREIGN -%token FOUND_SYM %token FROM %token FULL %token FULLTEXT_SYM @@ -283,10 +262,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token INFILE %token INNER_SYM %token INNOBASE_SYM -%token INOUT_SYM %token INTO %token IN_SYM -%token INVOKER_SYM %token ISOLATION %token JOIN_SYM %token KEYS @@ -296,17 +273,14 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token LEAVES %token LEVEL_SYM %token LEX_HOSTNAME -%token LANGUAGE_SYM %token LIKE %token LINES %token LOCAL_SYM -%token LOCATOR_SYM %token LOG_SYM %token LOGS_SYM %token LONG_NUM %token LONG_SYM %token LOW_PRIORITY -%token MERGE_SYM %token MASTER_HOST_SYM %token MASTER_USER_SYM %token MASTER_LOG_FILE_SYM @@ -331,7 +305,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token MEDIUM_SYM %token MIN_ROWS %token NAMES_SYM -%token NAME_SYM %token NATIONAL_SYM %token NATURAL %token NDBCLUSTER_SYM @@ -352,7 +325,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token OR_SYM %token OR_OR_CONCAT %token ORDER_SYM -%token OUT_SYM %token OUTER %token OUTFILE %token DUMPFILE @@ -369,7 +341,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token RAID_CHUNKS %token RAID_CHUNKSIZE %token READ_SYM -%token READS_SYM %token REAL_NUM %token REFERENCES %token REGEXP @@ -385,7 +356,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token ROW_FORMAT_SYM %token ROW_SYM %token RTREE_SYM -%token SECURITY_SYM %token SET %token SEPARATOR_SYM %token SERIAL_SYM @@ -394,10 +364,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token SIMPLE_SYM %token SHUTDOWN %token SPATIAL_SYM -%token SPECIFIC_SYM -%token SQLEXCEPTION_SYM -%token SQLSTATE_SYM -%token SQLWARNING_SYM %token SSL_SYM %token STARTING %token STATUS_SYM @@ -408,13 +374,11 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token TABLE_SYM %token TABLESPACE %token TEMPORARY -%token TEMPTABLE_SYM %token TERMINATED %token TEXT_STRING %token TO_SYM %token TRAILING %token TRANSACTION_SYM -%token TRIGGER_SYM %token TRUE_SYM %token TYPE_SYM %token TYPES_SYM @@ -422,15 +386,11 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token FUNC_ARG1 %token FUNC_ARG2 %token FUNC_ARG3 -%token RETURN_SYM -%token RETURNS_SYM -%token UDF_SONAME_SYM %token UDF_RETURNS_SYM -%token FUNCTION_SYM +%token UDF_SONAME_SYM +%token UDF_SYM %token UNCOMMITTED_SYM -%token UNDEFINED_SYM %token UNDERSCORE_CHARSET -%token UNDO_SYM %token UNICODE_SYM %token UNION_SYM %token UNIQUE_SYM @@ -441,7 +401,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token VALUE_SYM %token VALUES %token VARIABLES -%token VIEW_SYM %token WHERE %token WITH %token WRITE_SYM @@ -449,7 +408,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token X509_SYM %token XOR %token COMPRESSED_SYM -%token ROW_COUNT_SYM %token ERRORS %token WARNINGS @@ -486,8 +444,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token STRING_SYM %token TEXT_SYM %token TIMESTAMP -%token TIMESTAMP_ADD -%token TIMESTAMP_DIFF %token TIME_SYM %token TINYBLOB %token TINYINT @@ -534,7 +490,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token FIELD_FUNC %token FORMAT_SYM %token FOR_SYM -%token FRAC_SECOND_SYM %token FROM_UNIXTIME %token GEOMCOLLFROMTEXT %token GEOMFROMTEXT @@ -563,7 +518,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token MINUTE_SECOND_SYM %token MINUTE_SYM %token MODE_SYM -%token MODIFIES_SYM %token MODIFY_SYM %token MONTH_SYM %token MLINEFROMTEXT @@ -581,7 +535,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token POLYGON %token POSITION_SYM %token PROCEDURE -%token QUARTER_SYM %token RAND %token REPLACE %token RIGHT @@ -593,6 +546,12 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token SUBSTRING %token SUBSTRING_INDEX %token TRIM +%token UDA_CHAR_SUM +%token UDA_FLOAT_SUM +%token UDA_INT_SUM +%token UDF_CHAR_FUNC +%token UDF_FLOAT_FUNC +%token UDF_INT_FUNC %token UNIQUE_USERS %token UNIX_TIMESTAMP %token USER @@ -616,20 +575,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token SQL_SMALL_RESULT %token SQL_BUFFER_RESULT -%token CURSOR_SYM -%token ELSEIF_SYM -%token ITERATE_SYM -%token GOTO_SYM -%token LABEL_SYM -%token LEAVE_SYM -%token LOOP_SYM -%token REPEAT_SYM -%token UNTIL_SYM -%token WHILE_SYM -%token ASENSITIVE_SYM -%token INSENSITIVE_SYM -%token SENSITIVE_SYM - %token ISSUER_SYM %token SUBJECT_SYM %token CIPHER_SYM @@ -655,7 +600,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); LEX_HOSTNAME ULONGLONG_NUM field_ident select_alias ident ident_or_text UNDERSCORE_CHARSET IDENT_sys TEXT_STRING_sys TEXT_STRING_literal NCHAR_STRING opt_component key_cache_name - sp_opt_label %type <lex_str_ptr> opt_table_alias @@ -676,6 +620,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); table_option opt_if_not_exists opt_no_write_to_binlog opt_var_type opt_var_ident_type delete_option opt_temporary all_or_any opt_distinct opt_ignore_leaves fulltext_options spatial_type union_option + start_transaction_opts %type <ulong_num> ULONG_NUM raid_types merge_insert_types @@ -689,20 +634,17 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %type <item> literal text_literal insert_ident order_ident simple_ident select_item2 expr opt_expr opt_else sum_expr in_sum_expr - table_wild no_in_expr expr_expr simple_expr no_and_expr udf_expr + table_wild no_in_expr expr_expr simple_expr no_and_expr using_list expr_or_default set_expr_or_default interval_expr param_marker singlerow_subselect singlerow_subselect_init exists_subselect exists_subselect_init geometry_function signed_literal now_or_signed_literal opt_escape - sp_opt_default - simple_ident_nospvar simple_ident_q %type <item_num> NUM_literal %type <item_list> - expr_list udf_expr_list udf_expr_list2 when_list - ident_list ident_list_arg + expr_list udf_expr_list when_list ident_list ident_list_arg %type <key_type> key_type opt_unique_or_fulltext constraint_key_type @@ -718,13 +660,14 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %type <table_list> join_table_list join_table - table_factor table_ref + +%type <udf> + UDF_CHAR_FUNC UDF_FLOAT_FUNC UDF_INT_FUNC + UDA_CHAR_SUM UDA_FLOAT_SUM UDA_INT_SUM %type <date_time_type> date_time_type; %type <interval> interval -%type <interval_time_st> interval_time_st - %type <db_type> storage_engines %type <row_type> row_types @@ -768,7 +711,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); select_item_list select_item values_list no_braces opt_limit_clause delete_limit_clause fields opt_values values procedure_list procedure_list2 procedure_item - when_list2 expr_list2 udf_expr_list3 handler + when_list2 expr_list2 handler opt_precision opt_ignore opt_column opt_restrict grant revoke set lock unlock string_list field_options field_option field_opt_list opt_binary table_lock_list table_lock @@ -789,17 +732,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); subselect_end select_var_list select_var_list_init help opt_len opt_extended_describe prepare prepare_src execute deallocate - statement sp_suid opt_view_list view_list or_replace algorithm - sp_c_chistics sp_a_chistics sp_chistic sp_c_chistic END_OF_INPUT -%type <NONE> call sp_proc_stmts sp_proc_stmts1 sp_proc_stmt -%type <num> sp_decl_idents sp_opt_inout sp_handler_type sp_hcond_list -%type <spcondtype> sp_cond sp_hcond -%type <spblock> sp_decls sp_decl -%type <lex> sp_cursor_stmt -%type <spname> sp_name - %type <NONE> '-' '+' '*' '/' '%' '(' ')' ',' '!' '{' '}' '&' '|' AND_SYM OR_SYM OR_OR_CONCAT BETWEEN_SYM CASE_SYM @@ -825,16 +759,10 @@ query: | verb_clause END_OF_INPUT {}; verb_clause: - statement - | begin - ; - -/* Verb clauses, except begin */ -statement: alter | analyze | backup - | call + | begin | change | check | checksum @@ -1135,1267 +1063,19 @@ create: lex->name=$4.str; lex->create_info.options=$3; } - | CREATE udf_func_type FUNCTION_SYM sp_name + | CREATE udf_func_type UDF_SYM IDENT_sys { LEX *lex=Lex; - lex->spname= $4; + lex->sql_command = SQLCOM_CREATE_FUNCTION; + lex->udf.name = $4; lex->udf.type= $2; } - create_function_tail - {} - | CREATE PROCEDURE sp_name - { - LEX *lex= Lex; - sp_head *sp; - - if (lex->sphead) - { - net_printf(YYTHD, ER_SP_NO_RECURSIVE_CREATE, "PROCEDURE"); - YYABORT; - } - /* Order is important here: new - reset - init */ - sp= new sp_head(); - sp->reset_thd_mem_root(YYTHD); - sp->init(lex); - - sp->m_type= TYPE_ENUM_PROCEDURE; - lex->sphead= sp; - /* - * We have to turn of CLIENT_MULTI_QUERIES while parsing a - * stored procedure, otherwise yylex will chop it into pieces - * at each ';'. - */ - sp->m_old_cmq= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES; - YYTHD->client_capabilities &= (~CLIENT_MULTI_QUERIES); - } - '(' - { - LEX *lex= Lex; - - lex->sphead->m_param_begin= lex->tok_start+1; - } - sp_pdparam_list - ')' - { - LEX *lex= Lex; - - lex->sphead->m_param_end= lex->tok_start; - bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics)); - } - sp_c_chistics - { - LEX *lex= Lex; - - lex->sphead->m_chistics= &lex->sp_chistics; - lex->sphead->m_body_begin= lex->tok_start; - } - sp_proc_stmt - { - LEX *lex= Lex; - sp_head *sp= lex->sphead; - - if (sp->check_backpatch(YYTHD)) - YYABORT; - sp->init_strings(YYTHD, lex, $3); - lex->sql_command= SQLCOM_CREATE_PROCEDURE; - /* Restore flag if it was cleared above */ - if (sp->m_old_cmq) - YYTHD->client_capabilities |= CLIENT_MULTI_QUERIES; - sp->restore_thd_mem_root(YYTHD); - } - | CREATE or_replace algorithm VIEW_SYM table_ident - { - THD *thd= YYTHD; - LEX *lex= thd->lex; - lex->sql_command= SQLCOM_CREATE_VIEW; - lex->select_lex.resolve_mode= SELECT_LEX::SELECT_MODE; - /* first table in list is target VIEW name */ - if (!lex->select_lex.add_table_to_list(thd, $5, NULL, 0)) - YYABORT; - } - opt_view_list AS select_init check_option - {} - | CREATE TRIGGER_SYM ident trg_action_time trg_event - ON table_ident FOR_SYM EACH_SYM ROW_SYM - { - LEX *lex= Lex; - sp_head *sp; - - if (lex->sphead) - { - net_printf(YYTHD, ER_SP_NO_RECURSIVE_CREATE, "TRIGGER"); - YYABORT; - } - - sp= new sp_head(); - sp->reset_thd_mem_root(YYTHD); - sp->init(lex); - - sp->m_type= TYPE_ENUM_TRIGGER; - lex->sphead= sp; - /* - We have to turn of CLIENT_MULTI_QUERIES while parsing a - stored procedure, otherwise yylex will chop it into pieces - at each ';'. - */ - sp->m_old_cmq= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES; - YYTHD->client_capabilities &= ~CLIENT_MULTI_QUERIES; - - bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics)); - lex->sphead->m_chistics= &lex->sp_chistics; - lex->sphead->m_body_begin= lex->tok_start; - } - sp_proc_stmt - { - LEX *lex= Lex; - sp_head *sp= lex->sphead; - - lex->sql_command= SQLCOM_CREATE_TRIGGER; - sp->init_strings(YYTHD, lex, NULL); - /* Restore flag if it was cleared above */ - if (sp->m_old_cmq) - YYTHD->client_capabilities |= CLIENT_MULTI_QUERIES; - sp->restore_thd_mem_root(YYTHD); - - lex->name_and_length= $3; - - /* - We have to do it after parsing trigger body, because some of - sp_proc_stmt alternatives are not saving/restoring LEX, so - lex->query_tables can be wiped out. - - QQ: What are other consequences of this? - - QQ: Could we loosen lock type in certain cases ? - */ - if (!lex->select_lex.add_table_to_list(YYTHD, $7, - (LEX_STRING*) 0, - TL_OPTION_UPDATING, - TL_WRITE)) - YYABORT; - } - ; - -sp_name: - IDENT_sys '.' IDENT_sys - { - $$= new sp_name($1, $3); - $$->init_qname(YYTHD); - } - | IDENT_sys - { - $$= sp_name_current_db_new(YYTHD, $1); - } - ; - -create_function_tail: - RETURNS_SYM udf_type UDF_SONAME_SYM TEXT_STRING_sys + UDF_RETURNS_SYM udf_type UDF_SONAME_SYM TEXT_STRING_sys { LEX *lex=Lex; - lex->sql_command = SQLCOM_CREATE_FUNCTION; - lex->udf.name = lex->spname->m_name; - lex->udf.returns=(Item_result) $2; - lex->udf.dl=$4.str; - } - | '(' - { - LEX *lex= Lex; - sp_head *sp; - - if (lex->sphead) - { - net_printf(YYTHD, ER_SP_NO_RECURSIVE_CREATE, "FUNCTION"); - YYABORT; - } - /* Order is important here: new - reset - init */ - sp= new sp_head(); - sp->reset_thd_mem_root(YYTHD); - sp->init(lex); - - sp->m_type= TYPE_ENUM_FUNCTION; - lex->sphead= sp; - /* - * We have to turn of CLIENT_MULTI_QUERIES while parsing a - * stored procedure, otherwise yylex will chop it into pieces - * at each ';'. - */ - sp->m_old_cmq= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES; - YYTHD->client_capabilities &= ~CLIENT_MULTI_QUERIES; - lex->sphead->m_param_begin= lex->tok_start+1; - } - sp_fdparam_list ')' - { - LEX *lex= Lex; - - lex->sphead->m_param_end= lex->tok_start; - } - RETURNS_SYM - { - LEX *lex= Lex; - sp_head *sp= lex->sphead; - - sp->m_returns_begin= lex->tok_start; - sp->m_returns_cs= lex->charset= NULL; - } - type - { - LEX *lex= Lex; - sp_head *sp= lex->sphead; - - sp->m_returns_end= lex->tok_start; - sp->m_returns= (enum enum_field_types)$8; - sp->m_returns_cs= lex->charset; - bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics)); - } - sp_c_chistics - { - LEX *lex= Lex; - - lex->sphead->m_chistics= &lex->sp_chistics; - lex->sphead->m_body_begin= lex->tok_start; - } - sp_proc_stmt - { - LEX *lex= Lex; - sp_head *sp= lex->sphead; - - if (sp->check_backpatch(YYTHD)) - YYABORT; - lex->sql_command= SQLCOM_CREATE_SPFUNCTION; - sp->init_strings(YYTHD, lex, lex->spname); - /* Restore flag if it was cleared above */ - if (sp->m_old_cmq) - YYTHD->client_capabilities |= CLIENT_MULTI_QUERIES; - sp->restore_thd_mem_root(YYTHD); - } - ; - -sp_a_chistics: - /* Empty */ {} - | sp_a_chistics sp_chistic {} - ; - -sp_c_chistics: - /* Empty */ {} - | sp_c_chistics sp_c_chistic {} - ; - -/* Characteristics for both create and alter */ -sp_chistic: - COMMENT_SYM TEXT_STRING_sys - { Lex->sp_chistics.comment= $2; } - | LANGUAGE_SYM SQL_SYM - { /* Just parse it, we only have one language for now. */ } - | NO_SYM SQL_SYM - { Lex->sp_chistics.daccess= SP_NO_SQL; } - | CONTAINS_SYM SQL_SYM - { Lex->sp_chistics.daccess= SP_CONTAINS_SQL; } - | READS_SYM SQL_SYM DATA_SYM - { Lex->sp_chistics.daccess= SP_READS_SQL_DATA; } - | MODIFIES_SYM SQL_SYM DATA_SYM - { Lex->sp_chistics.daccess= SP_MODIFIES_SQL_DATA; } - | sp_suid - { } - ; - -/* Create characteristics */ -sp_c_chistic: - sp_chistic { } - | DETERMINISTIC_SYM { Lex->sp_chistics.detistic= TRUE; } - | NOT DETERMINISTIC_SYM { Lex->sp_chistics.detistic= FALSE; } - ; - -sp_suid: - SQL_SYM SECURITY_SYM DEFINER_SYM - { - Lex->sp_chistics.suid= SP_IS_SUID; - } - | SQL_SYM SECURITY_SYM INVOKER_SYM - { - Lex->sp_chistics.suid= SP_IS_NOT_SUID; - } - ; - -call: - CALL_SYM sp_name - { - LEX *lex = Lex; - - lex->sql_command= SQLCOM_CALL; - lex->spname= $2; - lex->value_list.empty(); - } - '(' sp_cparam_list ')' {} - ; - -/* CALL parameters */ -sp_cparam_list: - /* Empty */ - | sp_cparams - ; - -sp_cparams: - sp_cparams ',' expr - { - Lex->value_list.push_back($3); - } - | expr - { - Lex->value_list.push_back($1); - } - ; - -/* Stored FUNCTION parameter declaration list */ -sp_fdparam_list: - /* Empty */ - | sp_fdparams - ; - -sp_fdparams: - sp_fdparams ',' sp_fdparam - | sp_fdparam - ; - -sp_fdparam: - ident type - { - LEX *lex= Lex; - sp_pcontext *spc= lex->spcont; - - if (spc->find_pvar(&$1, TRUE)) - { - net_printf(YYTHD, ER_SP_DUP_PARAM, $1.str); - YYABORT; - } - spc->push_pvar(&$1, (enum enum_field_types)$2, sp_param_in); - } - ; - -/* Stored PROCEDURE parameter declaration list */ -sp_pdparam_list: - /* Empty */ - | sp_pdparams - ; - -sp_pdparams: - sp_pdparams ',' sp_pdparam - | sp_pdparam - ; - -sp_pdparam: - sp_opt_inout ident type - { - LEX *lex= Lex; - sp_pcontext *spc= lex->spcont; - - if (spc->find_pvar(&$2, TRUE)) - { - net_printf(YYTHD, ER_SP_DUP_PARAM, $2.str); - YYABORT; - } - spc->push_pvar(&$2, (enum enum_field_types)$3, - (sp_param_mode_t)$1); - } - ; - -sp_opt_inout: - /* Empty */ { $$= sp_param_in; } - | IN_SYM { $$= sp_param_in; } - | OUT_SYM { $$= sp_param_out; } - | INOUT_SYM { $$= sp_param_inout; } - ; - -sp_proc_stmts: - /* Empty */ {} - | sp_proc_stmts { Lex->query_tables= 0; } sp_proc_stmt ';' - ; - -sp_proc_stmts1: - sp_proc_stmt ';' {} - | sp_proc_stmts1 { Lex->query_tables= 0; } sp_proc_stmt ';' - ; - -sp_decls: - /* Empty */ - { - $$.vars= $$.conds= $$.hndlrs= $$.curs= 0; - } - | sp_decls sp_decl ';' - { - /* We check for declarations out of (standard) order this way - because letting the grammar rules reflect it caused tricky - shift/reduce conflicts with the wrong result. (And we get - better error handling this way.) */ - if (($2.vars || $2.conds) && ($1.curs || $1.hndlrs)) - { /* Variable or condition following cursor or handler */ - send_error(YYTHD, ER_SP_VARCOND_AFTER_CURSHNDLR); - YYABORT; - } - if ($2.curs && $1.hndlrs) - { /* Cursor following handler */ - send_error(YYTHD, ER_SP_CURSOR_AFTER_HANDLER); - YYABORT; - } - $$.vars= $1.vars + $2.vars; - $$.conds= $1.conds + $2.conds; - $$.hndlrs= $1.hndlrs + $2.hndlrs; - $$.curs= $1.curs + $2.curs; - } - ; - -sp_decl: - DECLARE_SYM sp_decl_idents type sp_opt_default - { - LEX *lex= Lex; - sp_pcontext *ctx= lex->spcont; - uint max= ctx->context_pvars(); - enum enum_field_types type= (enum enum_field_types)$3; - Item *it= $4; - - for (uint i = max-$2 ; i < max ; i++) - { - ctx->set_type(i, type); - if (! it) - ctx->set_isset(i, FALSE); - else - { - sp_instr_set *in= new sp_instr_set(lex->sphead->instructions(), - ctx, - ctx->pvar_context2index(i), - it, type); - - in->tables= lex->query_tables; - lex->query_tables= 0; - lex->sphead->add_instr(in); - ctx->set_isset(i, TRUE); - ctx->set_default(i, it); - } - } - $$.vars= $2; - $$.conds= $$.hndlrs= $$.curs= 0; - } - | DECLARE_SYM ident CONDITION_SYM FOR_SYM sp_cond - { - LEX *lex= Lex; - sp_pcontext *spc= lex->spcont; - - if (spc->find_cond(&$2, TRUE)) - { - net_printf(YYTHD, ER_SP_DUP_COND, $2.str); - YYABORT; - } - YYTHD->lex->spcont->push_cond(&$2, $5); - $$.vars= $$.hndlrs= $$.curs= 0; - $$.conds= 1; - } - | DECLARE_SYM sp_handler_type HANDLER_SYM FOR_SYM - { - LEX *lex= Lex; - sp_head *sp= lex->sphead; - sp_pcontext *ctx= lex->spcont; - sp_instr_hpush_jump *i= - new sp_instr_hpush_jump(sp->instructions(), ctx, $2, - ctx->current_pvars()); - - sp->add_instr(i); - sp->push_backpatch(i, ctx->push_label((char *)"", 0)); - ctx->add_handler(); - sp->m_in_handler= TRUE; - } - sp_hcond_list sp_proc_stmt - { - LEX *lex= Lex; - sp_head *sp= lex->sphead; - sp_pcontext *ctx= lex->spcont; - sp_label_t *hlab= lex->spcont->pop_label(); /* After this hdlr */ - sp_instr_hreturn *i; - - if ($2 == SP_HANDLER_CONTINUE) - { - i= new sp_instr_hreturn(sp->instructions(), ctx, - ctx->current_pvars()); - sp->add_instr(i); - } - else - { /* EXIT or UNDO handler, just jump to the end of the block */ - i= new sp_instr_hreturn(sp->instructions(), ctx, 0); - - sp->add_instr(i); - sp->push_backpatch(i, lex->spcont->last_label()); /* Block end */ - } - lex->sphead->backpatch(hlab); - sp->m_in_handler= FALSE; - $$.vars= $$.conds= $$.curs= 0; - $$.hndlrs= $6; - } - | DECLARE_SYM ident CURSOR_SYM FOR_SYM sp_cursor_stmt - { - LEX *lex= Lex; - sp_head *sp= lex->sphead; - sp_pcontext *ctx= lex->spcont; - uint offp; - sp_instr_cpush *i; - - if (ctx->find_cursor(&$2, &offp, TRUE)) - { - net_printf(YYTHD, ER_SP_DUP_CURS, $2.str); - delete $5; - YYABORT; - } - i= new sp_instr_cpush(sp->instructions(), ctx, $5); - sp->add_instr(i); - ctx->push_cursor(&$2); - $$.vars= $$.conds= $$.hndlrs= 0; - $$.curs= 1; - } - ; - -sp_cursor_stmt: - { - Lex->sphead->reset_lex(YYTHD); - - /* We use statement here just be able to get a better - error message. Using 'select' works too, but will then - result in a generic "syntax error" if a non-select - statement is given. */ + lex->udf.returns=(Item_result) $7; + lex->udf.dl=$9.str; } - statement - { - LEX *lex= Lex; - - if (lex->sql_command != SQLCOM_SELECT) - { - send_error(YYTHD, ER_SP_BAD_CURSOR_QUERY); - YYABORT; - } - if (lex->result) - { - send_error(YYTHD, ER_SP_BAD_CURSOR_SELECT); - YYABORT; - } - lex->sp_lex_in_use= TRUE; - $$= lex; - lex->sphead->restore_lex(YYTHD); - } - ; - -sp_handler_type: - EXIT_SYM { $$= SP_HANDLER_EXIT; } - | CONTINUE_SYM { $$= SP_HANDLER_CONTINUE; } -/* | UNDO_SYM { QQ No yet } */ - ; - -sp_hcond_list: - sp_hcond - { - LEX *lex= Lex; - sp_head *sp= lex->sphead; - sp_instr_hpush_jump *i= (sp_instr_hpush_jump *)sp->last_instruction(); - - i->add_condition($1); - $$= 1; - } - | sp_hcond_list ',' sp_hcond - { - LEX *lex= Lex; - sp_head *sp= lex->sphead; - sp_instr_hpush_jump *i= (sp_instr_hpush_jump *)sp->last_instruction(); - - i->add_condition($3); - $$= $1 + 1; - } - ; - -sp_cond: - ULONG_NUM - { /* mysql errno */ - $$= (sp_cond_type_t *)YYTHD->alloc(sizeof(sp_cond_type_t)); - $$->type= sp_cond_type_t::number; - $$->mysqlerr= $1; - } - | SQLSTATE_SYM opt_value TEXT_STRING_literal - { /* SQLSTATE */ - uint len= ($3.length < sizeof($$->sqlstate)-1 ? - $3.length : sizeof($$->sqlstate)-1); - - $$= (sp_cond_type_t *)YYTHD->alloc(sizeof(sp_cond_type_t)); - $$->type= sp_cond_type_t::state; - memcpy($$->sqlstate, $3.str, len); - $$->sqlstate[len]= '\0'; - } - ; - -opt_value: - /* Empty */ {} - | VALUE_SYM {} - ; - -sp_hcond: - sp_cond - { - $$= $1; - } - | ident /* CONDITION name */ - { - $$= Lex->spcont->find_cond(&$1); - if ($$ == NULL) - { - net_printf(YYTHD, ER_SP_COND_MISMATCH, $1.str); - YYABORT; - } - } - | SQLWARNING_SYM /* SQLSTATEs 01??? */ - { - $$= (sp_cond_type_t *)YYTHD->alloc(sizeof(sp_cond_type_t)); - $$->type= sp_cond_type_t::warning; - } - | NOT FOUND_SYM /* SQLSTATEs 02??? */ - { - $$= (sp_cond_type_t *)YYTHD->alloc(sizeof(sp_cond_type_t)); - $$->type= sp_cond_type_t::notfound; - } - | SQLEXCEPTION_SYM /* All other SQLSTATEs */ - { - $$= (sp_cond_type_t *)YYTHD->alloc(sizeof(sp_cond_type_t)); - $$->type= sp_cond_type_t::exception; - } - ; - -sp_decl_idents: - ident - { - LEX *lex= Lex; - sp_pcontext *spc= lex->spcont; - - if (spc->find_pvar(&$1, TRUE)) - { - net_printf(YYTHD, ER_SP_DUP_VAR, $1.str); - YYABORT; - } - spc->push_pvar(&$1, (enum_field_types)0, sp_param_in); - $$= 1; - } - | sp_decl_idents ',' ident - { - LEX *lex= Lex; - sp_pcontext *spc= lex->spcont; - - if (spc->find_pvar(&$3, TRUE)) - { - net_printf(YYTHD, ER_SP_DUP_VAR, $3.str); - YYABORT; - } - spc->push_pvar(&$3, (enum_field_types)0, sp_param_in); - $$= $1 + 1; - } - ; - -sp_opt_default: - /* Empty */ { $$ = NULL; } - | DEFAULT expr { $$ = $2; } - ; - -sp_proc_stmt: - { - LEX *lex= Lex; - - lex->sphead->reset_lex(YYTHD); - lex->sphead->m_tmp_query= lex->tok_start; - } - statement - { - LEX *lex= Lex; - sp_head *sp= lex->sphead; - - if ((lex->sql_command == SQLCOM_SELECT && !lex->result) || - sp_multi_results_command(lex->sql_command)) - { - /* We maybe have one or more SELECT without INTO */ - sp->m_multi_results= TRUE; - } - if (lex->sql_command == SQLCOM_CHANGE_DB) - { /* "USE db" doesn't work in a procedure */ - send_error(YYTHD, ER_SP_NO_USE); - YYABORT; - } - /* Don't add an instruction for empty SET statements. - ** (This happens if the SET only contained local variables, - ** which get their set instructions generated separately.) - */ - if (lex->sql_command != SQLCOM_SET_OPTION || - ! lex->var_list.is_empty()) - { - /* - Currently we can't handle queries inside a FUNCTION or - TRIGGER, because of the way table locking works. This is - unfortunate, and limits the usefulness of functions and - especially triggers a tremendously, but it's nothing we - can do about this at the moment. - */ - if (sp->m_type != TYPE_ENUM_PROCEDURE) - { - send_error(YYTHD, ER_SP_BADSTATEMENT); - YYABORT; - } - else - { - sp_instr_stmt *i=new sp_instr_stmt(sp->instructions(), - lex->spcont); - - /* Extract the query statement from the tokenizer: - The end is either lex->tok_end or tok->ptr. */ - if (lex->ptr - lex->tok_end > 1) - i->m_query.length= lex->ptr - sp->m_tmp_query; - else - i->m_query.length= lex->tok_end - sp->m_tmp_query; - i->m_query.str= strmake_root(YYTHD->mem_root, - (char *)sp->m_tmp_query, - i->m_query.length); - i->set_lex(lex); - sp->add_instr(i); - lex->sp_lex_in_use= TRUE; - } - } - sp->restore_lex(YYTHD); - } - | RETURN_SYM expr - { - LEX *lex= Lex; - - if (lex->sphead->m_type == TYPE_ENUM_PROCEDURE) - { - send_error(YYTHD, ER_SP_BADRETURN); - YYABORT; - } - else - { - sp_instr_freturn *i; - - if ($2->type() == Item::SUBSELECT_ITEM) - { /* QQ For now, just disallow subselects as values */ - send_error(lex->thd, ER_SP_BADSTATEMENT); - YYABORT; - } - i= new sp_instr_freturn(lex->sphead->instructions(), - lex->spcont, - $2, lex->sphead->m_returns); - lex->sphead->add_instr(i); - lex->sphead->m_has_return= TRUE; - } - } - | IF sp_if END IF {} - | CASE_SYM WHEN_SYM - { - Lex->sphead->m_simple_case= FALSE; - } - sp_case END CASE_SYM {} - | CASE_SYM expr WHEN_SYM - { - /* We "fake" this by using an anonymous variable which we - set to the expression. Note that all WHENs are evaluate - at the same frame level, so we then know that it's the - top-most variable in the frame. */ - LEX *lex= Lex; - uint offset= lex->spcont->current_pvars(); - sp_instr_set *i = new sp_instr_set(lex->sphead->instructions(), - lex->spcont, - offset, $2, MYSQL_TYPE_STRING); - LEX_STRING dummy; - - dummy.str= (char *)""; - dummy.length= 0; - lex->spcont->push_pvar(&dummy, MYSQL_TYPE_STRING, sp_param_in); - i->tables= lex->query_tables; - lex->query_tables= 0; - lex->sphead->add_instr(i); - lex->sphead->m_simple_case= TRUE; - } - sp_case END CASE_SYM - { - Lex->spcont->pop_pvar(); - } - | sp_labeled_control - {} - | { /* Unlabeled controls get a secret label. */ - LEX *lex= Lex; - - lex->spcont->push_label((char *)"", lex->sphead->instructions()); - } - sp_unlabeled_control - { - LEX *lex= Lex; - - lex->sphead->backpatch(lex->spcont->pop_label()); - } - | LEAVE_SYM IDENT - { - LEX *lex= Lex; - sp_head *sp = lex->sphead; - sp_pcontext *ctx= lex->spcont; - sp_label_t *lab= ctx->find_label($2.str); - - if (! lab) - { - net_printf(YYTHD, ER_SP_LILABEL_MISMATCH, "LEAVE", $2.str); - YYABORT; - } - else - { - uint ip= sp->instructions(); - sp_instr_jump *i; - sp_instr_hpop *ih; - sp_instr_cpop *ic; - - ih= new sp_instr_hpop(ip++, ctx, 0); - sp->push_backpatch(ih, lab); - sp->add_instr(ih); - ic= new sp_instr_cpop(ip++, ctx, 0); - sp->push_backpatch(ic, lab); - sp->add_instr(ic); - i= new sp_instr_jump(ip, ctx); - sp->push_backpatch(i, lab); /* Jumping forward */ - sp->add_instr(i); - } - } - | ITERATE_SYM IDENT - { - LEX *lex= Lex; - sp_head *sp= lex->sphead; - sp_pcontext *ctx= lex->spcont; - sp_label_t *lab= ctx->find_label($2.str); - - if (! lab || lab->type != SP_LAB_ITER) - { - net_printf(YYTHD, ER_SP_LILABEL_MISMATCH, "ITERATE", $2.str); - YYABORT; - } - else - { - sp_instr_jump *i; - uint ip= sp->instructions(); - uint n; - - n= ctx->diff_handlers(lab->ctx); - if (n) - sp->add_instr(new sp_instr_hpop(ip++, ctx, n)); - n= ctx->diff_cursors(lab->ctx); - if (n) - sp->add_instr(new sp_instr_cpop(ip++, ctx, n)); - i= new sp_instr_jump(ip, ctx, lab->ip); /* Jump back */ - sp->add_instr(i); - } - } - | LABEL_SYM IDENT - { - LEX *lex= Lex; - sp_head *sp= lex->sphead; - sp_pcontext *ctx= lex->spcont; - sp_label_t *lab= ctx->find_label($2.str); - - if (lab) - { - net_printf(YYTHD, ER_SP_LABEL_REDEFINE, $2.str); - YYABORT; - } - else - { - lab= ctx->push_label($2.str, sp->instructions()); - lab->type= SP_LAB_GOTO; - lab->ctx= ctx; - sp->backpatch(lab); - } - } - | GOTO_SYM IDENT - { - LEX *lex= Lex; - sp_head *sp= lex->sphead; - sp_pcontext *ctx= lex->spcont; - uint ip= lex->sphead->instructions(); - sp_label_t *lab; - sp_instr_jump *i; - sp_instr_hpop *ih; - sp_instr_cpop *ic; - - if (sp->m_in_handler) - { - send_error(lex->thd, ER_SP_GOTO_IN_HNDLR); - YYABORT; - } - lab= ctx->find_label($2.str); - if (! lab) - { - lab= (sp_label_t *)YYTHD->alloc(sizeof(sp_label_t)); - lab->name= $2.str; - lab->ip= 0; - lab->type= SP_LAB_REF; - lab->ctx= ctx; - - ih= new sp_instr_hpop(ip++, ctx, 0); - sp->push_backpatch(ih, lab); - sp->add_instr(ih); - ic= new sp_instr_cpop(ip++, ctx, 0); - sp->add_instr(ic); - sp->push_backpatch(ic, lab); - i= new sp_instr_jump(ip, ctx); - sp->push_backpatch(i, lab); /* Jumping forward */ - sp->add_instr(i); - } - else - { - uint n; - - n= ctx->diff_handlers(lab->ctx); - if (n) - { - ih= new sp_instr_hpop(ip++, ctx, n); - sp->add_instr(ih); - } - n= ctx->diff_cursors(lab->ctx); - if (n) - { - ic= new sp_instr_cpop(ip++, ctx, n); - sp->add_instr(ic); - } - i= new sp_instr_jump(ip, ctx, lab->ip); /* Jump back */ - sp->add_instr(i); - } - } - | OPEN_SYM ident - { - LEX *lex= Lex; - sp_head *sp= lex->sphead; - uint offset; - sp_instr_copen *i; - - if (! lex->spcont->find_cursor(&$2, &offset)) - { - net_printf(YYTHD, ER_SP_CURSOR_MISMATCH, $2.str); - YYABORT; - } - i= new sp_instr_copen(sp->instructions(), lex->spcont, offset); - sp->add_instr(i); - } - | FETCH_SYM sp_opt_fetch_noise ident INTO - { - LEX *lex= Lex; - sp_head *sp= lex->sphead; - uint offset; - sp_instr_cfetch *i; - - if (! lex->spcont->find_cursor(&$3, &offset)) - { - net_printf(YYTHD, ER_SP_CURSOR_MISMATCH, $3.str); - YYABORT; - } - i= new sp_instr_cfetch(sp->instructions(), lex->spcont, offset); - sp->add_instr(i); - } - sp_fetch_list - { } - | CLOSE_SYM ident - { - LEX *lex= Lex; - sp_head *sp= lex->sphead; - uint offset; - sp_instr_cclose *i; - - if (! lex->spcont->find_cursor(&$2, &offset)) - { - net_printf(YYTHD, ER_SP_CURSOR_MISMATCH, $2.str); - YYABORT; - } - i= new sp_instr_cclose(sp->instructions(), lex->spcont, offset); - sp->add_instr(i); - } - ; - -sp_opt_fetch_noise: - /* Empty */ - | NEXT_SYM FROM - | FROM - ; - -sp_fetch_list: - ident - { - LEX *lex= Lex; - sp_head *sp= lex->sphead; - sp_pcontext *spc= lex->spcont; - sp_pvar_t *spv; - - if (!spc || !(spv = spc->find_pvar(&$1))) - { - net_printf(YYTHD, ER_SP_UNDECLARED_VAR, $1.str); - YYABORT; - } - else - { - /* An SP local variable */ - sp_instr_cfetch *i= (sp_instr_cfetch *)sp->last_instruction(); - - i->add_to_varlist(spv); - spv->isset= TRUE; - } - } - | - sp_fetch_list ',' ident - { - LEX *lex= Lex; - sp_head *sp= lex->sphead; - sp_pcontext *spc= lex->spcont; - sp_pvar_t *spv; - - if (!spc || !(spv = spc->find_pvar(&$3))) - { - net_printf(YYTHD, ER_SP_UNDECLARED_VAR, $3.str); - YYABORT; - } - else - { - /* An SP local variable */ - sp_instr_cfetch *i= (sp_instr_cfetch *)sp->last_instruction(); - - i->add_to_varlist(spv); - spv->isset= TRUE; - } - } - ; - -sp_if: - expr THEN_SYM - { - LEX *lex= Lex; - sp_head *sp= lex->sphead; - sp_pcontext *ctx= lex->spcont; - uint ip= sp->instructions(); - sp_instr_jump_if_not *i = new sp_instr_jump_if_not(ip, ctx, $1); - - i->tables= lex->query_tables; - lex->query_tables= 0; - sp->push_backpatch(i, ctx->push_label((char *)"", 0)); - sp->add_instr(i); - } - sp_proc_stmts1 - { - sp_head *sp= Lex->sphead; - sp_pcontext *ctx= Lex->spcont; - uint ip= sp->instructions(); - sp_instr_jump *i = new sp_instr_jump(ip, ctx); - - sp->add_instr(i); - sp->backpatch(ctx->pop_label()); - sp->push_backpatch(i, ctx->push_label((char *)"", 0)); - } - sp_elseifs - { - LEX *lex= Lex; - - lex->sphead->backpatch(lex->spcont->pop_label()); - } - ; - -sp_elseifs: - /* Empty */ - | ELSEIF_SYM sp_if - | ELSE sp_proc_stmts1 - ; - -sp_case: - expr THEN_SYM - { - LEX *lex= Lex; - sp_head *sp= lex->sphead; - sp_pcontext *ctx= Lex->spcont; - uint ip= sp->instructions(); - sp_instr_jump_if_not *i; - - if (! sp->m_simple_case) - i= new sp_instr_jump_if_not(ip, ctx, $1); - else - { /* Simple case: <caseval> = <whenval> */ - LEX_STRING ivar; - - ivar.str= (char *)"_tmp_"; - ivar.length= 5; - Item *var= (Item*) new Item_splocal(ivar, - ctx->current_pvars()-1); - Item *expr= new Item_func_eq(var, $1); - - i= new sp_instr_jump_if_not(ip, ctx, expr); - lex->variables_used= 1; - } - sp->push_backpatch(i, ctx->push_label((char *)"", 0)); - i->tables= lex->query_tables; - lex->query_tables= 0; - sp->add_instr(i); - } - sp_proc_stmts1 - { - sp_head *sp= Lex->sphead; - sp_pcontext *ctx= Lex->spcont; - uint ip= sp->instructions(); - sp_instr_jump *i = new sp_instr_jump(ip, ctx); - - sp->add_instr(i); - sp->backpatch(ctx->pop_label()); - sp->push_backpatch(i, ctx->push_label((char *)"", 0)); - } - sp_whens - { - LEX *lex= Lex; - - lex->sphead->backpatch(lex->spcont->pop_label()); - } - ; - -sp_whens: - /* Empty */ - { - sp_head *sp= Lex->sphead; - uint ip= sp->instructions(); - sp_instr_error *i= new sp_instr_error(ip, Lex->spcont, - ER_SP_CASE_NOT_FOUND); - - sp->add_instr(i); - } - | ELSE sp_proc_stmts1 {} - | WHEN_SYM sp_case {} - ; - -sp_labeled_control: - IDENT ':' - { - LEX *lex= Lex; - sp_pcontext *ctx= lex->spcont; - sp_label_t *lab= ctx->find_label($1.str); - - if (lab) - { - net_printf(YYTHD, ER_SP_LABEL_REDEFINE, $1.str); - YYABORT; - } - else - { - lab= lex->spcont->push_label($1.str, - lex->sphead->instructions()); - lab->type= SP_LAB_ITER; - } - } - sp_unlabeled_control sp_opt_label - { - LEX *lex= Lex; - - if ($5.str) - { - sp_label_t *lab= lex->spcont->find_label($5.str); - - if (!lab || - my_strcasecmp(system_charset_info, $5.str, lab->name) != 0) - { - net_printf(YYTHD, ER_SP_LABEL_MISMATCH, $5.str); - YYABORT; - } - } - lex->sphead->backpatch(lex->spcont->pop_label()); - } - ; - -sp_opt_label: - /* Empty */ - { $$.str= NULL; $$.length= 0; } - | IDENT - { $$= $1; } - ; - -sp_unlabeled_control: - BEGIN_SYM - { /* QQ This is just a dummy for grouping declarations and statements - together. No [[NOT] ATOMIC] yet, and we need to figure out how - make it coexist with the existing BEGIN COMMIT/ROLLBACK. */ - LEX *lex= Lex; - sp_label_t *lab= lex->spcont->last_label(); - - lab->type= SP_LAB_BEGIN; - lex->spcont= lex->spcont->push_context(); - } - sp_decls - sp_proc_stmts - END - { - LEX *lex= Lex; - sp_head *sp= lex->sphead; - sp_pcontext *ctx= lex->spcont; - - sp->backpatch(ctx->last_label()); /* We always have a label */ - if ($3.hndlrs) - sp->add_instr(new sp_instr_hpop(sp->instructions(), ctx, - $3.hndlrs)); - if ($3.curs) - sp->add_instr(new sp_instr_cpop(sp->instructions(), ctx, - $3.curs)); - lex->spcont= ctx->pop_context(); - } - | LOOP_SYM - sp_proc_stmts1 END LOOP_SYM - { - LEX *lex= Lex; - uint ip= lex->sphead->instructions(); - sp_label_t *lab= lex->spcont->last_label(); /* Jumping back */ - sp_instr_jump *i = new sp_instr_jump(ip, lex->spcont, lab->ip); - - lex->sphead->add_instr(i); - } - | WHILE_SYM expr DO_SYM - { - LEX *lex= Lex; - sp_head *sp= lex->sphead; - uint ip= sp->instructions(); - sp_instr_jump_if_not *i = new sp_instr_jump_if_not(ip, lex->spcont, - $2); - - /* Jumping forward */ - sp->push_backpatch(i, lex->spcont->last_label()); - i->tables= lex->query_tables; - lex->query_tables= 0; - sp->add_instr(i); - } - sp_proc_stmts1 END WHILE_SYM - { - LEX *lex= Lex; - uint ip= lex->sphead->instructions(); - sp_label_t *lab= lex->spcont->last_label(); /* Jumping back */ - sp_instr_jump *i = new sp_instr_jump(ip, lex->spcont, lab->ip); - - lex->sphead->add_instr(i); - } - | REPEAT_SYM sp_proc_stmts1 UNTIL_SYM expr END REPEAT_SYM - { - LEX *lex= Lex; - uint ip= lex->sphead->instructions(); - sp_label_t *lab= lex->spcont->last_label(); /* Jumping back */ - sp_instr_jump_if_not *i = new sp_instr_jump_if_not(ip, lex->spcont, - $4, lab->ip); - - i->tables= lex->query_tables; - lex->query_tables= 0; - lex->sphead->add_instr(i); - } - ; - -trg_action_time: - BEFORE_SYM - { Lex->trg_chistics.action_time= TRG_ACTION_BEFORE; } - | AFTER_SYM - { Lex->trg_chistics.action_time= TRG_ACTION_AFTER; } - ; - -trg_event: - INSERT - { Lex->trg_chistics.event= TRG_EVENT_INSERT; } - | UPDATE_SYM - { Lex->trg_chistics.event= TRG_EVENT_UPDATE; } - | DELETE_SYM - { Lex->trg_chistics.event= TRG_EVENT_DELETE; } ; create2: @@ -2437,10 +1117,6 @@ create_select: lex->sql_command= SQLCOM_INSERT_SELECT; else if (lex->sql_command == SQLCOM_REPLACE) lex->sql_command= SQLCOM_REPLACE_SELECT; - /* - The following work only with the local list, the global list - is created correctly in this case - */ lex->current_select->table_list.save_and_clear(&lex->save_list); mysql_init_select(lex); lex->current_select->parsing_place= SELECT_LIST; @@ -2450,13 +1126,7 @@ create_select: Select->parsing_place= NO_MATTER; } opt_select_from - { - /* - The following work only with the local list, the global list - is created correctly in this case - */ - Lex->current_select->table_list.push_front(&Lex->save_list); - } + { Lex->current_select->table_list.push_front(&Lex->save_list); } ; opt_as: @@ -2504,19 +1174,19 @@ create_table_options: | create_table_option ',' create_table_options; create_table_option: - ENGINE_SYM opt_equal storage_engines { Lex->create_info.db_type= $3; Lex->create_info.used_fields|= HA_CREATE_USED_ENGINE; } - | TYPE_SYM opt_equal storage_engines { Lex->create_info.db_type= $3; WARN_DEPRECATED("TYPE=storage_engine","ENGINE=storage_engine"); Lex->create_info.used_fields|= HA_CREATE_USED_ENGINE; } + ENGINE_SYM opt_equal storage_engines { Lex->create_info.db_type= $3; } + | TYPE_SYM opt_equal storage_engines { Lex->create_info.db_type= $3; WARN_DEPRECATED("TYPE=storage_engine","ENGINE=storage_engine"); } | MAX_ROWS opt_equal ulonglong_num { Lex->create_info.max_rows= $3; Lex->create_info.used_fields|= HA_CREATE_USED_MAX_ROWS;} | MIN_ROWS opt_equal ulonglong_num { Lex->create_info.min_rows= $3; Lex->create_info.used_fields|= HA_CREATE_USED_MIN_ROWS;} | AVG_ROW_LENGTH opt_equal ULONG_NUM { Lex->create_info.avg_row_length=$3; Lex->create_info.used_fields|= HA_CREATE_USED_AVG_ROW_LENGTH;} - | PASSWORD opt_equal TEXT_STRING_sys { Lex->create_info.password=$3.str; Lex->create_info.used_fields|= HA_CREATE_USED_PASSWORD; } - | COMMENT_SYM opt_equal TEXT_STRING_sys { Lex->create_info.comment=$3.str; Lex->create_info.used_fields|= HA_CREATE_USED_COMMENT; } + | PASSWORD opt_equal TEXT_STRING_sys { Lex->create_info.password=$3.str; } + | COMMENT_SYM opt_equal TEXT_STRING_sys { Lex->create_info.comment=$3.str; } | AUTO_INC opt_equal ulonglong_num { Lex->create_info.auto_increment_value=$3; Lex->create_info.used_fields|= HA_CREATE_USED_AUTO;} | PACK_KEYS_SYM opt_equal ULONG_NUM { Lex->create_info.table_options|= $3 ? HA_OPTION_PACK_KEYS : HA_OPTION_NO_PACK_KEYS; Lex->create_info.used_fields|= HA_CREATE_USED_PACK_KEYS;} | PACK_KEYS_SYM opt_equal DEFAULT { Lex->create_info.table_options&= ~(HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS); Lex->create_info.used_fields|= HA_CREATE_USED_PACK_KEYS;} - | CHECKSUM_SYM opt_equal ULONG_NUM { Lex->create_info.table_options|= $3 ? HA_OPTION_CHECKSUM : HA_OPTION_NO_CHECKSUM; Lex->create_info.used_fields|= HA_CREATE_USED_CHECKSUM; } - | DELAY_KEY_WRITE_SYM opt_equal ULONG_NUM { Lex->create_info.table_options|= $3 ? HA_OPTION_DELAY_KEY_WRITE : HA_OPTION_NO_DELAY_KEY_WRITE; Lex->create_info.used_fields|= HA_CREATE_USED_DELAY_KEY_WRITE; } - | ROW_FORMAT_SYM opt_equal row_types { Lex->create_info.row_type= $3; Lex->create_info.used_fields|= HA_CREATE_USED_ROW_FORMAT; } + | CHECKSUM_SYM opt_equal ULONG_NUM { Lex->create_info.table_options|= $3 ? HA_OPTION_CHECKSUM : HA_OPTION_NO_CHECKSUM; } + | DELAY_KEY_WRITE_SYM opt_equal ULONG_NUM { Lex->create_info.table_options|= $3 ? HA_OPTION_DELAY_KEY_WRITE : HA_OPTION_NO_DELAY_KEY_WRITE; } + | ROW_FORMAT_SYM opt_equal row_types { Lex->create_info.row_type= $3; } | RAID_TYPE opt_equal raid_types { Lex->create_info.raid_type= $3; Lex->create_info.used_fields|= HA_CREATE_USED_RAID;} | RAID_CHUNKS opt_equal ULONG_NUM { Lex->create_info.raid_chunks= $3; Lex->create_info.used_fields|= HA_CREATE_USED_RAID;} | RAID_CHUNKSIZE opt_equal ULONG_NUM { Lex->create_info.raid_chunksize= $3*RAID_BLOCK_SIZE; Lex->create_info.used_fields|= HA_CREATE_USED_RAID;} @@ -2527,20 +1197,18 @@ create_table_option: TABLE_LIST *table_list= lex->select_lex.get_table_list(); lex->create_info.merge_list= lex->select_lex.table_list; lex->create_info.merge_list.elements--; - lex->create_info.merge_list.first= - (byte*) (table_list->next_local); + lex->create_info.merge_list.first= (byte*) (table_list->next); lex->select_lex.table_list.elements=1; - lex->select_lex.table_list.next= - (byte**) &(table_list->next_local); - table_list->next_local= 0; + lex->select_lex.table_list.next= (byte**) &(table_list->next); + table_list->next=0; lex->create_info.used_fields|= HA_CREATE_USED_UNION; } | default_charset | default_collation | INSERT_METHOD opt_equal merge_insert_types { Lex->create_info.merge_insert_method= $3; Lex->create_info.used_fields|= HA_CREATE_USED_INSERT_METHOD;} - | DATA_SYM DIRECTORY_SYM opt_equal TEXT_STRING_sys { Lex->create_info.data_file_name= $4.str; Lex->create_info.used_fields|= HA_CREATE_USED_DATADIR; } - | INDEX_SYM DIRECTORY_SYM opt_equal TEXT_STRING_sys { Lex->create_info.index_file_name= $4.str; Lex->create_info.used_fields|= HA_CREATE_USED_INDEXDIR; } - ; + | DATA_SYM DIRECTORY_SYM opt_equal TEXT_STRING_sys + { Lex->create_info.data_file_name= $4.str; } + | INDEX_SYM DIRECTORY_SYM opt_equal TEXT_STRING_sys { Lex->create_info.index_file_name= $4.str; }; default_charset: opt_default charset opt_equal charset_name_or_default @@ -3155,12 +1823,14 @@ key_part: | ident '(' NUM ')' { int key_part_len= atoi($3.str); +#if MYSQL_VERSION_ID < 50000 if (!key_part_len) { my_printf_error(ER_UNKNOWN_ERROR, "Key part '%s' length cannot be 0", MYF(0), $1.str); } +#endif $$=new key_part_spec($1.str,(uint) key_part_len); }; @@ -3199,7 +1869,8 @@ alter: lex->create_info.db_type= DB_TYPE_DEFAULT; lex->create_info.default_table_charset= NULL; lex->create_info.row_type= ROW_TYPE_NOT_USED; - lex->alter_info.reset(); + lex->alter_info.reset(); + lex->alter_info.is_simple= 1; lex->alter_info.flags= 0; } alter_list @@ -3214,48 +1885,8 @@ alter: LEX *lex=Lex; lex->sql_command=SQLCOM_ALTER_DB; lex->name=$3.str; - } - | ALTER PROCEDURE sp_name - { - LEX *lex= Lex; - - bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics)); - } - sp_a_chistics - { - THD *thd= YYTHD; - LEX *lex=Lex; + }; - lex->sql_command= SQLCOM_ALTER_PROCEDURE; - lex->spname= $3; - } - | ALTER FUNCTION_SYM sp_name - { - LEX *lex= Lex; - - bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics)); - } - sp_a_chistics - { - THD *thd= YYTHD; - LEX *lex=Lex; - - lex->sql_command= SQLCOM_ALTER_FUNCTION; - lex->spname= $3; - } - | ALTER algorithm VIEW_SYM table_ident - { - THD *thd= YYTHD; - LEX *lex= thd->lex; - lex->sql_command= SQLCOM_CREATE_VIEW; - lex->create_view_mode= VIEW_ALTER; - lex->select_lex.resolve_mode= SELECT_LEX::SELECT_MODE; - /* first table in list is target VIEW name */ - lex->select_lex.add_table_to_list(thd, $4, NULL, 0); - } - opt_view_list AS select_init check_option - {} - ; alter_list: | DISCARD TABLESPACE { Lex->alter_info.tablespace_op= DISCARD_TABLESPACE; } @@ -3264,27 +1895,27 @@ alter_list: | alter_list ',' alter_list_item; add_column: - ADD opt_column + ADD opt_column { LEX *lex=Lex; - lex->change=0; - lex->alter_info.flags|= ALTER_ADD_COLUMN; + lex->change=0; + lex->alter_info.flags|= ALTER_ADD_COLUMN; }; alter_list_item: - add_column column_def opt_place { } - | ADD key_def - { - Lex->alter_info.flags|= ALTER_ADD_INDEX; + add_column column_def opt_place { Lex->alter_info.is_simple= 0; } + | ADD key_def + { + LEX *lex=Lex; + lex->alter_info.is_simple= 0; + lex->alter_info.flags|= ALTER_ADD_INDEX; } - | add_column '(' field_list ')' - { - Lex->alter_info.flags|= ALTER_ADD_COLUMN | ALTER_ADD_INDEX; - } + | add_column '(' field_list ')' { Lex->alter_info.is_simple= 0; } | CHANGE opt_column field_ident { LEX *lex=Lex; - lex->change= $3.str; + lex->change= $3.str; + lex->alter_info.is_simple= 0; lex->alter_info.flags|= ALTER_CHANGE_COLUMN; } field_spec opt_place @@ -3295,6 +1926,7 @@ alter_list_item: lex->default_value= lex->on_update_value= 0; lex->comment=0; lex->charset= NULL; + lex->alter_info.is_simple= 0; lex->alter_info.flags|= ALTER_CHANGE_COLUMN; } type opt_attribute @@ -3314,18 +1946,17 @@ alter_list_item: { LEX *lex=Lex; lex->alter_info.drop_list.push_back(new Alter_drop(Alter_drop::COLUMN, - $3.str)); + $3.str)); + lex->alter_info.is_simple= 0; lex->alter_info.flags|= ALTER_DROP_COLUMN; } - | DROP FOREIGN KEY_SYM opt_ident - { - Lex->alter_info.flags|= ALTER_DROP_INDEX; - } + | DROP FOREIGN KEY_SYM opt_ident { Lex->alter_info.is_simple= 0; } | DROP PRIMARY_SYM KEY_SYM { LEX *lex=Lex; lex->alter_info.drop_list.push_back(new Alter_drop(Alter_drop::KEY, primary_key_name)); + lex->alter_info.is_simple= 0; lex->alter_info.flags|= ALTER_DROP_INDEX; } | DROP key_or_index field_ident @@ -3333,32 +1964,25 @@ alter_list_item: LEX *lex=Lex; lex->alter_info.drop_list.push_back(new Alter_drop(Alter_drop::KEY, $3.str)); + lex->alter_info.is_simple= 0; lex->alter_info.flags|= ALTER_DROP_INDEX; } - | DISABLE_SYM KEYS - { - LEX *lex=Lex; - lex->alter_info.keys_onoff= DISABLE; - lex->alter_info.flags|= ALTER_KEYS_ONOFF; - } - | ENABLE_SYM KEYS - { - LEX *lex=Lex; - lex->alter_info.keys_onoff= ENABLE; - lex->alter_info.flags|= ALTER_KEYS_ONOFF; - } + | DISABLE_SYM KEYS { Lex->alter_info.keys_onoff= DISABLE; } + | ENABLE_SYM KEYS { Lex->alter_info.keys_onoff= ENABLE; } | ALTER opt_column field_ident SET DEFAULT signed_literal { LEX *lex=Lex; lex->alter_info.alter_list.push_back(new Alter_column($3.str,$6)); - lex->alter_info.flags|= ALTER_CHANGE_COLUMN_DEFAULT; + lex->alter_info.is_simple= 0; + lex->alter_info.flags|= ALTER_CHANGE_COLUMN; } | ALTER opt_column field_ident DROP DEFAULT { LEX *lex=Lex; lex->alter_info.alter_list.push_back(new Alter_column($3.str, (Item*) 0)); - lex->alter_info.flags|= ALTER_CHANGE_COLUMN_DEFAULT; + lex->alter_info.is_simple= 0; + lex->alter_info.flags|= ALTER_CHANGE_COLUMN; } | RENAME opt_to table_ident { @@ -3388,20 +2012,22 @@ alter_list_item: YYABORT; } LEX *lex= Lex; - lex->create_info.table_charset= + lex->create_info.table_charset= lex->create_info.default_table_charset= $5; lex->create_info.used_fields|= (HA_CREATE_USED_CHARSET | HA_CREATE_USED_DEFAULT_CHARSET); - lex->alter_info.flags|= ALTER_CONVERT; + lex->alter_info.is_simple= 0; } - | create_table_options_space_separated + | create_table_options_space_separated { LEX *lex=Lex; + lex->alter_info.is_simple= 0; lex->alter_info.flags|= ALTER_OPTIONS; } - | order_clause + | order_clause { LEX *lex=Lex; + lex->alter_info.is_simple= 0; lex->alter_info.flags|= ALTER_ORDER; }; @@ -3414,10 +2040,9 @@ opt_ignore: | IGNORE_SYM { Lex->duplicates=DUP_IGNORE; }; opt_restrict: - /* empty */ { Lex->drop_mode= DROP_DEFAULT; } - | RESTRICT { Lex->drop_mode= DROP_RESTRICT; } - | CASCADE { Lex->drop_mode= DROP_CASCADE; } - ; + /* empty */ {} + | RESTRICT {} + | CASCADE {}; opt_place: /* empty */ {} @@ -3435,7 +2060,7 @@ opt_to: */ slave: - START_SYM SLAVE slave_thread_opts + START_SYM SLAVE slave_thread_opts { LEX *lex=Lex; lex->sql_command = SQLCOM_SLAVE_START; @@ -3473,10 +2098,21 @@ slave: start: - START_SYM TRANSACTION_SYM { Lex->sql_command = SQLCOM_BEGIN;} - {} + START_SYM TRANSACTION_SYM start_transaction_opts + { + Lex->sql_command = SQLCOM_BEGIN; + Lex->start_transaction_opt= $3; + } ; +start_transaction_opts: + /*empty*/ { $$ = 0; } + | WITH CONSISTENT_SYM SNAPSHOT_SYM + { + $$= MYSQL_START_TRANS_OPT_WITH_CONS_SNAPSHOT; + } + ; + slave_thread_opts: { Lex->slave_thd_opt= 0; } slave_thread_opt_list @@ -3906,12 +2542,8 @@ select_item: YYABORT; if ($4.str) $2->set_name($4.str,$4.length,system_charset_info); - else if (!$2->name) { - char *str = $1; - if (str[-1] == '`') - str--; - $2->set_name(str,(uint) ($3 - str), YYTHD->charset()); - } + else if (!$2->name) + $2->set_name($1,(uint) ($3 - $1), YYTHD->charset()); }; remember_name: @@ -4135,16 +2767,12 @@ simple_expr: | '@' ident_or_text SET_VAR expr { $$= new Item_func_set_user_var($2,$4); - LEX *lex= Lex; - lex->uncacheable(UNCACHEABLE_RAND); - lex->variables_used= 1; + Lex->uncacheable(UNCACHEABLE_RAND); } | '@' ident_or_text { $$= new Item_func_get_user_var($2); - LEX *lex= Lex; - lex->uncacheable(UNCACHEABLE_RAND); - lex->variables_used= 1; + Lex->uncacheable(UNCACHEABLE_RAND); } | '@' '@' opt_var_ident_type ident_or_text opt_component { @@ -4156,7 +2784,6 @@ simple_expr: } if (!($$= get_system_var(YYTHD, (enum_var_type) $3, $4, $5))) YYABORT; - Lex->variables_used= 1; } | sum_expr | '+' expr %prec NEG { $$= $2; } @@ -4261,8 +2888,6 @@ simple_expr: { $$= new Item_date_add_interval($3, $5, INTERVAL_DAY, 0);} | ADDDATE_SYM '(' expr ',' INTERVAL_SYM expr interval ')' { $$= new Item_date_add_interval($3, $6, $7, 0); } - | REPEAT_SYM '(' expr ',' expr ')' - { $$= new Item_func_repeat($3,$5); } | ATAN '(' expr ')' { $$= new Item_func_atan($3); } | ATAN '(' expr ',' expr ')' @@ -4279,8 +2904,6 @@ simple_expr: { $$= new Item_func_concat(* $3); } | CONCAT_WS '(' expr ',' expr_list ')' { $5->push_front($3); $$= new Item_func_concat_ws(*$5); } - | CONTAINS_SYM '(' expr ',' expr ')' - { $$= create_func_contains($3, $5); } | CONVERT_TZ_SYM '(' expr ',' expr ',' expr ')' { Lex->time_zone_tables_used= &fake_time_zone_tables_list; @@ -4436,8 +3059,6 @@ simple_expr: { $$= new Item_func_old_password($3); } | POSITION_SYM '(' no_in_expr IN_SYM expr ')' { $$ = new Item_func_locate($5,$3); } - | QUARTER_SYM '(' expr ')' - { $$ = new Item_func_quarter($3); } | RAND '(' expr ')' { $$= new Item_func_rand($3); Lex->uncacheable(UNCACHEABLE_RAND);} | RAND '(' ')' @@ -4449,11 +3070,6 @@ simple_expr: | ROUND '(' expr ')' { $$= new Item_func_round($3, new Item_int((char*)"0",0,1),0); } | ROUND '(' expr ',' expr ')' { $$= new Item_func_round($3,$5,0); } - | ROW_COUNT_SYM '(' ')' - { - $$= new Item_func_row_count(); - Lex->safe_to_cache_query= 0; - } | SUBDATE_SYM '(' expr ',' expr ')' { $$= new Item_date_add_interval($3, $5, INTERVAL_DAY, 1);} | SUBDATE_SYM '(' expr ',' INTERVAL_SYM expr interval ')' @@ -4476,10 +3092,6 @@ simple_expr: { $$= new Item_datetime_typecast($3); } | TIMESTAMP '(' expr ',' expr ')' { $$= new Item_func_add_time($3, $5, 1, 0); } - | TIMESTAMP_ADD '(' interval_time_st ',' expr ',' expr ')' - { $$= new Item_date_add_interval($7,$5,$3,0); } - | TIMESTAMP_DIFF '(' interval_time_st ',' expr ',' expr ')' - { $$= new Item_func_timestamp_diff($5,$7,$3); } | TRIM '(' expr ')' { $$= new Item_func_trim($3); } | TRIM '(' LEADING expr FROM expr ')' @@ -4500,90 +3112,48 @@ simple_expr: { $$= new Item_func_round($3,$5,1); } | TRUE_SYM { $$= new Item_int((char*) "TRUE",1,1); } - | ident '.' ident '(' udf_expr_list ')' + | UDA_CHAR_SUM '(' udf_expr_list ')' { - LEX *lex= Lex; - sp_name *name= new sp_name($1, $3); - - name->init_qname(YYTHD); - sp_add_fun_to_lex(Lex, name); - if ($5) - $$= new Item_func_sp(name, *$5); + if ($3 != NULL) + $$ = new Item_sum_udf_str($1, *$3); else - $$= new Item_func_sp(name); + $$ = new Item_sum_udf_str($1); + } + | UDA_FLOAT_SUM '(' udf_expr_list ')' + { + if ($3 != NULL) + $$ = new Item_sum_udf_float($1, *$3); + else + $$ = new Item_sum_udf_float($1); + } + | UDA_INT_SUM '(' udf_expr_list ')' + { + if ($3 != NULL) + $$ = new Item_sum_udf_int($1, *$3); + else + $$ = new Item_sum_udf_int($1); + } + | UDF_CHAR_FUNC '(' udf_expr_list ')' + { + if ($3 != NULL) + $$ = new Item_func_udf_str($1, *$3); + else + $$ = new Item_func_udf_str($1); + } + | UDF_FLOAT_FUNC '(' udf_expr_list ')' + { + if ($3 != NULL) + $$ = new Item_func_udf_float($1, *$3); + else + $$ = new Item_func_udf_float($1); + } + | UDF_INT_FUNC '(' udf_expr_list ')' + { + if ($3 != NULL) + $$ = new Item_func_udf_int($1, *$3); + else + $$ = new Item_func_udf_int($1); } - | IDENT_sys '(' udf_expr_list ')' - { -#ifdef HAVE_DLOPEN - udf_func *udf; - - if (using_udf_functions && (udf=find_udf($1.str, $1.length))) - { - switch (udf->returns) { - case STRING_RESULT: - if (udf->type == UDFTYPE_FUNCTION) - { - if ($3 != NULL) - $$ = new Item_func_udf_str(udf, *$3); - else - $$ = new Item_func_udf_str(udf); - } - else - { - if ($3 != NULL) - $$ = new Item_sum_udf_str(udf, *$3); - else - $$ = new Item_sum_udf_str(udf); - } - break; - case REAL_RESULT: - if (udf->type == UDFTYPE_FUNCTION) - { - if ($3 != NULL) - $$ = new Item_func_udf_float(udf, *$3); - else - $$ = new Item_func_udf_float(udf); - } - else - { - if ($3 != NULL) - $$ = new Item_sum_udf_float(udf, *$3); - else - $$ = new Item_sum_udf_float(udf); - } - break; - case INT_RESULT: - if (udf->type == UDFTYPE_FUNCTION) - { - if ($3 != NULL) - $$ = new Item_func_udf_int(udf, *$3); - else - $$ = new Item_func_udf_int(udf); - } - else - { - if ($3 != NULL) - $$ = new Item_sum_udf_int(udf, *$3); - else - $$ = new Item_sum_udf_int(udf); - } - break; - default: - YYABORT; - } - } - else -#endif /* HAVE_DLOPEN */ - { - sp_name *name= sp_name_current_db_new(YYTHD, $1); - - sp_add_fun_to_lex(Lex, name); - if ($3) - $$= new Item_func_sp(name, *$3); - else - $$= new Item_func_sp(name); - } - } | UNIQUE_USERS '(' text_literal ',' NUM ',' NUM ',' expr_list ')' { $$= new Item_func_unique_users($3,atoi($5.str),atoi($7.str), * $9); @@ -4691,37 +3261,8 @@ fulltext_options: ; udf_expr_list: - /* empty */ { $$= NULL; } - | udf_expr_list2 { $$= $1;} - ; - -udf_expr_list2: - { Select->expr_list.push_front(new List<Item>); } - udf_expr_list3 - { $$= Select->expr_list.pop(); } - ; - -udf_expr_list3: - udf_expr - { - Select->expr_list.head()->push_back($1); - } - | udf_expr_list3 ',' udf_expr - { - Select->expr_list.head()->push_back($3); - } - ; - -udf_expr: - remember_name expr remember_end select_alias - { - if ($4.str) - $2->set_name($4.str,$4.length,system_charset_info); - else - $2->set_name($1,(uint) ($3 - $1), YYTHD->charset()); - $$= $2; - } - ; + /* empty */ { $$= NULL; } + | expr_list { $$= $1;}; sum_expr: AVG_SYM '(' in_sum_expr ')' @@ -4746,25 +3287,14 @@ sum_expr: { $$= new Item_sum_unique_users($3,atoi($5.str),atoi($7.str),$9); } | MIN_SYM '(' in_sum_expr ')' { $$=new Item_sum_min($3); } -/* - According to ANSI SQL, DISTINCT is allowed and has - no sence inside MIN and MAX grouping functions; so MIN|MAX(DISTINCT ...) - is processed like an ordinary MIN | MAX() - */ - | MIN_SYM '(' DISTINCT in_sum_expr ')' - { $$=new Item_sum_min($4); } | MAX_SYM '(' in_sum_expr ')' { $$=new Item_sum_max($3); } - | MAX_SYM '(' DISTINCT in_sum_expr ')' - { $$=new Item_sum_max($4); } | STD_SYM '(' in_sum_expr ')' { $$=new Item_sum_std($3); } | VARIANCE_SYM '(' in_sum_expr ')' { $$=new Item_sum_variance($3); } | SUM_SYM '(' in_sum_expr ')' { $$=new Item_sum_sum($3); } - | SUM_SYM '(' DISTINCT in_sum_expr ')' - { $$=new Item_sum_sum_distinct($4); } | GROUP_CONCAT_SYM '(' opt_distinct { Select->in_sum_expr++; } expr_list opt_gorder_clause @@ -4878,80 +3408,59 @@ when_list2: sel->when_list.head()->push_back($5); }; -table_ref: - table_factor { $$=$1; } - | join_table { $$=$1; } - { - LEX *lex= Lex; - if (!($$= lex->current_select->nest_last_join(lex->thd))) - YYABORT; - } - ; - join_table_list: - table_ref { $$=$1; } - | join_table_list ',' table_ref { $$=$3; } - ; - -join_table: - table_ref normal_join table_ref { $$=$3; } - | table_ref STRAIGHT_JOIN table_factor - { $3->straight=1; $$=$3 ; } - | table_ref normal_join table_ref ON expr + '(' join_table_list ')' { $$=$2; } + | join_table { $$=$1; } + | join_table_list ',' join_table_list { $$=$3; } + | join_table_list normal_join join_table_list { $$=$3; } + | join_table_list STRAIGHT_JOIN join_table_list + { $$=$3 ; $1->next->straight=1; } + | join_table_list normal_join join_table_list ON expr { add_join_on($3,$5); $$=$3; } - | table_ref normal_join table_ref + | join_table_list normal_join join_table_list USING { SELECT_LEX *sel= Select; - sel->save_names_for_using_list($1, $3); + sel->db1=$1->db; sel->table1=$1->alias; + sel->db2=$3->db; sel->table2=$3->alias; } '(' using_list ')' { add_join_on($3,$7); $$=$3; } - | table_ref LEFT opt_outer JOIN_SYM table_ref ON expr + | join_table_list LEFT opt_outer JOIN_SYM join_table_list ON expr { add_join_on($5,$7); $5->outer_join|=JOIN_TYPE_LEFT; $$=$5; } - | table_ref LEFT opt_outer JOIN_SYM table_factor + | join_table_list LEFT opt_outer JOIN_SYM join_table_list { SELECT_LEX *sel= Select; - sel->save_names_for_using_list($1, $5); + sel->db1=$1->db; sel->table1=$1->alias; + sel->db2=$5->db; sel->table2=$5->alias; } USING '(' using_list ')' { add_join_on($5,$9); $5->outer_join|=JOIN_TYPE_LEFT; $$=$5; } - | table_ref NATURAL LEFT opt_outer JOIN_SYM table_factor + | join_table_list NATURAL LEFT opt_outer JOIN_SYM join_table_list { - add_join_natural($1,$6); - $6->outer_join|=JOIN_TYPE_LEFT; + add_join_natural($1,$1->next); + $1->next->outer_join|=JOIN_TYPE_LEFT; $$=$6; } - | table_ref RIGHT opt_outer JOIN_SYM table_ref ON expr - { - LEX *lex= Lex; - if (!($$= lex->current_select->convert_right_join())) - YYABORT; - add_join_on($$, $7); - } - | table_ref RIGHT opt_outer JOIN_SYM table_factor + | join_table_list RIGHT opt_outer JOIN_SYM join_table_list ON expr + { add_join_on($1,$7); $1->outer_join|=JOIN_TYPE_RIGHT; $$=$5; } + | join_table_list RIGHT opt_outer JOIN_SYM join_table_list { SELECT_LEX *sel= Select; - sel->save_names_for_using_list($1, $5); + sel->db1=$1->db; sel->table1=$1->alias; + sel->db2=$5->db; sel->table2=$5->alias; } USING '(' using_list ')' - { - LEX *lex= Lex; - if (!($$= lex->current_select->convert_right_join())) - YYABORT; - add_join_on($$, $9); - } - | table_ref NATURAL RIGHT opt_outer JOIN_SYM table_factor + { add_join_on($1,$9); $1->outer_join|=JOIN_TYPE_RIGHT; $$=$5; } + | join_table_list NATURAL RIGHT opt_outer JOIN_SYM join_table_list { - add_join_natural($6,$1); - LEX *lex= Lex; - if (!($$= lex->current_select->convert_right_join())) - YYABORT; + add_join_natural($1->next,$1); + $1->outer_join|=JOIN_TYPE_RIGHT; + $$=$6; } - | table_ref NATURAL JOIN_SYM table_factor - { add_join_natural($1,$4); $$=$4; }; - + | join_table_list NATURAL JOIN_SYM join_table_list + { add_join_natural($1,$1->next); $$=$4; }; normal_join: JOIN_SYM {} @@ -4959,7 +3468,7 @@ normal_join: | CROSS JOIN_SYM {} ; -table_factor: +join_table: { SELECT_LEX *sel= Select; sel->use_index_ptr=sel->ignore_index_ptr=0; @@ -4975,21 +3484,8 @@ table_factor: sel->get_use_index(), sel->get_ignore_index()))) YYABORT; - sel->add_joined_table($$); } - | '(' - { - LEX *lex= Lex; - if (lex->current_select->init_nested_join(lex->thd)) - YYABORT; - } - join_table_list ')' - { - LEX *lex= Lex; - if (!($$= lex->current_select->end_nested_join(lex->thd))) - YYABORT; - } - | '{' ident table_ref LEFT OUTER JOIN_SYM table_ref ON expr '}' + | '{' ident join_table LEFT OUTER JOIN_SYM join_table ON expr '}' { add_join_on($7,$9); $7->outer_join|=JOIN_TYPE_LEFT; $$=$7; } | '(' SELECT_SYM select_derived ')' opt_table_alias { @@ -5002,13 +3498,12 @@ table_factor: (List<String> *)0))) YYABORT; - lex->current_select->add_joined_table($$); }; select_derived: { LEX *lex= Lex; - lex->derived_tables|= DERIVED_SUBQUERY; + lex->derived_tables= 1; if (((int)lex->sql_command >= (int)SQLCOM_HA_OPEN && lex->sql_command <= (int)SQLCOM_HA_READ) || lex->sql_command == (int)SQLCOM_KILL) @@ -5099,29 +3594,23 @@ using_list: }; interval: - interval_time_st {} - | DAY_HOUR_SYM { $$=INTERVAL_DAY_HOUR; } + DAY_HOUR_SYM { $$=INTERVAL_DAY_HOUR; } | DAY_MICROSECOND_SYM { $$=INTERVAL_DAY_MICROSECOND; } | DAY_MINUTE_SYM { $$=INTERVAL_DAY_MINUTE; } | DAY_SECOND_SYM { $$=INTERVAL_DAY_SECOND; } + | DAY_SYM { $$=INTERVAL_DAY; } | HOUR_MICROSECOND_SYM { $$=INTERVAL_HOUR_MICROSECOND; } | HOUR_MINUTE_SYM { $$=INTERVAL_HOUR_MINUTE; } | HOUR_SECOND_SYM { $$=INTERVAL_HOUR_SECOND; } + | HOUR_SYM { $$=INTERVAL_HOUR; } | MICROSECOND_SYM { $$=INTERVAL_MICROSECOND; } | MINUTE_MICROSECOND_SYM { $$=INTERVAL_MINUTE_MICROSECOND; } | MINUTE_SECOND_SYM { $$=INTERVAL_MINUTE_SECOND; } - | SECOND_MICROSECOND_SYM { $$=INTERVAL_SECOND_MICROSECOND; } - | YEAR_MONTH_SYM { $$=INTERVAL_YEAR_MONTH; }; - -interval_time_st: - DAY_SYM { $$=INTERVAL_DAY; } - | WEEK_SYM { $$=INTERVAL_WEEK; } - | HOUR_SYM { $$=INTERVAL_HOUR; } - | FRAC_SECOND_SYM { $$=INTERVAL_MICROSECOND; } | MINUTE_SYM { $$=INTERVAL_MINUTE; } | MONTH_SYM { $$=INTERVAL_MONTH; } - | QUARTER_SYM { $$=INTERVAL_QUARTER; } + | SECOND_MICROSECOND_SYM { $$=INTERVAL_SECOND_MICROSECOND; } | SECOND_SYM { $$=INTERVAL_SECOND; } + | YEAR_MONTH_SYM { $$=INTERVAL_YEAR_MONTH; } | YEAR_SYM { $$=INTERVAL_YEAR; } ; @@ -5182,11 +3671,8 @@ having_clause: opt_escape: ESCAPE_SYM simple_expr { $$= $2; } | /* empty */ - { - - $$= ((YYTHD->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES) ? - new Item_string("", 0, &my_charset_latin1) : - new Item_string("\\", 1, &my_charset_latin1)); + { + $$= new Item_string("\\", 1, &my_charset_latin1); } ; @@ -5399,33 +3885,12 @@ select_var_list: | select_var_ident {} ; -select_var_ident: - '@' ident_or_text +select_var_ident: '@' ident_or_text { LEX *lex=Lex; - if (lex->result) - ((select_dumpvar *)lex->result)->var_list.push_back( new my_var($2,0,0,(enum_field_types)0)); - else + if (lex->result && ((select_dumpvar *)lex->result)->var_list.push_back((LEX_STRING*) sql_memdup(&$2,sizeof(LEX_STRING)))) YYABORT; } - | ident_or_text - { - LEX *lex=Lex; - sp_pvar_t *t; - - if (!lex->spcont || !(t=lex->spcont->find_pvar(&$1))) - { - net_printf(YYTHD, ER_SP_UNDECLARED_VAR, $1.str); - YYABORT; - } - if (! lex->result) - YYABORT; - else - { - ((select_dumpvar *)lex->result)->var_list.push_back( new my_var($1,1,t->offset,t->type)); - t->isset= TRUE; - } - } ; into: @@ -5501,29 +3966,11 @@ drop: lex->drop_if_exists=$3; lex->name=$4.str; } - | DROP FUNCTION_SYM if_exists sp_name + | DROP UDF_SYM IDENT_sys { LEX *lex=Lex; - if (lex->sphead) - { - net_printf(YYTHD, ER_SP_NO_DROP_SP, "FUNCTION"); - YYABORT; - } lex->sql_command = SQLCOM_DROP_FUNCTION; - lex->drop_if_exists= $3; - lex->spname= $4; - } - | DROP PROCEDURE if_exists sp_name - { - LEX *lex=Lex; - if (lex->sphead) - { - net_printf(YYTHD, ER_SP_NO_DROP_SP, "PROCEDURE"); - YYABORT; - } - lex->sql_command = SQLCOM_DROP_PROCEDURE; - lex->drop_if_exists= $3; - lex->spname= $4; + lex->udf.name = $3; } | DROP USER { @@ -5533,28 +3980,8 @@ drop: } user_list {} - | DROP VIEW_SYM if_exists table_list opt_restrict - { - THD *thd= YYTHD; - LEX *lex= thd->lex; - lex->sql_command= SQLCOM_DROP_VIEW; - lex->drop_if_exists= $3; - } - | DROP TRIGGER_SYM ident '.' ident - { - LEX *lex= Lex; + ; - lex->sql_command= SQLCOM_DROP_TRIGGER; - /* QQ: Could we loosen lock type in certain cases ? */ - if (!lex->select_lex.add_table_to_list(YYTHD, - new Table_ident($3), - (LEX_STRING*) 0, - TL_OPTION_UPDATING, - TL_WRITE)) - YYABORT; - lex->name_and_length= $5; - } - ; table_list: table_name @@ -5614,6 +4041,7 @@ replace: } insert_field_spec {} + {} ; insert_lock_option: @@ -5679,7 +4107,7 @@ ident_eq_list: ident_eq_value; ident_eq_value: - simple_ident_nospvar equal expr_or_default + simple_ident equal expr_or_default { LEX *lex=Lex; if (lex->field_list.push_back($1) || @@ -5745,6 +4173,7 @@ opt_insert_update: yyerror(ER(ER_SYNTAX_ERROR)); YYABORT; } + lex->duplicates= DUP_UPDATE; } KEY_SYM UPDATE_SYM update_list ; @@ -5782,12 +4211,12 @@ update: ; update_list: - update_list ',' simple_ident_nospvar equal expr_or_default + update_list ',' simple_ident equal expr_or_default { if (add_item_to_list(YYTHD, $3) || add_value_to_list(YYTHD, $5)) YYABORT; } - | simple_ident_nospvar equal expr_or_default + | simple_ident equal expr_or_default { if (add_item_to_list(YYTHD, $1) || add_value_to_list(YYTHD, $3)) YYABORT; @@ -5892,11 +4321,11 @@ show: SHOW show_param: DATABASES wild { Lex->sql_command= SQLCOM_SHOW_DATABASES; } - | opt_full TABLES opt_db wild + | TABLES opt_db wild { LEX *lex= Lex; lex->sql_command= SQLCOM_SHOW_TABLES; - lex->select_lex.db= $3; + lex->select_lex.db= $2; } | TABLE_SYM STATUS_SYM opt_db wild { @@ -5982,12 +4411,8 @@ show_param: { Lex->sql_command = SQLCOM_SHOW_WARNS;} | ERRORS opt_limit_clause_init { Lex->sql_command = SQLCOM_SHOW_ERRORS;} - | opt_var_type STATUS_SYM wild - { - THD *thd= YYTHD; - thd->lex->sql_command= SQLCOM_SHOW_STATUS; - thd->lex->option_type= (enum_var_type) $1; - } + | STATUS_SYM wild + { Lex->sql_command= SQLCOM_SHOW_STATUS; } | INNOBASE_SYM STATUS_SYM { Lex->sql_command = SQLCOM_SHOW_INNODB_STATUS; WARN_DEPRECATED("SHOW INNODB STATUS", "SHOW ENGINE INNODB STATUS"); } | opt_full PROCESSLIST_SYM @@ -6044,19 +4469,9 @@ show_param: } | CREATE TABLE_SYM table_ident { - LEX *lex= Lex; - lex->sql_command = SQLCOM_SHOW_CREATE; - if (!lex->select_lex.add_table_to_list(YYTHD, $3, NULL,0)) + Lex->sql_command = SQLCOM_SHOW_CREATE; + if (!Select->add_table_to_list(YYTHD, $3, NULL,0)) YYABORT; - lex->only_view= 0; - } - | CREATE VIEW_SYM table_ident - { - LEX *lex= Lex; - lex->sql_command = SQLCOM_SHOW_CREATE; - if (!lex->select_lex.add_table_to_list(YYTHD, $3, NULL, 0)) - YYABORT; - lex->only_view= 1; } | MASTER_SYM STATUS_SYM { @@ -6065,29 +4480,7 @@ show_param: | SLAVE STATUS_SYM { Lex->sql_command = SQLCOM_SHOW_SLAVE_STAT; - } - | CREATE PROCEDURE sp_name - { - LEX *lex= Lex; - - lex->sql_command = SQLCOM_SHOW_CREATE_PROC; - lex->spname= $3; - } - | CREATE FUNCTION_SYM sp_name - { - LEX *lex= Lex; - - lex->sql_command = SQLCOM_SHOW_CREATE_FUNC; - lex->spname= $3; - } - | PROCEDURE STATUS_SYM wild - { - Lex->sql_command = SQLCOM_SHOW_STATUS_PROC; - } - | FUNCTION_SYM STATUS_SYM wild - { - Lex->sql_command = SQLCOM_SHOW_STATUS_FUNC; - }; + }; show_engine_param: STATUS_SYM @@ -6277,23 +4670,18 @@ purge_option: /* kill threads */ kill: - KILL_SYM kill_option expr + KILL_SYM expr { LEX *lex=Lex; - if ($3->fix_fields(lex->thd, 0, &$3) || $3->check_cols(1)) + if ($2->fix_fields(lex->thd, 0, &$2) || $2->check_cols(1)) { send_error(lex->thd, ER_SET_CONSTANTS_ONLY); YYABORT; } lex->sql_command=SQLCOM_KILL; - lex->thread_id= (ulong) $3->val_int(); + lex->thread_id= (ulong) $2->val_int(); }; -kill_option: - /* empty */ { Lex->type= 0; } - | CONNECTION_SYM { Lex->type= 0; } - | QUERY_SYM { Lex->type= ONLY_KILL_QUERY; }; - /* change database */ use: USE_SYM ident @@ -6504,24 +4892,8 @@ NUM_literal: NUM { int error; $$ = new Item_int($1.str, (longlong) my_strtoll10($1.str, NULL, &error), $1.length); } | LONG_NUM { int error; $$ = new Item_int($1.str, (longlong) my_strtoll10($1.str, NULL, &error), $1.length); } | ULONGLONG_NUM { $$ = new Item_uint($1.str, $1.length); } - | REAL_NUM - { - $$= new Item_real($1.str, $1.length); - if (YYTHD->net.report_error) - { - send_error(YYTHD, 0, NullS); - YYABORT; - } - } - | FLOAT_NUM - { - $$ = new Item_float($1.str, $1.length); - if (YYTHD->net.report_error) - { - send_error(YYTHD, 0, NullS); - YYABORT; - } - } + | REAL_NUM { $$ = new Item_real($1.str, $1.length); } + | FLOAT_NUM { $$ = new Item_float($1.str, $1.length); } ; /********************************************************************** @@ -6529,7 +4901,7 @@ NUM_literal: **********************************************************************/ insert_ident: - simple_ident_nospvar { $$=$1; } + simple_ident { $$=$1; } | table_wild { $$=$1; }; table_wild: @@ -6553,108 +4925,28 @@ order_ident: simple_ident: ident { - sp_pvar_t *spv; - LEX *lex = Lex; - sp_pcontext *spc = lex->spcont; - - if (spc && (spv = spc->find_pvar(&$1))) - { /* We're compiling a stored procedure and found a variable */ - $$ = (Item*) new Item_splocal($1, spv->offset); - lex->variables_used= 1; - lex->safe_to_cache_query=0; - } - else - { - SELECT_LEX *sel=Select; - $$= (sel->parsing_place != IN_HAVING || - sel->get_in_sum_expr() > 0) ? - (Item*) new Item_field(NullS,NullS,$1.str) : - (Item*) new Item_ref(NullS,NullS,$1.str); - } - } - | simple_ident_q { $$= $1; } - ; - -simple_ident_nospvar: - ident - { SELECT_LEX *sel=Select; $$= (sel->parsing_place != IN_HAVING || sel->get_in_sum_expr() > 0) ? (Item*) new Item_field(NullS,NullS,$1.str) : - (Item*) new Item_ref(NullS,NullS,$1.str); + (Item*) new Item_ref(NullS, NullS, $1.str); } - | simple_ident_q { $$= $1; } - ; - -simple_ident_q: - ident '.' ident + | ident '.' ident { THD *thd= YYTHD; LEX *lex= thd->lex; - - /* - FIXME This will work ok in simple_ident_nospvar case because - we can't meet simple_ident_nospvar in trigger now. But it - should be changed in future. - */ - if (lex->sphead && lex->sphead->m_type == TYPE_ENUM_TRIGGER && - (!my_strcasecmp(system_charset_info, $1.str, "NEW") || - !my_strcasecmp(system_charset_info, $1.str, "OLD"))) - { - bool new_row= ($1.str[0]=='N' || $1.str[0]=='n'); - - if (lex->trg_chistics.event == TRG_EVENT_INSERT && - !new_row) - { - net_printf(YYTHD, ER_TRG_NO_SUCH_ROW_IN_TRG, "OLD", - "on INSERT"); - YYABORT; - } - - if (lex->trg_chistics.event == TRG_EVENT_DELETE && - new_row) - { - net_printf(YYTHD, ER_TRG_NO_SUCH_ROW_IN_TRG, "NEW", - "on DELETE"); - YYABORT; - } - - Item_trigger_field *trg_fld= - new Item_trigger_field(new_row ? Item_trigger_field::NEW_ROW : - Item_trigger_field::OLD_ROW, - $3.str); - - if (lex->trg_table && - trg_fld->setup_field(thd, lex->trg_table, - lex->trg_chistics.event)) - { - /* - FIXME. Far from perfect solution. See comment for - "SET NEW.field_name:=..." for more info. - */ - net_printf(YYTHD, ER_BAD_FIELD_ERROR, $3.str, - new_row ? "NEW": "OLD"); - YYABORT; - } - - $$= (Item *)trg_fld; - } - else - { - SELECT_LEX *sel= lex->current_select; - if (sel->no_table_names_allowed) - { - my_printf_error(ER_TABLENAME_NOT_ALLOWED_HERE, - ER(ER_TABLENAME_NOT_ALLOWED_HERE), - MYF(0), $1.str, thd->where); - } - $$= (sel->parsing_place != IN_HAVING || - sel->get_in_sum_expr() > 0) ? - (Item*) new Item_field(NullS,$1.str,$3.str) : - (Item*) new Item_ref(NullS,$1.str,$3.str); - } - } + SELECT_LEX *sel= lex->current_select; + if (sel->no_table_names_allowed) + { + my_printf_error(ER_TABLENAME_NOT_ALLOWED_HERE, + ER(ER_TABLENAME_NOT_ALLOWED_HERE), + MYF(0), $1.str, thd->where); + } + $$= (sel->parsing_place != IN_HAVING || + sel->get_in_sum_expr() > 0) ? + (Item*) new Item_field(NullS,$1.str,$3.str) : + (Item*) new Item_ref(NullS, $1.str, $3.str); + } | '.' ident '.' ident { THD *thd= YYTHD; @@ -6817,7 +5109,6 @@ keyword: | AFTER_SYM {} | AGAINST {} | AGGREGATE_SYM {} - | ALGORITHM_SYM {} | ANY_SYM {} | ASCII_SYM {} | AUTO_INC {} @@ -6833,7 +5124,6 @@ keyword: | BYTE_SYM {} | BTREE_SYM {} | CACHE_SYM {} - | CASCADED {} | CHANGED {} | CHARSET {} | CHECKSUM_SYM {} @@ -6846,14 +5136,13 @@ keyword: | COMMIT_SYM {} | COMPRESSED_SYM {} | CONCURRENT {} - | CONTAINS_SYM {} + | CONSISTENT_SYM {} | CUBE_SYM {} | DATA_SYM {} | DATETIME {} | DATE_SYM {} | DAY_SYM {} | DEALLOCATE_SYM {} - | DEFINER_SYM {} | DELAY_KEY_WRITE_SYM {} | DES_KEY_FILE {} | DIRECTORY_SYM {} @@ -6873,7 +5162,6 @@ keyword: | EXPANSION_SYM {} | EXTENDED_SYM {} | FAST_SYM {} - | FOUND_SYM {} | DISABLE_SYM {} | ENABLE_SYM {} | FULL {} @@ -6881,7 +5169,6 @@ keyword: | FIRST_SYM {} | FIXED_SYM {} | FLUSH_SYM {} - | FRAC_SECOND_SYM {} | GEOMETRY_SYM {} | GEOMETRYCOLLECTION {} | GET_FORMAT {} @@ -6893,7 +5180,6 @@ keyword: | HOSTS_SYM {} | HOUR_SYM {} | IDENTIFIED_SYM {} - | INVOKER_SYM {} | IMPORT {} | INDEXES {} | ISOLATION {} @@ -6901,8 +5187,6 @@ keyword: | INNOBASE_SYM {} | INSERT_METHOD {} | RELAY_THREAD {} - | LABEL_SYM {} - | LANGUAGE_SYM {} | LAST_SYM {} | LEAVES {} | LEVEL_SYM {} @@ -6930,7 +5214,6 @@ keyword: | MAX_QUERIES_PER_HOUR {} | MAX_UPDATES_PER_HOUR {} | MEDIUM_SYM {} - | MERGE_SYM {} | MICROSECOND_SYM {} | MINUTE_SYM {} | MIN_ROWS {} @@ -6940,7 +5223,6 @@ keyword: | MULTILINESTRING {} | MULTIPOINT {} | MULTIPOLYGON {} - | NAME_SYM {} | NAMES_SYM {} | NATIONAL_SYM {} | NCHAR_SYM {} @@ -6963,7 +5245,6 @@ keyword: | PREV_SYM {} | PROCESS {} | PROCESSLIST_SYM {} - | QUARTER_SYM {} | QUERY_SYM {} | QUICK {} | RAID_0_SYM {} @@ -6980,7 +5261,6 @@ keyword: | RESET_SYM {} | RESOURCES {} | RESTORE_SYM {} - | RETURNS_SYM {} | ROLLBACK_SYM {} | ROLLUP_SYM {} | ROWS_SYM {} @@ -6989,7 +5269,6 @@ keyword: | RTREE_SYM {} | SAVEPOINT_SYM {} | SECOND_SYM {} - | SECURITY_SYM {} | SERIAL_SYM {} | SERIALIZABLE_SYM {} | SESSION_SYM {} @@ -6998,6 +5277,7 @@ keyword: | SHARE_SYM {} | SHUTDOWN {} | SLAVE {} + | SNAPSHOT_SYM {} | SOUNDS_SYM {} | SQL_CACHE_SYM {} | SQL_BUFFER_RESULT {} @@ -7013,29 +5293,23 @@ keyword: | SUPER_SYM {} | TABLESPACE {} | TEMPORARY {} - | TEMPTABLE_SYM {} | TEXT_SYM {} | TRANSACTION_SYM {} | TRUNCATE_SYM {} | TIMESTAMP {} - | TIMESTAMP_ADD {} - | TIMESTAMP_DIFF {} | TIME_SYM {} | TYPE_SYM {} | TYPES_SYM {} | UDF_RETURNS_SYM {} - | FUNCTION_SYM {} + | UDF_SYM {} | UNCOMMITTED_SYM {} - | UNDEFINED_SYM {} | UNICODE_SYM {} | UNTIL_SYM {} | USER {} | USE_FRM {} | VARIABLES {} - | VIEW_SYM {} | VALUE_SYM {} | WARNINGS {} - | WEEK_SYM {} | WORK_SYM {} | X509_SYM {} | YEAR_SYM {} @@ -7087,107 +5361,15 @@ opt_var_ident_type: ; option_value: - '@' ident_or_text equal expr - { - LEX *lex= Lex; - - if (lex->sphead && lex->sphead->m_type != TYPE_ENUM_PROCEDURE) - { - /* - We have to use special instruction in functions and triggers - because sp_instr_stmt will close all tables and thus ruin - execution of statement invoking function or trigger. - - We also do not want to allow expression with subselects in - this case. - */ - if (lex->query_tables) - { - send_error(YYTHD, ER_SP_SUBSELECT_NYI); - YYABORT; - } - sp_instr_set_user_var *i= - new sp_instr_set_user_var(lex->sphead->instructions(), - lex->spcont, $2, $4); - lex->sphead->add_instr(i); - } - else - lex->var_list.push_back(new set_var_user(new Item_func_set_user_var($2,$4))); - - } + '@' ident_or_text equal expr + { + Lex->var_list.push_back(new set_var_user(new Item_func_set_user_var($2,$4))); + } | internal_variable_name equal set_expr_or_default { LEX *lex=Lex; - - if ($1.var == &trg_new_row_fake_var) - { - /* We are in trigger and assigning value to field of new row */ - Item *it; - sp_instr_set_trigger_field *i; - if (lex->query_tables) - { - send_error(YYTHD, ER_SP_SUBSELECT_NYI); - YYABORT; - } - if ($3) - it= $3; - else - { - /* QQ: Shouldn't this be field's default value ? */ - it= new Item_null(); - } - i= new sp_instr_set_trigger_field(lex->sphead->instructions(), - lex->spcont, $1.base_name, it); - if (lex->trg_table && i->setup_field(YYTHD, lex->trg_table, - lex->trg_chistics.event)) - { - /* - FIXME. Now we are catching this kind of errors only - during opening tables. But this doesn't save us from most - common user error - misspelling field name, because we - will bark too late in this case... Moreover it is easy to - make table unusable with such kind of error... - - So in future we either have to parse trigger definition - second time during create trigger or gather all trigger - fields in one list and perform setup_field() for them as - separate stage. - - Error message also should be improved. - */ - net_printf(YYTHD, ER_BAD_FIELD_ERROR, $1.base_name, "NEW"); - YYABORT; - } - lex->sphead->add_instr(i); - } - else if ($1.var) - { /* System variable */ - lex->var_list.push_back(new set_var(lex->option_type, $1.var, - &$1.base_name, $3)); - } - else - { - /* An SP local variable */ - sp_pcontext *ctx= lex->spcont; - sp_pvar_t *spv; - sp_instr_set *i; - Item *it; - - spv= ctx->find_pvar(&$1.base_name); - - if ($3) - it= $3; - else if (spv->dflt) - it= spv->dflt; - else - it= new Item_null(); - i= new sp_instr_set(lex->sphead->instructions(), ctx, - spv->offset, it, spv->type); - i->tables= lex->query_tables; - lex->query_tables= 0; - lex->sphead->add_instr(i); - spv->isset= TRUE; - } + lex->var_list.push_back(new set_var(lex->option_type, $1.var, + &$1.base_name, $3)); } | '@' '@' opt_var_ident_type internal_variable_name equal set_expr_or_default { @@ -7245,76 +5427,33 @@ option_value: internal_variable_name: ident { - LEX *lex= Lex; - sp_pcontext *spc= lex->spcont; - sp_pvar_t *spv; - - /* We have to lookup here since local vars can shadow sysvars */ - if (!spc || !(spv = spc->find_pvar(&$1))) - { - /* Not an SP local variable */ - sys_var *tmp=find_sys_var($1.str, $1.length); - if (!tmp) - YYABORT; - $$.var= tmp; - $$.base_name.str=0; - $$.base_name.length=0; - /* - If this is time_zone variable we should open time zone - describing tables - */ - if (tmp == &sys_time_zone) - Lex->time_zone_tables_used= &fake_time_zone_tables_list; - } - else - { - /* An SP local variable */ - $$.var= NULL; - $$.base_name= $1; - } + sys_var *tmp=find_sys_var($1.str, $1.length); + if (!tmp) + YYABORT; + $$.var= tmp; + $$.base_name.str=0; + $$.base_name.length=0; + /* + If this is time_zone variable we should open time zone + describing tables + */ + if (tmp == &sys_time_zone) + Lex->time_zone_tables_used= &fake_time_zone_tables_list; } | ident '.' ident { - LEX *lex= Lex; if (check_reserved_words(&$1)) { yyerror(ER(ER_SYNTAX_ERROR)); YYABORT; } - if (lex->sphead && lex->sphead->m_type == TYPE_ENUM_TRIGGER && - (!my_strcasecmp(system_charset_info, $1.str, "NEW") || - !my_strcasecmp(system_charset_info, $1.str, "OLD"))) - { - if ($1.str[0]=='O' || $1.str[0]=='o') - { - net_printf(YYTHD, ER_TRG_CANT_CHANGE_ROW, "OLD", ""); - YYABORT; - } - if (lex->trg_chistics.event == TRG_EVENT_DELETE) - { - net_printf(YYTHD, ER_TRG_NO_SUCH_ROW_IN_TRG, "NEW", - "on DELETE"); - YYABORT; - } - if (lex->trg_chistics.action_time == TRG_ACTION_AFTER) - { - net_printf(YYTHD, ER_TRG_CANT_CHANGE_ROW, "NEW", "after "); - YYABORT; - } - /* This special combination will denote field of NEW row */ - $$.var= &trg_new_row_fake_var; - $$.base_name= $3; - } - else - { - sys_var *tmp=find_sys_var($3.str, $3.length); - if (!tmp) - YYABORT; - if (!tmp->is_struct()) - net_printf(YYTHD, ER_VARIABLE_IS_NOT_STRUCT, $3.str); - $$.var= tmp; - $$.base_name= $1; - } + sys_var *tmp=find_sys_var($3.str, $3.length); + if (!tmp) + YYABORT; + if (!tmp->is_struct()) + net_printf(YYTHD, ER_VARIABLE_IS_NOT_STRUCT, $3.str); + $$.var= tmp; + $$.base_name= $1; } | DEFAULT '.' ident { @@ -7489,7 +5628,7 @@ revoke_command: grant_privileges ON opt_table FROM user_list {} | - ALL PRIVILEGES ',' GRANT OPTION FROM user_list + ALL opt_privileges ',' GRANT OPTION FROM user_list { Lex->sql_command = SQLCOM_REVOKE_ALL; } @@ -7515,10 +5654,14 @@ grant: grant_privileges: grant_privilege_list {} - | ALL PRIVILEGES { Lex->grant = GLOBAL_ACLS;} - | ALL { Lex->grant = GLOBAL_ACLS;} + | ALL opt_privileges { Lex->grant = GLOBAL_ACLS;} ; +opt_privileges: + /* empty */ + | PRIVILEGES + ; + grant_privilege_list: grant_privilege | grant_privilege_list ',' grant_privilege; @@ -7544,10 +5687,8 @@ grant_privilege: | SUPER_SYM { Lex->grant |= SUPER_ACL;} | CREATE TEMPORARY TABLES { Lex->grant |= CREATE_TMP_ACL;} | LOCK_SYM TABLES { Lex->grant |= LOCK_TABLES_ACL; } - | REPLICATION SLAVE { Lex->grant |= REPL_SLAVE_ACL; } - | REPLICATION CLIENT_SYM { Lex->grant |= REPL_CLIENT_ACL; } - | CREATE VIEW_SYM { Lex->grant |= CREATE_VIEW_ACL; } - | SHOW VIEW_SYM { Lex->grant |= SHOW_VIEW_ACL; } + | REPLICATION SLAVE { Lex->grant |= REPL_SLAVE_ACL;} + | REPLICATION CLIENT_SYM { Lex->grant |= REPL_CLIENT_ACL;} ; @@ -7767,7 +5908,7 @@ grant_option: ; begin: - BEGIN_SYM { Lex->sql_command = SQLCOM_BEGIN;} opt_work {} + BEGIN_SYM { Lex->sql_command = SQLCOM_BEGIN; Lex->start_transaction_opt= 0;} opt_work {} ; opt_work: @@ -7936,47 +6077,3 @@ subselect_end: lex->current_select = lex->current_select->return_after_parsing(); }; -opt_view_list: - /* empty */ {} - | '(' view_list ')' - ; - -view_list: - ident - { - Lex->view_list.push_back((LEX_STRING*) - sql_memdup(&$1, sizeof(LEX_STRING))); - } - | view_list ',' ident - { - Lex->view_list.push_back((LEX_STRING*) - sql_memdup(&$3, sizeof(LEX_STRING))); - } - ; - -or_replace: - /* empty */ { Lex->create_view_mode= VIEW_CREATE_NEW; } - | OR_SYM REPLACE { Lex->create_view_mode= VIEW_CREATE_OR_REPLACE; } - ; - -algorithm: - /* empty */ - { Lex->create_view_algorithm= VIEW_ALGORITHM_UNDEFINED; } - | ALGORITHM_SYM EQ UNDEFINED_SYM - { Lex->create_view_algorithm= VIEW_ALGORITHM_UNDEFINED; } - | ALGORITHM_SYM EQ MERGE_SYM - { Lex->create_view_algorithm= VIEW_ALGORITHM_MERGE; } - | ALGORITHM_SYM EQ TEMPTABLE_SYM - { Lex->create_view_algorithm= VIEW_ALGORITHM_TMPTABLE; } - ; -check_option: - /* empty */ - { Lex->create_view_check= VIEW_CHECK_NONE; } - | WITH CHECK_SYM OPTION - { Lex->create_view_check= VIEW_CHECK_CASCADED; } - | WITH CASCADED CHECK_SYM OPTION - { Lex->create_view_check= VIEW_CHECK_CASCADED; } - | WITH LOCAL_SYM CHECK_SYM OPTION - { Lex->create_view_check= VIEW_CHECK_LOCAL; } - ; - |