diff options
author | unknown <monty@hundin.mysql.fi> | 2002-01-02 21:29:41 +0200 |
---|---|---|
committer | unknown <monty@hundin.mysql.fi> | 2002-01-02 21:29:41 +0200 |
commit | f4fee3d90e8456cfd2a4e2f395bd270d0a12c70d (patch) | |
tree | ef8afaf7a0fed42b30ef0d9d38acccc992b5f87d /sql | |
parent | 27f652efefba29bf58f45cbfe21a4228ec6fdb34 (diff) | |
download | mariadb-git-f4fee3d90e8456cfd2a4e2f395bd270d0a12c70d.tar.gz |
Added macros for nice TIMESPEC usage.
Fixes for building MySQL with gcc 3.0
Added SIGNED / UNSIGNED casts
Fixed core dump bug in net_clear() with libmysqld.
Back to using semaphores in query cache.
Added 'Null' and 'Index_type' to SHOW INDEX.
BUILD/FINISH.sh:
Fixes for gcc 3.0
BUILD/SETUP.sh:
Fixes for gcc 3.0
Docs/manual.texi:
Changelog + SIGNED/UNSIGNED casts.
Makefile.am:
include BUILD scripts in source distribution.
client/Makefile.am:
Fixes for gcc 3.0
client/mysql.cc:
Cleanup
client/mysqldump.c:
Changed 'K' to mean 'disable-keys' instead of 'no-disabled-keys'
client/readline.cc:
Cleanup
configure.in:
Include BUILD in source distrbution
extra/my_print_defaults.c:
Cleanup
include/my_global.h:
Fix for HPUX and setrlimit.
Portability fix.
Added macros for nice TIMESPEC usage.
innobase/include/dyn0dyn.h:
Fix for AIX
libmysql/Makefile.shared:
Added strxmov to libmysqld
libmysqld/examples/Makefile.am:
Fixes for gcc 3.0
libmysqld/lib_vio.c:
Cleanup
myisam/ft_dump.c:
Portability fixes
myisam/ftdefs.h:
Portability fixes
mysql-test/r/bdb.result:
Cleanup results after adding 2 columns to SHOW KEYS
mysql-test/r/bigint.result:
New test for SIGNED/UNSIGNED
mysql-test/r/fulltext.result:
Cleanup results after adding 2 columns to SHOW KEYS
mysql-test/r/heap.result:
Cleanup results after adding 2 columns to SHOW KEYS
mysql-test/r/innodb.result:
Cleanup results after adding 2 columns to SHOW KEYS
mysql-test/r/isam.result:
Cleanup results after adding 2 columns to SHOW KEYS
mysql-test/r/key.result:
Cleanup results after adding 2 columns to SHOW KEYS
mysql-test/r/myisam.result:
Cleanup results after adding 2 columns to SHOW KEYS
mysql-test/r/query_cache.result:
Cleanup results after adding 2 columns to SHOW KEYS
mysql-test/r/select.result:
Cleanup results after adding 2 columns to SHOW KEYS
mysql-test/r/show_check.result:
Cleanup results after adding 2 columns to SHOW KEYS
mysql-test/r/type_ranges.result:
Cleanup results after adding 2 columns to SHOW KEYS
mysql-test/t/bigint.test:
New test for SIGNED/UNSIGNED
mysql-test/t/key.test:
New test for SIGNED/UNSIGNED
mysql-test/t/query_cache.test:
Test for FOUND_ROWS()
sql-bench/crash-me.sh:
Safety fixes
sql/derror.cc:
Cleanup
sql/ha_berkeley.h:
New test for SIGNED/UNSIGNED
sql/ha_heap.h:
New test for SIGNED/UNSIGNED
sql/ha_innobase.cc:
New test for SIGNED/UNSIGNED
sql/ha_innobase.h:
New test for SIGNED/UNSIGNED
sql/ha_isam.h:
New test for SIGNED/UNSIGNED
sql/ha_myisam.cc:
New test for SIGNED/UNSIGNED
sql/ha_myisam.h:
New test for SIGNED/UNSIGNED
sql/handler.h:
New test for SIGNED/UNSIGNED
sql/item_func.cc:
Cleanup TIMESPEC usage
sql/item_func.h:
Added SIGNED / UNSIGNED casts
sql/lex.h:
Added SIGNED / UNSIGNED casts
sql/mysqld.cc:
Cleanup TIMESPEC usage
sql/net_pkg.cc:
Cleanup
sql/net_serv.cc:
Fixed core dump bug in net_clear()
sql/slave.cc:
Cleanup
sql/sql_cache.cc:
Back to using semaphores
sql/sql_cache.h:
Back to using semaphores
sql/sql_insert.cc:
Cleanup TIMESPEC usage
sql/sql_manager.cc:
Cleanup TIMESPEC usage
sql/sql_parse.cc:
Cleanup
sql/sql_repl.cc:
Cleanup TIMESPEC usage
sql/sql_show.cc:
Added 'Null' and 'Index_type' to SHOW INDEX.
sql/sql_table.cc:
Sort keys in table in a more logical order.
sql/sql_yacc.yy:
Support for SIGNED/UNSIGNED casts.
Diffstat (limited to 'sql')
-rw-r--r-- | sql/derror.cc | 34 | ||||
-rw-r--r-- | sql/ha_berkeley.h | 1 | ||||
-rw-r--r-- | sql/ha_heap.h | 1 | ||||
-rw-r--r-- | sql/ha_innobase.cc | 21 | ||||
-rw-r--r-- | sql/ha_innobase.h | 1 | ||||
-rw-r--r-- | sql/ha_isam.h | 1 | ||||
-rw-r--r-- | sql/ha_myisam.cc | 14 | ||||
-rw-r--r-- | sql/ha_myisam.h | 3 | ||||
-rw-r--r-- | sql/handler.h | 1 | ||||
-rw-r--r-- | sql/item_func.cc | 18 | ||||
-rw-r--r-- | sql/item_func.h | 21 | ||||
-rw-r--r-- | sql/lex.h | 1 | ||||
-rw-r--r-- | sql/mysqld.cc | 10 | ||||
-rw-r--r-- | sql/net_pkg.cc | 2 | ||||
-rw-r--r-- | sql/net_serv.cc | 2 | ||||
-rw-r--r-- | sql/slave.cc | 62 | ||||
-rw-r--r-- | sql/sql_cache.cc | 60 | ||||
-rw-r--r-- | sql/sql_cache.h | 7 | ||||
-rw-r--r-- | sql/sql_insert.cc | 16 | ||||
-rw-r--r-- | sql/sql_manager.cc | 8 | ||||
-rw-r--r-- | sql/sql_parse.cc | 4 | ||||
-rw-r--r-- | sql/sql_repl.cc | 25 | ||||
-rw-r--r-- | sql/sql_show.cc | 14 | ||||
-rw-r--r-- | sql/sql_table.cc | 105 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 8 |
25 files changed, 242 insertions, 198 deletions
diff --git a/sql/derror.cc b/sql/derror.cc index d0519c37dca..7ebe6e4b3c5 100644 --- a/sql/derror.cc +++ b/sql/derror.cc @@ -44,7 +44,7 @@ static void read_texts(const char *file_name,const char ***point, uint error_messages) { register uint i; - uint ant,funktpos,length,textant; + uint count,funktpos,length,textcount; File file; char name[FN_REFLEN]; const char *buff; @@ -64,36 +64,38 @@ static void read_texts(const char *file_name,const char ***point, if (head[0] != (uchar) 254 || head[1] != (uchar) 254 || head[2] != 2 || head[3] != 1) goto err; /* purecov: inspected */ - textant=head[4]; - length=uint2korr(head+6); ant=uint2korr(head+8); + textcount=head[4]; + length=uint2korr(head+6); count=uint2korr(head+8); - if (ant < error_messages) + if (count < error_messages) { - fprintf(stderr,"\n%s: Fatal error: Error message file '%s' had only %d error messages, but it should have at least %d error messages.\n\ -Check that the above file is the right version for this program!\n\n", - my_progname,name,ant,error_messages); + sql_print_error("\ +Error message file '%s' had only %d error messages,\n\ +but it should contain at least %d error messages.\n\ +Check that the above file is the right version for this program!", + name,count,error_messages); VOID(my_close(file,MYF(MY_WME))); unireg_abort(1); } x_free((gptr) *point); /* Free old language */ if (!(*point= (const char**) - my_malloc((uint) (length+ant*sizeof(char*)),MYF(0)))) + my_malloc((uint) (length+count*sizeof(char*)),MYF(0)))) { funktpos=2; /* purecov: inspected */ goto err; /* purecov: inspected */ } - buff= (char*) (*point + ant); + buff= (char*) (*point + count); - if (my_read(file,(byte*) buff,(uint) ant*2,MYF(MY_NABP))) goto err; - for (i=0, pos= (uchar*) buff ; i< ant ; i++) + if (my_read(file,(byte*) buff,(uint) count*2,MYF(MY_NABP))) goto err; + for (i=0, pos= (uchar*) buff ; i< count ; i++) { (*point)[i]=buff+uint2korr(pos); pos+=2; } if (my_read(file,(byte*) buff,(uint) length,MYF(MY_NABP))) goto err; - for (i=1 ; i < textant ; i++) + for (i=1 ; i < textcount ; i++) { point[i]= *point +uint2korr(head+10+i+i); } @@ -103,18 +105,18 @@ Check that the above file is the right version for this program!\n\n", err: switch (funktpos) { case 2: - buff="\n%s: Fatal error: Not enough memory for messagefile '%s'\n\n"; + buff="Not enough memory for messagefile '%s'"; break; case 1: - buff="\n%s: Fatal error: Can't read from messagefile '%s'\n\n"; + buff="Can't read from messagefile '%s'"; break; default: - buff="\n%s: Fatal error: Can't find messagefile '%s'\n\n"; + buff="Can't find messagefile '%s'"; break; } if (file != FERR) VOID(my_close(file,MYF(MY_WME))); - fprintf(stderr,buff,my_progname,name); + sql_print_error(buff,name); unireg_abort(1); } /* read_texts */ diff --git a/sql/ha_berkeley.h b/sql/ha_berkeley.h index 65116f908ac..fbc858b5996 100644 --- a/sql/ha_berkeley.h +++ b/sql/ha_berkeley.h @@ -98,6 +98,7 @@ class ha_berkeley: public handler } ~ha_berkeley() {} const char *table_type() const { return "BerkeleyDB"; } + const char *index_type(uint key_number) { return "BTREE"; } const char **bas_ext() const; ulong option_flag() const { return int_option_flag; } uint max_record_length() const { return HA_MAX_REC_LENGTH; } diff --git a/sql/ha_heap.h b/sql/ha_heap.h index 9b041411012..fa077cef60a 100644 --- a/sql/ha_heap.h +++ b/sql/ha_heap.h @@ -31,6 +31,7 @@ class ha_heap: public handler ha_heap(TABLE *table): handler(table), file(0) {} ~ha_heap() {} const char *table_type() const { return "HEAP"; } + const char *index_type(uint key_number) { return "HASH"; } const char **bas_ext() const; ulong option_flag() const { return (HA_READ_RND_SAME | HA_NO_INDEX | HA_ONLY_WHOLE_INDEX | diff --git a/sql/ha_innobase.cc b/sql/ha_innobase.cc index 836a1a4331e..3b6b15d1e79 100644 --- a/sql/ha_innobase.cc +++ b/sql/ha_innobase.cc @@ -580,7 +580,7 @@ innobase_init(void) ret = innobase_parse_data_file_paths_and_sizes(); if (ret == FALSE) { - fprintf(stderr, "InnoDB: syntax error in innodb_data_file_path\n"); + sql_print_error("InnoDB: syntax error in innodb_data_file_path"); DBUG_RETURN(TRUE); } @@ -928,13 +928,13 @@ ha_innobase::open( if (NULL == (ib_table = dict_table_get(norm_name, NULL))) { - fprintf(stderr, -"InnoDB: Error: cannot find table %s from the internal data dictionary\n" -"InnoDB: of InnoDB though the .frm file for the table exists. Maybe you\n" -"InnoDB: have deleted and recreated InnoDB data files but have forgotten\n" -"InnoDB: to delete the corresponding .frm files of InnoDB tables, or you\n" -"InnoDB: have moved .frm files to another database?\n", - norm_name); + sql_print_error("InnoDB error:\n\ +Cannot find table %s from the internal data dictionary\n\ +of InnoDB though the .frm file for the table exists. Maybe you\n\ +have deleted and recreated InnoDB data files but have forgotten\n\ +to delete the corresponding .frm files of InnoDB tables, or you\n\ +have moved .frm files to another database?", + norm_name); free_share(share); my_free((char*) upd_buff, MYF(0)); @@ -2034,10 +2034,7 @@ ha_innobase::change_active_index( prebuilt->index=dict_table_get_index_noninline(prebuilt->table, key->name); if (!prebuilt->index) { - fprintf(stderr, - "InnoDB: Could not find key n:o %u with name %s from dict cache\n" - "InnoDB: for table %s\n", keynr, key->name, - prebuilt->table->name); + sql_print_error("Innodb could not find key n:o %u with name %s from dict cache for table %s", keynr, key->name, prebuilt->table->name); return(1); } } diff --git a/sql/ha_innobase.h b/sql/ha_innobase.h index b1613c2503c..bcd11b8a96e 100644 --- a/sql/ha_innobase.h +++ b/sql/ha_innobase.h @@ -91,6 +91,7 @@ class ha_innobase: public handler ~ha_innobase() {} const char* table_type() const { return("InnoDB");} + const char *index_type(uint key_number) { return "BTREE"; } const char** bas_ext() const; ulong option_flag() const { return int_option_flag; } uint max_record_length() const { return HA_MAX_REC_LENGTH; } diff --git a/sql/ha_isam.h b/sql/ha_isam.h index 33ca99b5063..e878f0fe697 100644 --- a/sql/ha_isam.h +++ b/sql/ha_isam.h @@ -38,6 +38,7 @@ class ha_isam: public handler {} ~ha_isam() {} const char *table_type() const { return "ISAM"; } + const char *index_type(uint key_number) { return "BTREE"; } const char **bas_ext() const; ulong option_flag() const { return int_option_flag; } uint max_record_length() const { return HA_MAX_REC_LENGTH; } diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc index 0378ff7ba6f..77d541bfdfb 100644 --- a/sql/ha_myisam.cc +++ b/sql/ha_myisam.cc @@ -80,9 +80,8 @@ static void mi_check_print_msg(MI_CHECK *param, const char* msg_type, net_store_data(packet, msgbuf); if (my_net_write(&thd->net, (char*)thd->packet.ptr(), thd->packet.length())) - fprintf(stderr, - "Failed on my_net_write, writing to stderr instead: %s\n", - msgbuf); + sql_print_error("Failed on my_net_write, writing to stderr instead: %s\n", + msgbuf); return; } @@ -122,6 +121,13 @@ const char **ha_myisam::bas_ext() const { static const char *ext[]= { ".MYD",".MYI", NullS }; return ext; } +const char *ha_myisam::index_type(uint key_number) +{ + return ((table->key_info[key_number].flags & HA_FULLTEXT) ? + "FULLTEXT" : + "BTREE"); +} + int ha_myisam::net_read_dump(NET* net) { int data_fd = file->dfile; @@ -1170,7 +1176,7 @@ longlong ha_myisam::get_auto_increment() longlong nr; int error; - byte key[MAX_KEY_LENGTH]; + byte key[MI_MAX_KEY_LENGTH]; (void) extra(HA_EXTRA_KEYREAD); key_copy(key,table,table->next_number_index, table->next_number_key_offset); diff --git a/sql/ha_myisam.h b/sql/ha_myisam.h index 7b5c959ccfa..e2044dfe1e2 100644 --- a/sql/ha_myisam.h +++ b/sql/ha_myisam.h @@ -54,12 +54,13 @@ class ha_myisam: public handler {} ~ha_myisam() {} const char *table_type() const { return "MyISAM"; } + const char *index_type(uint key_number); const char **bas_ext() const; ulong option_flag() const { return int_option_flag; } uint max_record_length() const { return HA_MAX_REC_LENGTH; } uint max_keys() const { return MI_MAX_KEY; } uint max_key_parts() const { return MAX_REF_PARTS; } - uint max_key_length() const { return MAX_KEY_LENGTH; } + uint max_key_length() const { return MI_MAX_KEY_LENGTH; } int open(const char *name, int mode, uint test_if_locked); int close(void); diff --git a/sql/handler.h b/sql/handler.h index 1e2c0074475..33cfa965363 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -236,6 +236,7 @@ public: virtual bool has_transactions(){ return 0;} virtual uint extra_rec_buf_length() { return 0; } virtual ha_rows estimate_number_of_rows() { return records+EXTRA_RECORDS; } + virtual const char *index_type(uint key_number) { return "";} virtual int index_init(uint idx) { active_index=idx; return 0;} virtual int index_end() {return 0; } diff --git a/sql/item_func.cc b/sql/item_func.cc index 4caa959bce8..93edcc64146 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -1496,14 +1496,7 @@ void debug_sync_point(const char* lock_name, uint lock_timeout) thd->mysys_var->current_mutex= &LOCK_user_locks; thd->mysys_var->current_cond= &ull->cond; -#ifdef HAVE_TIMESPEC_TS_SEC - abstime.ts_sec=time((time_t*) 0)+(time_t) lock_timeout; - abstime.ts_nsec=0; -#else - abstime.tv_sec=time((time_t*) 0)+(time_t) lock_timeout; - abstime.tv_nsec=0; -#endif - + set_timespec(abstime,lock_timeout); while (!thd->killed && (error=pthread_cond_timedwait(&ull->cond,&LOCK_user_locks,&abstime)) != ETIME && error != ETIMEDOUT && ull->locked) ; @@ -1591,14 +1584,7 @@ longlong Item_func_get_lock::val_int() thd->mysys_var->current_mutex= &LOCK_user_locks; thd->mysys_var->current_cond= &ull->cond; -#ifdef HAVE_TIMESPEC_TS_SEC - abstime.ts_sec=time((time_t*) 0)+(time_t) timeout; - abstime.ts_nsec=0; -#else - abstime.tv_sec=time((time_t*) 0)+(time_t) timeout; - abstime.tv_nsec=0; -#endif - + set_timespec(abstime,timeout); while (!thd->killed && (error=pthread_cond_timedwait(&ull->cond,&LOCK_user_locks,&abstime)) != ETIME && error != ETIMEDOUT && ull->locked) ; diff --git a/sql/item_func.h b/sql/item_func.h index 23cdf7082cf..648ca6d0743 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -181,6 +181,27 @@ public: void fix_length_and_dec() { decimals=0; max_length=21; } }; +class Item_func_signed :public Item_int_func +{ +public: + Item_func_signed(Item *a) :Item_int_func(a) {} + double val() { return args[0]->val(); } + longlong val_int() { return args[0]->val_int(); } + void fix_length_and_dec() + { decimals=0; max_length=args[0]->max_length; unsigned_flag=0; } +}; + +class Item_func_unsigned :public Item_int_func +{ +public: + Item_func_unsigned(Item *a) :Item_int_func(a) {} + double val() { return args[0]->val(); } + longlong val_int() { return args[0]->val_int(); } + void fix_length_and_dec() + { decimals=0; max_length=args[0]->max_length; unsigned_flag=1; } +}; + + class Item_func_plus :public Item_num_op { public: diff --git a/sql/lex.h b/sql/lex.h index 59c71f20cd7..baabe2d16f0 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -301,6 +301,7 @@ static SYMBOL symbols[] = { { "SERIALIZABLE", SYM(SERIALIZABLE_SYM),0,0}, { "SESSION", SYM(SESSION_SYM),0,0}, { "SET", SYM(SET),0,0}, + { "SIGNED", SYM(SIGNED),0,0}, { "SHARE", SYM(SHARE_SYM),0,0}, { "SHOW", SYM(SHOW),0,0}, { "SHUTDOWN", SYM(SHUTDOWN),0,0}, diff --git a/sql/mysqld.cc b/sql/mysqld.cc index e4e24c5ce53..a6eb447f1a1 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -447,15 +447,7 @@ static void close_connections(void) if (pthread_kill(select_thread,THR_CLIENT_ALARM)) break; // allready dead #endif -#ifdef HAVE_TIMESPEC_TS_SEC - abstime.ts_sec=time(NULL)+2; // Bsd 2.1 - abstime.ts_nsec=0; -#else - struct timeval tv; - gettimeofday(&tv,0); - abstime.tv_sec=tv.tv_sec+2; - abstime.tv_nsec=tv.tv_usec*1000; -#endif + set_timespec(abstime, 2); for (uint tmp=0 ; tmp < 10 ; tmp++) { error=pthread_cond_timedwait(&COND_thread_count,&LOCK_thread_count, diff --git a/sql/net_pkg.cc b/sql/net_pkg.cc index 2f26ad81bd5..64c1b07a493 100644 --- a/sql/net_pkg.cc +++ b/sql/net_pkg.cc @@ -52,6 +52,7 @@ void send_error(NET *net, uint sql_errno, const char *err) { if (thd && thd->bootstrap) { + /* In bootstrap it's ok to print on stderr */ fprintf(stderr,"ERROR: %d %s\n",sql_errno,err); } DBUG_VOID_RETURN; @@ -120,6 +121,7 @@ net_printf(NET *net, uint errcode, ...) { if (thd && thd->bootstrap) { + /* In bootstrap it's ok to print on stderr */ fprintf(stderr,"ERROR: %d %s\n",errcode,text_pos); thd->fatal_error=1; } diff --git a/sql/net_serv.cc b/sql/net_serv.cc index 3e4dcb75ebb..9a8d6b5e967 100644 --- a/sql/net_serv.cc +++ b/sql/net_serv.cc @@ -167,7 +167,7 @@ static my_bool net_realloc(NET *net, ulong length) void net_clear(NET *net) { -#ifndef EXTRA_DEBUG +#if !defined(EXTRA_DEBUG) && !defined(EMBEDDED_LIBRARY) int count; /* One may get 'unused' warn */ bool is_blocking=vio_is_blocking(net->vio); if (is_blocking) diff --git a/sql/slave.cc b/sql/slave.cc index 33c4273bcb0..f2c29146308 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -285,11 +285,11 @@ char* rewrite_db(char* db) I_List_iterator<i_string_pair> it(replicate_rewrite_db); i_string_pair* tmp; - while((tmp=it++)) - { - if (!strcmp(tmp->key, db)) - return tmp->val; - } + while ((tmp=it++)) + { + if (!strcmp(tmp->key, db)) + return tmp->val; + } return db; } @@ -310,7 +310,7 @@ int db_ok(const char* db, I_List<i_string> &do_list, I_List_iterator<i_string> it(do_list); i_string* tmp; - while((tmp=it++)) + while ((tmp=it++)) { if (!strcmp(tmp->ptr, db)) return 1; // match @@ -322,7 +322,7 @@ int db_ok(const char* db, I_List<i_string> &do_list, I_List_iterator<i_string> it(ignore_list); i_string* tmp; - while((tmp=it++)) + while ((tmp=it++)) { if (!strcmp(tmp->ptr, db)) return 0; // match @@ -346,7 +346,7 @@ static int init_strvar_from_file(char* var, int max_size, IO_CACHE* f, // if we truncated a line or stopped on last char, remove all chars // up to and including newline int c; - while( ((c=my_b_get(f)) != '\n' && c != my_b_EOF)); + while (((c=my_b_get(f)) != '\n' && c != my_b_EOF)); } return 0; } @@ -803,7 +803,7 @@ int st_master_info::wait_for_pos(THD* thd, String* log_name, ulonglong log_pos) bool pos_reached; int event_count = 0; pthread_mutex_lock(&lock); - while(!thd->killed) + while (!thd->killed) { int cmp_result; if (*log_file_name) @@ -1002,8 +1002,8 @@ server_errno=%d)", if (len == 1) { - sql_print_error("Slave: received 0 length packet from server, apparent\ - master shutdown: %s (%d)", + sql_print_error("Slave: received 0 length packet from server, apparent \ +master shutdown: %s (%d)", mc_mysql_error(mysql), read_errno); return packet_error; } @@ -1015,24 +1015,23 @@ server_errno=%d)", int check_expected_error(THD* thd, int expected_error) { - switch(expected_error) - { - case ER_NET_READ_ERROR: - case ER_NET_ERROR_ON_WRITE: - case ER_SERVER_SHUTDOWN: - case ER_NEW_ABORTING_CONNECTION: - my_snprintf(last_slave_error, sizeof(last_slave_error), - "Slave: query '%s' partially completed on the master \ + switch (expected_error) { + case ER_NET_READ_ERROR: + case ER_NET_ERROR_ON_WRITE: + case ER_SERVER_SHUTDOWN: + case ER_NEW_ABORTING_CONNECTION: + my_snprintf(last_slave_error, sizeof(last_slave_error),"\ +Slave: query '%s' partially completed on the master \ and was aborted. There is a chance that your master is inconsistent at this \ -point. If you are sure that your master is ok, run this query manually on the\ - slave and then restart the slave with SET SQL_SLAVE_SKIP_COUNTER=1;\ - SLAVE START;", thd->query); - last_slave_errno = expected_error; - sql_print_error("%s",last_slave_error); - return 1; - default: - return 0; - } +point. If you are sure that your master is ok, run this query manually on the \ +slave and then restart the slave with SET SQL_SLAVE_SKIP_COUNTER=1;\ +SLAVE START;", thd->query); + last_slave_errno = expected_error; + sql_print_error("%s",last_slave_error); + return 1; + default: + return 0; + } } @@ -1230,8 +1229,7 @@ try again, log '%s' at postion %s", RPL_LOG_NAME, goto connected; } - - while(!slave_killed(thd)) + while (!slave_killed(thd)) { thd->proc_info = "Reading master update"; ulong event_len = read_event(mysql, &glob_mi); @@ -1323,8 +1321,8 @@ the slave thread with \"mysqladmin start-slave\". We stopped at log \ events_till_disconnect++; } #endif - } // while(!slave_killed(thd)) - read/exec loop - } // while(!slave_killed(thd)) - slave loop + } // while (!slave_killed(thd)) - read/exec loop + } // while (!slave_killed(thd)) - slave loop // error = 0; err: diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index 523e835f472..388abd99bd5 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -288,6 +288,11 @@ If join_results allocated new block(s) then we need call pack_cache again. pthread_mutex_lock(M);} #define MUTEX_UNLOCK(M) {DBUG_PRINT("lock", ("mutex unlock 0x%lx",\ (ulong)(M))); pthread_mutex_unlock(M);} +#define SEM_LOCK(M) { int val = 0; sem_getvalue (M, &val); \ + DBUG_PRINT("lock", ("sem lock 0x%lx (%d)", (ulong)(M), val)); \ + sem_wait(M); DBUG_PRINT("lock", ("sem lock ok")); } +#define SEM_UNLOCK(M) {DBUG_PRINT("info", ("sem unlock 0x%lx", (ulong)(M))); \ + sem_post(M); DBUG_PRINT("info", ("sem unlock ok")); } #define STRUCT_LOCK(M) {DBUG_PRINT("lock", ("%d struct lock...",__LINE__)); \ pthread_mutex_lock(M);DBUG_PRINT("lock", ("struct lock OK"));} #define STRUCT_UNLOCK(M) { \ @@ -310,6 +315,8 @@ If join_results allocated new block(s) then we need call pack_cache again. #else #define MUTEX_LOCK(M) pthread_mutex_lock(M) #define MUTEX_UNLOCK(M) pthread_mutex_unlock(M) +#define SEM_LOCK(M) sem_wait(M) +#define SEM_UNLOCK(M) sem_post(M) #define STRUCT_LOCK(M) pthread_mutex_lock(M) #define STRUCT_UNLOCK(M) pthread_mutex_unlock(M) #define BLOCK_LOCK_WR(B) B->query()->lock_writing() @@ -426,7 +433,7 @@ void Query_cache_query::init_n_lock() { DBUG_ENTER("Query_cache_query::init_n_lock"); res=0; wri = 0; len = 0; - pthread_cond_init(&lock, NULL); + sem_init(&lock, 0, 1); pthread_mutex_init(&clients_guard,MY_MUTEX_INIT_FAST); clients = 0; lock_writing(); @@ -446,7 +453,7 @@ void Query_cache_query::unlock_n_destroy() active semaphore */ this->unlock_writing(); - pthread_cond_destroy(&lock); + sem_destroy(&lock); pthread_mutex_destroy(&clients_guard); DBUG_VOID_RETURN; } @@ -462,9 +469,7 @@ void Query_cache_query::unlock_n_destroy() void Query_cache_query::lock_writing() { - MUTEX_LOCK(&clients_guard); - while (clients != 0) - pthread_cond_wait(&lock,&clients_guard); + SEM_LOCK(&lock); } @@ -478,18 +483,12 @@ void Query_cache_query::lock_writing() my_bool Query_cache_query::try_lock_writing() { DBUG_ENTER("Query_cache_block::try_lock_writing"); - if (pthread_mutex_trylock(&clients_guard)) - { - DBUG_PRINT("qcache", ("can't lock mutex")); - DBUG_RETURN(0); - } - if (clients != 0) + if (sem_trywait(&lock)!=0 || clients != 0) { - DBUG_PRINT("info", ("already locked (r)")); - MUTEX_UNLOCK(&clients_guard); + DBUG_PRINT("info", ("can't lock semaphore")); DBUG_RETURN(0); } - DBUG_PRINT("qcache", ("mutex 'lock' 0x%lx locked", (ulong) &lock)); + DBUG_PRINT("info", ("mutex 'lock' 0x%lx locked", (ulong) &lock)); DBUG_RETURN(1); } @@ -497,23 +496,28 @@ my_bool Query_cache_query::try_lock_writing() void Query_cache_query::lock_reading() { MUTEX_LOCK(&clients_guard); - clients++; + if ( ++clients == 1 ) + SEM_LOCK(&lock); MUTEX_UNLOCK(&clients_guard); } void Query_cache_query::unlock_writing() { - MUTEX_UNLOCK(&clients_guard); + SEM_UNLOCK(&lock); } void Query_cache_query::unlock_reading() { + /* + To avoid unlocking semaphore before unlocking mutex (that may cause + destroying locked mutex), we use temporary boolean variable 'unlock'. + */ MUTEX_LOCK(&clients_guard); - if (--clients == 0) - pthread_cond_broadcast(&lock); + bool ulock = ((--clients) == 0); MUTEX_UNLOCK(&clients_guard); + if (ulock) SEM_UNLOCK(&lock); } extern "C" @@ -1377,8 +1381,11 @@ void Query_cache::free_cache(my_bool destruction) /* Becasue we did a flush, all cache memory must be in one this block */ bins[0].free_blocks->destroy(); total_blocks--; - DBUG_PRINT("qcache", ("free memory %lu (should be %lu)", - free_memory , query_cache_size)); +#ifndef DBUG_OFF + if (free_memory != query_cache_size) + DBUG_PRINT("qcache", ("free memory %lu (should be %lu)", + free_memory , query_cache_size)); +#endif my_free((gptr) cache, MYF(MY_ALLOW_ZERO_PTR)); make_disabled(); hash_free(&queries); @@ -2573,7 +2580,7 @@ my_bool Query_cache::move_by_type(byte **border, } while ( result_block != first_result_block ); } Query_cache_query *new_query= ((Query_cache_query *) new_block->data()); - pthread_cond_init(&new_query->lock, NULL); + sem_init(&new_query->lock, 0, 1); pthread_mutex_init(&new_query->clients_guard,MY_MUTEX_INIT_FAST); /* @@ -2948,6 +2955,7 @@ my_bool Query_cache::check_integrity() my_bool result = 0; uint i; STRUCT_LOCK(&structure_guard_mutex); + DBUG_ENTER("check_integrity"); if (hash_check(&queries)) { @@ -3030,6 +3038,8 @@ my_bool Query_cache::check_integrity() result = 1; break; case Query_cache_block::RES_INCOMPLETE: + // This type of block can be not lincked yet (in multithread environment) + break; case Query_cache_block::RES_BEG: case Query_cache_block::RES_CONT: case Query_cache_block::RESULT: @@ -3048,11 +3058,13 @@ my_bool Query_cache::check_integrity() } else { + BLOCK_LOCK_RD(query_block); if (in_list(queries_blocks, query_block, "query from results")) result = 1; if (in_list(query_block->query()->result(), block, "results")) result = 1; + BLOCK_UNLOCK_RD(query_block); } break; } @@ -3160,15 +3172,15 @@ my_bool Query_cache::check_integrity() } while (block != bins[i].free_blocks); if (count != bins[i].number) { - DBUG_PRINT("qcache", ("bin[%d].number is %d, but bin have %d blocks", - bins[i].number, count)); + DBUG_PRINT("error", ("bin[%d].number is %d, but bin have %d blocks", + bins[i].number, count)); result = 1; } } } DBUG_ASSERT(result == 0); STRUCT_UNLOCK(&structure_guard_mutex); - return result; + DBUG_RETURN(result); } diff --git a/sql/sql_cache.h b/sql/sql_cache.h index 50ae765e446..bde11d2dbb6 100644 --- a/sql/sql_cache.h +++ b/sql/sql_cache.h @@ -55,6 +55,8 @@ #define TABLE_COUNTER_TYPE uint8 +#include <my_semaphore.h> + struct Query_cache_block; struct Query_cache_block_table; struct Query_cache_table; @@ -107,7 +109,7 @@ struct Query_cache_query Query_cache_block *res; NET *wri; ulong len; - pthread_cond_t lock; // R/W lock of block + sem_t lock; // R/W lock of block pthread_mutex_t clients_guard; uint clients; @@ -396,5 +398,8 @@ protected: }; extern Query_cache query_cache; +void query_cache_insert(NET *net, const char *packet, ulong length); +void query_cache_end_of_result(NET *net); +void query_cache_abort(NET *net); #endif diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 06a1818b50d..75feca8d759 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -988,23 +988,12 @@ static pthread_handler_decl(handle_delayed_insert,arg) if (!di->status && !di->stacked_inserts) { struct timespec abstime; -#if defined(HAVE_TIMESPEC_TS_SEC) - abstime.ts_sec=time((time_t*) 0)+(time_t) delayed_insert_timeout; - abstime.ts_nsec=0; -#elif defined(__WIN__) - abstime.tv_sec=time((time_t*) 0)+(time_t) delayed_insert_timeout; - abstime.tv_nsec=0; -#else - struct timeval tv; - gettimeofday(&tv,0); - abstime.tv_sec=tv.tv_sec+(time_t) delayed_insert_timeout; - abstime.tv_nsec=tv.tv_usec*1000; -#endif + set_timespec(abstime, delayed_insert_timeout); /* Information for pthread_kill */ di->thd.mysys_var->current_mutex= &di->mutex; di->thd.mysys_var->current_cond= &di->cond; - di->thd.proc_info=0; + di->thd.proc_info="Waiting for INSERT"; DBUG_PRINT("info",("Waiting for someone to insert rows")); while (!thd->killed) @@ -1039,6 +1028,7 @@ static pthread_handler_decl(handle_delayed_insert,arg) pthread_mutex_unlock(&di->thd.mysys_var->mutex); pthread_mutex_lock(&di->mutex); } + di->thd.proc_info=0; if (di->tables_in_use && ! thd->lock) { diff --git a/sql/sql_manager.cc b/sql/sql_manager.cc index 53953c96d0b..13cac83fc3f 100644 --- a/sql/sql_manager.cc +++ b/sql/sql_manager.cc @@ -55,13 +55,7 @@ pthread_handler_decl(handle_manager,arg __attribute__((unused))) { if (reset_flush_time) { -#ifdef HAVE_TIMESPEC_TS_SEC - abstime.ts_sec = time(NULL)+flush_time; // Bsd 2.1 - abstime.ts_nsec = 0; -#else - abstime.tv_sec = time(NULL)+flush_time; // Linux or Solairs - abstime.tv_nsec = 0; -#endif + set_timespec(abstime, flush_time); reset_flush_time = FALSE; } while (!manager_status && !error && !abort_loop) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 3662aa301e2..f61624dbe52 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -89,8 +89,8 @@ static void test_signal(int sig_ptr) MessageBox(NULL,"Test signal","DBUG",MB_OK); #endif #if defined(OS2) - fprintf( stderr, "Test signal %d\n", sig_ptr); - fflush( stderr); + fprintf(stderr, "Test signal %d\n", sig_ptr); + fflush(stderr); #endif } static void init_signals(void) diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index bfee5f9235b..c65654faefb 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -607,25 +607,14 @@ int stop_slave(THD* thd, bool net_report ) // do not abort the slave in the middle of a query, so we do not set // thd->killed for the slave thread thd->proc_info = "waiting for slave to die"; - while(slave_running) + while (slave_running) { - /* there is a small chance that slave thread might miss the first - alarm. To protect againts it, resend the signal until it reacts + /* + There is a small chance that slave thread might miss the first + alarm. To protect againts it, resend the signal until it reacts */ - struct timespec abstime; -#ifdef HAVE_TIMESPEC_TS_SEC - abstime.ts_sec=time(NULL)+2; - abstime.ts_nsec=0; -#elif defined(__WIN__) - abstime.tv_sec=time((time_t*) 0)+2; - abstime.tv_nsec=0; -#else - struct timeval tv; - gettimeofday(&tv,0); - abstime.tv_sec=tv.tv_sec+2; - abstime.tv_nsec=tv.tv_usec*1000; -#endif + set_timespec(abstime, 2); pthread_cond_timedwait(&COND_slave_stopped, &LOCK_slave, &abstime); if (slave_running) KICK_SLAVE; @@ -659,8 +648,8 @@ void reset_slave() pthread_mutex_lock(&LOCK_slave); if ((slave_was_running = slave_running)) { - pthread_mutex_unlock(&LOCK_slave); - stop_slave(0,0); + pthread_mutex_unlock(&LOCK_slave); + stop_slave(0,0); } else pthread_mutex_unlock(&LOCK_slave); diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 821ec3fe972..8ffeb70e912 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -652,6 +652,8 @@ mysqld_show_keys(THD *thd, TABLE_LIST *table_list) item->maybe_null=1; field_list.push_back(item=new Item_empty_string("Packed",10)); item->maybe_null=1; + field_list.push_back(new Item_empty_string("Null",3)); + field_list.push_back(new Item_empty_string("Index_type",16)); field_list.push_back(new Item_empty_string("Comment",255)); item->maybe_null=1; @@ -691,6 +693,8 @@ mysqld_show_keys(THD *thd, TABLE_LIST *table_list) } else net_store_null(packet); + + /* Check if we have a key part that only uses part of the field */ if (!key_part->field || key_part->length != table->field[key_part->fieldnr-1]->key_length()) @@ -701,8 +705,14 @@ mysqld_show_keys(THD *thd, TABLE_LIST *table_list) else net_store_null(packet); net_store_null(packet); // No pack_information yet - net_store_data(packet,convert, - key_info->flags & HA_FULLTEXT ? "FULLTEXT":""); + + /* Null flag */ + uint flags= key_part->field ? key_part->field->flags : 0; + char *pos=(byte*) ((flags & NOT_NULL_FLAG) ? "" : "YES"); + net_store_data(packet,convert,(const char*) pos); + net_store_data(packet,convert,table->file->index_type(i)); + /* Comment */ + net_store_data(packet,convert,""); if (my_net_write(&thd->net,(char*) packet->ptr(),packet->length())) DBUG_RETURN(1); /* purecov: inspected */ } diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 6ded046ccbf..ac0748d1497 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -26,6 +26,7 @@ #endif extern HASH open_cache; +static const char *primary_key_name="PRIMARY"; static bool check_if_keyname_exists(const char *name,KEY *start, KEY *end); static char *make_unique_key_name(const char *field_name,KEY *start,KEY *end); @@ -196,6 +197,48 @@ int quick_rm_table(enum db_type base,const char *db, return ha_delete_table(base,path) || error; } +/* + Sort keys in the following order: + - PRIMARY KEY + - UNIQUE keyws where all column are NOT NULL + - Other UNIQUE keys + - Normal keys + - Fulltext keys + + This will make checking for duplicated keys faster and ensure that + PRIMARY keys are prioritized. +*/ + + +static int sort_keys(KEY *a, KEY *b) +{ + if (a == b) // Safety + return 0; + if (a->flags & HA_NOSAME) + { + if (!(b->flags & HA_NOSAME)) + return -1; + if ((a->flags ^ b->flags) & HA_NULL_PART_KEY) + { + /* Sort NOT NULL keys before other keys */ + return (a->flags & HA_NULL_PART_KEY) ? 1 : -1; + } + if (a->name == primary_key_name) + return -1; + if (b->name == primary_key_name) + return 1; + } + else if (b->flags & HA_NOSAME) + return 1; // Prefer b + + if ((a->flags ^ b->flags) & HA_FULLTEXT) + { + return (a->flags & HA_FULLTEXT) ? 1 : -1; + } + return a < b ? -1 : 1; // Prefer original key order +} + + /***************************************************************************** * Create a table. * If one creates a temporary table, this is automaticly opened @@ -351,8 +394,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, List_iterator<Key> key_iterator(keys); uint key_parts=0,key_count=keys.elements; List<Key> keys_in_order; // Add new keys here - Key *primary_key=0; - bool unique_key=0; + bool primary_key=0,unique_key=0; Key *key; uint tmp; tmp=min(file->max_keys(), MAX_KEY); @@ -362,12 +404,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, DBUG_RETURN(-1); } - /* - Check keys; - Put PRIMARY KEY first, then UNIQUE keys and other keys last - This will make checking for duplicated keys faster and ensure that - primary keys are prioritized. - */ + /* Calculate number of key segements */ while ((key=key_iterator++)) { @@ -383,33 +420,6 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, DBUG_RETURN(-1); } key_parts+=key->columns.elements; - if (key->type == Key::PRIMARY) - { - if (primary_key) - { - my_error(ER_MULTIPLE_PRI_KEY,MYF(0)); - DBUG_RETURN(-1); - } - primary_key=key; - } - else if (key->type == Key::UNIQUE) - { - unique_key=1; - if (keys_in_order.push_front(key)) - DBUG_RETURN(-1); - } - else if (keys_in_order.push_back(key)) - DBUG_RETURN(-1); - } - if (primary_key) - { - if (keys_in_order.push_front(primary_key)) - DBUG_RETURN(-1); - } - else if (!unique_key && (file->option_flag() & HA_REQUIRE_PRIMARY_KEY)) - { - my_error(ER_REQUIRES_PRIMARY_KEY,MYF(0)); - DBUG_RETURN(-1); } key_info_buffer=key_info=(KEY*) sql_calloc(sizeof(KEY)*key_count); @@ -417,8 +427,8 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, if (!key_info_buffer || ! key_part_info) DBUG_RETURN(-1); // Out of memory - List_iterator<Key> key_iterator_in_order(keys_in_order); - for (; (key=key_iterator_in_order++) ; key_info++) + key_iterator.rewind(); + for (; (key=key_iterator++) ; key_info++) { uint key_length=0; key_part_spec *column; @@ -486,6 +496,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, MYF(0),column->field_name); DBUG_RETURN(-1); } + key_info->flags|= HA_NULL_PART_KEY; } if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER) { @@ -545,7 +556,15 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, if (column_nr == 0) { if (key->type == Key::PRIMARY) - key_name="PRIMARY"; + { + if (primary_key) + { + my_error(ER_MULTIPLE_PRI_KEY,MYF(0)); + DBUG_RETURN(-1); + } + key_name=primary_key_name; + primary_key=1; + } else if (!(key_name = key->name())) key_name=make_unique_key_name(sql_field->field_name, key_info_buffer,key_info); @@ -557,6 +576,8 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, key_info->name=(char*) key_name; } } + if (!(key_info->flags & HA_NULL_PART_KEY)) + unique_key=1; key_info->key_length=(uint16) key_length; uint max_key_length= max(file->max_key_length(), MAX_KEY_LENGTH); if (key_length > max_key_length && key->type != Key::FULLTEXT) @@ -565,11 +586,19 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, DBUG_RETURN(-1); } } + if (!unique_key && !primary_key && + (file->option_flag() & HA_REQUIRE_PRIMARY_KEY)) + { + my_error(ER_REQUIRES_PRIMARY_KEY,MYF(0)); + DBUG_RETURN(-1); + } if (auto_increment > 0) { my_error(ER_WRONG_AUTO_KEY,MYF(0)); DBUG_RETURN(-1); } + /* Sort keys in optimized order */ + qsort((gptr) key_info_buffer, key_count, sizeof(KEY), (qsort_cmp) sort_keys); /* Check if table exists */ if (create_info->options & HA_LEX_CREATE_TMP_TABLE) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 5282fb157e6..382e007447d 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -351,6 +351,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token PRECISION %token QUICK %token REAL +%token SIGNED %token SMALLINT %token STRING_SYM %token TEXT_SYM @@ -1009,7 +1010,8 @@ field_opt_list: | field_option {} field_option: - UNSIGNED { Lex->type|= UNSIGNED_FLAG;} + SIGNED {} + | UNSIGNED { Lex->type|= UNSIGNED_FLAG;} | ZEROFILL { Lex->type|= UNSIGNED_FLAG | ZEROFILL_FLAG; } opt_len: @@ -1595,7 +1597,9 @@ simple_expr: | MATCH ident_list_arg AGAINST '(' expr IN_SYM BOOLEAN_SYM MODE_SYM ')' { Select->ftfunc_list.push_back((Item_func_match *) ($$=new Item_func_match_bool(*$2,$5))); } - | BINARY expr %prec NEG { $$= new Item_func_binary($2); } + | BINARY expr %prec NEG { $$= new Item_func_binary($2); } + | SIGNED expr %prec NEG { $$= new Item_func_signed($2); } + | UNSIGNED expr %prec NEG { $$= new Item_func_unsigned($2); } | CASE_SYM opt_expr WHEN_SYM when_list opt_else END { $$= new Item_func_case(* $4, $2, $5 ) } | FUNC_ARG0 '(' ')' |