summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <monty@mashka.mysql.fi>2002-11-21 15:56:48 +0200
committerunknown <monty@mashka.mysql.fi>2002-11-21 15:56:48 +0200
commit33fc0d53b543032accea2476a4eed0522cead2bb (patch)
treed3df5d3fc1abf364dcbcc8eb2305a1cf62540192 /sql
parent2723dbdb5e2c60162ca464f65f68fdd13b7c9cef (diff)
parent70a17cd5a7aab52697b494cd8379fb78db15eeea (diff)
downloadmariadb-git-33fc0d53b543032accea2476a4eed0522cead2bb.tar.gz
Merge with 4.0
BitKeeper/etc/gone: auto-union BitKeeper/etc/ignore: auto-union BitKeeper/etc/logging_ok: auto-union BitKeeper/deleted/.del-.my_sys.h.swp~f6a4a7f8dae03f18: Auto merged BitKeeper/etc/config: Auto merged acconfig.h: Auto merged acinclude.m4: Auto merged Docs/manual.texi: Auto merged client/mysqlcheck.c: Auto merged client/mysqlshow.c: Auto merged include/myisam.h: Auto merged include/violite.h: Auto merged isam/pack_isam.c: Auto merged libmysql/libmysql.c: Auto merged libmysqld/lib_sql.cc: Auto merged myisam/Makefile.am: Auto merged myisam/ft_nlq_search.c: Auto merged myisam/mi_open.c: Auto merged myisam/mi_write.c: Auto merged myisam/sort.c: Auto merged mysql-test/mysql-test-run.sh: Auto merged mysql-test/r/fulltext.result: Auto merged mysql-test/r/func_test.result: Auto merged mysql-test/r/isam.result: Auto merged mysql-test/r/rpl_replicate_do.result: Auto merged mysql-test/r/variables.result: Auto merged mysql-test/t/func_test.test: Auto merged mysql-test/t/myisam.test: Auto merged mysql-test/t/rpl_rotate_logs.test: Auto merged mysql-test/t/variables.test: Auto merged mysys/hash.c: Auto merged mysys/tree.c: Auto merged scripts/Makefile.am: Auto merged sql/Makefile.am: Auto merged sql/filesort.cc: Auto merged sql/gen_lex_hash.cc: Auto merged sql/ha_berkeley.cc: Auto merged sql/ha_innodb.cc: Auto merged sql/handler.cc: Auto merged sql/handler.h: Auto merged sql/hash_filo.h: Auto merged sql/hostname.cc: Auto merged sql/item_func.cc: Auto merged sql/item_func.h: Auto merged sql/item_timefunc.cc: Auto merged sql/lex.h: Auto merged sql/lock.cc: Auto merged sql/log.cc: Auto merged sql/log_event.h: Auto merged sql/mini_client.cc: Auto merged sql/opt_range.cc: Auto merged sql/opt_sum.cc: Auto merged sql/repl_failsafe.cc: Auto merged sql/set_var.h: Auto merged sql/slave.h: Auto merged sql/sql_acl.cc: Auto merged sql/sql_analyse.cc: Auto merged sql/sql_cache.cc: Auto merged sql/sql_insert.cc: Auto merged sql/sql_load.cc: Auto merged sql/sql_rename.cc: Auto merged sql/sql_repl.cc: Auto merged sql/sql_show.cc: Auto merged sql/sql_table.cc: Auto merged sql/sql_udf.cc: Auto merged sql/share/czech/errmsg.txt: Auto merged sql/share/danish/errmsg.txt: Auto merged sql/share/dutch/errmsg.txt: Auto merged sql/share/english/errmsg.txt: Auto merged sql/share/estonian/errmsg.txt: Auto merged sql/share/french/errmsg.txt: Auto merged sql/share/german/errmsg.txt: Auto merged sql/share/greek/errmsg.txt: Auto merged sql/share/hungarian/errmsg.txt: Auto merged sql/share/italian/errmsg.txt: Auto merged sql/share/japanese/errmsg.txt: Auto merged sql/share/korean/errmsg.txt: Auto merged sql/share/norwegian/errmsg.txt: Auto merged sql/table.h: Auto merged sql/unireg.cc: Auto merged sql-bench/server-cfg.sh: Auto merged sql/share/norwegian-ny/errmsg.txt: Auto merged sql/share/polish/errmsg.txt: Auto merged sql/share/portuguese/errmsg.txt: Auto merged sql/share/romanian/errmsg.txt: Auto merged sql/share/russian/errmsg.txt: Auto merged sql/share/slovak/errmsg.txt: Auto merged sql/share/spanish/errmsg.txt: Auto merged sql/share/swedish/errmsg.txt: Auto merged sql/share/ukrainian/errmsg.txt: Auto merged sql/ha_myisam.cc: Merge with 4.0 Removed some commented code sql/sql_db.cc: Merge with 4.0 Optimized the logging of the drop db call a bit sql/sql_update.cc: Added comment
Diffstat (limited to 'sql')
-rw-r--r--sql/field.cc155
-rw-r--r--sql/filesort.cc4
-rw-r--r--sql/gen_lex_hash.cc2
-rw-r--r--sql/ha_berkeley.cc4
-rw-r--r--sql/ha_berkeley.h3
-rw-r--r--sql/ha_heap.cc12
-rw-r--r--sql/ha_innodb.cc255
-rw-r--r--sql/ha_innodb.h2
-rw-r--r--sql/ha_isam.cc3
-rw-r--r--sql/ha_isammrg.cc12
-rw-r--r--sql/ha_myisam.cc46
-rw-r--r--sql/ha_myisammrg.cc66
-rw-r--r--sql/ha_myisammrg.h5
-rw-r--r--sql/handler.cc3
-rw-r--r--sql/handler.h3
-rw-r--r--sql/hash_filo.h4
-rw-r--r--sql/hostname.cc2
-rw-r--r--sql/item.h2
-rw-r--r--sql/item_cmpfunc.cc88
-rw-r--r--sql/item_cmpfunc.h21
-rw-r--r--sql/item_func.cc63
-rw-r--r--sql/item_func.h2
-rw-r--r--sql/item_timefunc.cc19
-rw-r--r--sql/lex.h1
-rw-r--r--sql/lock.cc12
-rw-r--r--sql/log.cc38
-rw-r--r--sql/log_event.cc146
-rw-r--r--sql/log_event.h50
-rw-r--r--sql/mini_client.cc4
-rw-r--r--sql/mysql_priv.h23
-rw-r--r--sql/mysqld.cc136
-rw-r--r--sql/nt_servc.cc28
-rw-r--r--sql/opt_range.cc59
-rw-r--r--sql/opt_sum.cc13
-rw-r--r--sql/repl_failsafe.cc9
-rw-r--r--sql/set_var.cc25
-rw-r--r--sql/set_var.h17
-rw-r--r--sql/share/czech/errmsg.txt2
-rw-r--r--sql/share/danish/errmsg.txt2
-rw-r--r--sql/share/dutch/errmsg.txt2
-rw-r--r--sql/share/english/errmsg.txt2
-rw-r--r--sql/share/estonian/errmsg.txt2
-rw-r--r--sql/share/french/errmsg.txt2
-rw-r--r--sql/share/german/errmsg.txt2
-rw-r--r--sql/share/greek/errmsg.txt2
-rw-r--r--sql/share/hungarian/errmsg.txt2
-rw-r--r--sql/share/italian/errmsg.txt2
-rw-r--r--sql/share/japanese/errmsg.txt2
-rw-r--r--sql/share/korean/errmsg.txt2
-rw-r--r--sql/share/norwegian-ny/errmsg.txt2
-rw-r--r--sql/share/norwegian/errmsg.txt2
-rw-r--r--sql/share/polish/errmsg.txt2
-rw-r--r--sql/share/portuguese/errmsg.txt2
-rw-r--r--sql/share/romanian/errmsg.txt2
-rw-r--r--sql/share/russian/errmsg.txt2
-rw-r--r--sql/share/slovak/errmsg.txt2
-rw-r--r--sql/share/spanish/errmsg.txt2
-rw-r--r--sql/share/swedish/errmsg.txt2
-rw-r--r--sql/share/ukrainian/errmsg.txt2
-rw-r--r--sql/slave.cc20
-rw-r--r--sql/slave.h4
-rw-r--r--sql/sql_acl.cc40
-rw-r--r--sql/sql_acl.h6
-rw-r--r--sql/sql_analyse.cc2
-rw-r--r--sql/sql_base.cc180
-rw-r--r--sql/sql_cache.cc129
-rw-r--r--sql/sql_cache.h4
-rw-r--r--sql/sql_class.cc107
-rw-r--r--sql/sql_class.h13
-rw-r--r--sql/sql_db.cc27
-rw-r--r--sql/sql_delete.cc108
-rw-r--r--sql/sql_insert.cc54
-rw-r--r--sql/sql_lex.h4
-rw-r--r--sql/sql_load.cc31
-rw-r--r--sql/sql_manager.cc2
-rw-r--r--sql/sql_parse.cc178
-rw-r--r--sql/sql_rename.cc2
-rw-r--r--sql/sql_repl.cc7
-rw-r--r--sql/sql_repl.h4
-rw-r--r--sql/sql_select.cc69
-rw-r--r--sql/sql_show.cc6
-rw-r--r--sql/sql_table.cc65
-rw-r--r--sql/sql_udf.cc4
-rw-r--r--sql/sql_update.cc117
-rw-r--r--sql/sql_yacc.yy246
-rw-r--r--sql/stacktrace.c2
-rw-r--r--sql/table.cc15
-rw-r--r--sql/table.h1
88 files changed, 1726 insertions, 1102 deletions
diff --git a/sql/field.cc b/sql/field.cc
index 73ef4439bc9..f2324a0a331 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -41,6 +41,11 @@
#include <floatingpoint.h>
#endif
+// Maximum allowed exponent value for converting string to decimal
+#define MAX_EXPONENT 1024
+
+
+
/*****************************************************************************
Instansiate templates and static variables
*****************************************************************************/
@@ -392,7 +397,7 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs)
const char *frac_digits_from, *frac_digits_end;
/* The sign of the exponent : will be 0 (means no exponent), '+' or '-' */
char expo_sign_char=0;
- uint exponent=0; // value of the exponent
+ uint exponent=0; // value of the exponent
/*
Pointers used when digits move from the left of the '.' to the
right of the '.' (explained below)
@@ -488,13 +493,17 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs)
else
expo_sign_char= '+';
/*
- Read digits of the exponent and compute its value
- 'exponent' overflow (e.g. if 1E10000000000000000) is not a problem
- (the value of the field will be overflow anyway, or 0 anyway,
- it does not change anything if the exponent is 2^32 or more
+ Read digits of the exponent and compute its value. We must care about
+ 'exponent' overflow, because as unsigned arithmetic is "modulo", big
+ exponents will become small (e.g. 1e4294967296 will become 1e0, and the
+ field will finally contain 1 instead of its max possible value).
*/
- for (;from!=end && my_isdigit(system_charset_info, (*from)); from++)
+ for (;from!=end && my_isdigit(system_charset_info, *from); from++)
+ {
exponent=10*exponent+(*from-'0');
+ if (exponent>MAX_EXPONENT)
+ break;
+ }
}
/*
@@ -536,6 +545,13 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs)
int_digits_added_zeros=2 (to make 1234500).
*/
+ /*
+ Below tmp_uint cannot overflow with small enough MAX_EXPONENT setting,
+ as int_digits_added_zeros<=exponent<4G and
+ (int_digits_end-int_digits_from)<=max_allowed_packet<=2G and
+ (frac_digits_from-int_digits_tail_from)<=max_allowed_packet<=2G
+ */
+
if (!expo_sign_char)
tmp_uint=tmp_dec+(uint)(int_digits_end-int_digits_from);
else if (expo_sign_char == '-')
@@ -544,7 +560,7 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs)
frac_digits_added_zeros=exponent-tmp_uint;
int_digits_end -= tmp_uint;
frac_digits_head_end=int_digits_end+tmp_uint;
- tmp_uint=tmp_dec+(uint)(int_digits_end-int_digits_from);
+ tmp_uint=tmp_dec+(uint)(int_digits_end-int_digits_from);
}
else // (expo_sign_char=='+')
{
@@ -571,9 +587,9 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs)
int_digits_added_zeros=0;
}
}
- tmp_uint=(tmp_dec+(uint)(int_digits_end-int_digits_from)
- +(uint)(frac_digits_from-int_digits_tail_from)+
- int_digits_added_zeros);
+ tmp_uint= (tmp_dec+(int_digits_end-int_digits_from)+
+ (uint)(frac_digits_from-int_digits_tail_from)+
+ int_digits_added_zeros);
}
/*
@@ -584,7 +600,7 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs)
If the sign is defined and '-', we need one position for it
*/
- if (field_length < tmp_uint + (int) (sign_char == '-'))
+ if (field_length < tmp_uint + (int) (sign_char == '-'))
{
// too big number, change to max or min number
Field_decimal::overflow(sign_char == '-');
@@ -647,69 +663,67 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs)
*pos--=' '; //fill with blanks
}
- if (tmp_dec) // This field has decimals
- {
- /*
- Write digits of the frac_% parts ;
- Depending on current_thd->count_cutted_fields, we may also want
- to know if some non-zero tail of these parts will
- be truncated (for example, 0.002->0.00 will generate a warning,
- while 0.000->0.00 will not)
- (and 0E1000000000 will not, while 1E-1000000000 will)
- */
+ /*
+ Write digits of the frac_% parts ;
+ Depending on current_thd->count_cutted_fields, we may also want
+ to know if some non-zero tail of these parts will
+ be truncated (for example, 0.002->0.00 will generate a warning,
+ while 0.000->0.00 will not)
+ (and 0E1000000000 will not, while 1E-1000000000 will)
+ */
- pos=to+(uint)(field_length-tmp_dec); // Calculate post to '.'
+ pos=to+(uint)(field_length-tmp_dec); // Calculate post to '.'
+ right_wall=to+field_length;
+ if (pos != right_wall)
*pos++='.';
- right_wall=to+field_length;
- if (expo_sign_char == '-')
+ if (expo_sign_char == '-')
+ {
+ while (frac_digits_added_zeros-- > 0)
{
- while (frac_digits_added_zeros-- > 0)
+ if (pos == right_wall)
{
- if (pos == right_wall)
- {
- if (current_thd->count_cuted_fields && !is_cuted_fields_incr)
- break; // Go on below to see if we lose non zero digits
- return 0;
- }
- *pos++='0';
+ if (current_thd->count_cuted_fields && !is_cuted_fields_incr)
+ break; // Go on below to see if we lose non zero digits
+ return 0;
}
- while (int_digits_end != frac_digits_head_end)
+ *pos++='0';
+ }
+ while (int_digits_end != frac_digits_head_end)
+ {
+ tmp_char= *int_digits_end++;
+ if (pos == right_wall)
{
- tmp_char= *int_digits_end++;
- if (pos == right_wall)
- {
- if (tmp_char != '0') // Losing a non zero digit ?
- {
- if (!is_cuted_fields_incr)
- current_thd->cuted_fields++;
- return 0;
- }
- continue;
- }
- *pos++= tmp_char;
+ if (tmp_char != '0') // Losing a non zero digit ?
+ {
+ if (!is_cuted_fields_incr)
+ current_thd->cuted_fields++;
+ return 0;
+ }
+ continue;
}
+ *pos++= tmp_char;
}
+ }
- for (;frac_digits_from!=frac_digits_end;)
+ for (;frac_digits_from!=frac_digits_end;)
+ {
+ tmp_char= *frac_digits_from++;
+ if (pos == right_wall)
{
- tmp_char= *frac_digits_from++;
- if (pos == right_wall)
+ if (tmp_char != '0') // Losing a non zero digit ?
{
- if (tmp_char != '0') // Losing a non zero digit ?
- {
- if (!is_cuted_fields_incr)
- current_thd->cuted_fields++;
- return 0;
- }
- continue;
+ if (!is_cuted_fields_incr)
+ current_thd->cuted_fields++;
+ return 0;
}
- *pos++= tmp_char;
+ continue;
}
-
- while (pos != right_wall)
- *pos++='0'; // Fill with zeros at right of '.'
+ *pos++= tmp_char;
}
+
+ while (pos != right_wall)
+ *pos++='0'; // Fill with zeros at right of '.'
return 0;
}
@@ -3930,12 +3944,12 @@ int Field_string::pack_cmp(const char *b, uint length)
}
-uint Field_string::packed_col_length(const char *ptr, uint length)
+uint Field_string::packed_col_length(const char *data_ptr, uint length)
{
if (length > 255)
- return uint2korr(ptr)+2;
+ return uint2korr(data_ptr)+2;
else
- return (uint) ((uchar) *ptr)+1;
+ return (uint) ((uchar) *data_ptr)+1;
}
uint Field_string::max_packed_col_length(uint max_length)
@@ -4162,12 +4176,12 @@ int Field_varstring::pack_cmp(const char *b, uint key_length)
(const uchar *)b,b_length);
}
-uint Field_varstring::packed_col_length(const char *ptr, uint length)
+uint Field_varstring::packed_col_length(const char *data_ptr, uint length)
{
if (length > 255)
- return uint2korr(ptr)+2;
+ return uint2korr(data_ptr)+2;
else
- return (uint) ((uchar) *ptr)+1;
+ return (uint) ((uchar) *data_ptr)+1;
}
uint Field_varstring::max_packed_col_length(uint max_length)
@@ -4698,12 +4712,12 @@ char *Field_blob::pack_key_from_key_image(char *to, const char *from,
return to+length;
}
-uint Field_blob::packed_col_length(const char *ptr, uint length)
+uint Field_blob::packed_col_length(const char *data_ptr, uint length)
{
if (length > 255)
- return uint2korr(ptr)+2;
+ return uint2korr(data_ptr)+2;
else
- return (uint) ((uchar) *ptr)+1;
+ return (uint) ((uchar) *data_ptr)+1;
}
uint Field_blob::max_packed_col_length(uint max_length)
@@ -5294,10 +5308,11 @@ Field *make_field(char *ptr, uint32 field_length,
return new Field_datetime(ptr,null_pos,null_bit,
unireg_check, field_name, table, field_charset);
case FIELD_TYPE_NULL:
- default: // Impossible (Wrong version)
return new Field_null(ptr,field_length,unireg_check,field_name,table, field_charset);
+ default: // Impossible (Wrong version)
+ break;
}
- return 0; // Impossible (Wrong version)
+ return 0;
}
diff --git a/sql/filesort.cc b/sql/filesort.cc
index 53af60b0370..fab666a1203 100644
--- a/sql/filesort.cc
+++ b/sql/filesort.cc
@@ -223,7 +223,7 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length,
if (error)
my_error(ER_FILSORT_ABORT,MYF(ME_ERROR+ME_WAITTANG));
else
- statistic_add(filesort_rows, records, &LOCK_status);
+ statistic_add(filesort_rows, (ulong) records, &LOCK_status);
*examined_rows= param.examined_rows;
#ifdef SKIP_DBUG_IN_FILESORT
DBUG_POP(); /* Ok to DBUG */
@@ -724,7 +724,7 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
org_max_rows=max_rows=param->max_rows;
if (init_queue(&queue,(uint) (Tb-Fb)+1,offsetof(BUFFPEK,key),0,
- (int (*) (void *, byte *,byte*))
+ (queue_compare)
(cmp=get_ptr_compare(sort_length)),(void*) &sort_length))
DBUG_RETURN(1); /* purecov: inspected */
for (buffpek= Fb ; buffpek <= Tb ; buffpek++)
diff --git a/sql/gen_lex_hash.cc b/sql/gen_lex_hash.cc
index 0d92397b616..7daab228093 100644
--- a/sql/gen_lex_hash.cc
+++ b/sql/gen_lex_hash.cc
@@ -320,7 +320,7 @@ and you are welcome to modify and redistribute it under the GPL license\n");
my_print_help(my_long_options);
}
-static my_bool
+extern "C" my_bool
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
char *argument __attribute__((unused)))
{
diff --git a/sql/ha_berkeley.cc b/sql/ha_berkeley.cc
index 6d5b469a913..679642ca949 100644
--- a/sql/ha_berkeley.cc
+++ b/sql/ha_berkeley.cc
@@ -1931,7 +1931,7 @@ int ha_berkeley::delete_table(const char *name)
double ha_berkeley::scan_time()
{
- return records/3;
+ return rows2double(records/3);
}
ha_rows ha_berkeley::records_in_range(int keynr,
@@ -2206,7 +2206,7 @@ static BDB_SHARE *get_share(const char *table_name, TABLE *table)
if (!(share=(BDB_SHARE*) hash_search(&bdb_open_tables, (byte*) table_name,
length)))
{
- ha_rows *rec_per_key;
+ ulong *rec_per_key;
char *tmp_name;
DB **key_file;
u_int32_t *key_type;
diff --git a/sql/ha_berkeley.h b/sql/ha_berkeley.h
index 198664d0c06..f2a81d123f1 100644
--- a/sql/ha_berkeley.h
+++ b/sql/ha_berkeley.h
@@ -27,7 +27,8 @@
typedef struct st_berkeley_share {
ulonglong auto_ident;
- ha_rows rows, org_rows, *rec_per_key;
+ ha_rows rows, org_rows;
+ ulong *rec_per_key;
THR_LOCK lock;
pthread_mutex_t mutex;
char *table_name;
diff --git a/sql/ha_heap.cc b/sql/ha_heap.cc
index c06421617dd..4a3b9495f6f 100644
--- a/sql/ha_heap.cc
+++ b/sql/ha_heap.cc
@@ -245,7 +245,7 @@ int ha_heap::create(const char *name, TABLE *table,
{
uint key, parts, mem_per_row= 0;
uint auto_key= 0, auto_key_type= 0;
- ulong max_rows;
+ ha_rows max_rows;
HP_KEYDEF *keydef;
HA_KEYSEG *seg;
char buff[FN_REFLEN];
@@ -310,8 +310,8 @@ int ha_heap::create(const char *name, TABLE *table,
}
}
mem_per_row+= MY_ALIGN(table->reclength + 1, sizeof(char*));
- max_rows = (ulong) (current_thd->variables.max_heap_table_size /
- mem_per_row);
+ max_rows = (ha_rows) (current_thd->variables.max_heap_table_size /
+ mem_per_row);
HP_CREATE_INFO hp_create_info;
hp_create_info.auto_key= auto_key;
hp_create_info.auto_key_type= auto_key_type;
@@ -319,9 +319,9 @@ int ha_heap::create(const char *name, TABLE *table,
create_info->auto_increment_value - 1 : 0);
error= heap_create(fn_format(buff,name,"","",4+2),
table->keys,keydef, table->reclength,
- ((table->max_rows < max_rows && table->max_rows) ?
- table->max_rows : max_rows),
- table->min_rows, &hp_create_info);
+ (ulong) ((table->max_rows < max_rows && table->max_rows) ?
+ table->max_rows : max_rows),
+ (ulong) table->min_rows, &hp_create_info);
my_free((gptr) keydef, MYF(0));
if (file)
info(HA_STATUS_NO_LOCK | HA_STATUS_CONST | HA_STATUS_VARIABLE);
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index 9aa63cc1435..7787b543f34 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -40,17 +40,12 @@ InnoDB */
#include "ha_innodb.h"
-/* We must declare this here because we undef SAFE_MUTEX below */
pthread_mutex_t innobase_mutex;
/* Store MySQL definition of 'byte': in Linux it is char while InnoDB
uses unsigned char */
typedef byte mysql_byte;
-#ifdef SAFE_MUTEX
-#undef pthread_mutex_t
-#endif
-
#define INSIDE_HA_INNOBASE_CC
/* Include necessary InnoDB headers */
@@ -97,6 +92,8 @@ are determined in innobase_init below: */
char* innobase_data_home_dir = NULL;
char* innobase_log_group_home_dir = NULL;
char* innobase_log_arch_dir = NULL;
+/* The following has a midleading name: starting from 4.0.5 this also
+affects Windows */
char* innobase_unix_file_flush_method = NULL;
/* Below we have boolean-valued start-up parameters, and their default
@@ -253,6 +250,10 @@ convert_error_code_to_mysql(
} else if (error == (int) DB_TOO_BIG_RECORD) {
return(HA_ERR_TO_BIG_ROW);
+
+ } else if (error == (int) DB_CORRUPTION) {
+
+ return(HA_ERR_CRASHED);
} else {
return(-1); // Unknown error
}
@@ -346,7 +347,8 @@ check_trx_exists(
trx = trx_allocate_for_mysql();
trx->mysql_thd = thd;
-
+ trx->mysql_query_str = &((*thd).query);
+
thd->transaction.all.innobase_tid = trx;
/* The execution of a single SQL statement is denoted by
@@ -713,9 +715,10 @@ innobase_init(void)
DBUG_RETURN(TRUE);
}
- srv_unix_file_flush_method_str = (innobase_unix_file_flush_method ?
+
+ srv_file_flush_method_str = (innobase_unix_file_flush_method ?
innobase_unix_file_flush_method :
- (char*)"fdatasync");
+ NULL);
srv_n_log_groups = (ulint) innobase_mirrored_log_groups;
srv_n_log_files = (ulint) innobase_log_files_in_group;
@@ -725,8 +728,6 @@ innobase_init(void)
srv_log_buffer_size = (ulint) innobase_log_buffer_size;
srv_flush_log_at_trx_commit = (ulint) innobase_flush_log_at_trx_commit;
- srv_use_native_aio = 0;
-
srv_pool_size = (ulint) innobase_buffer_pool_size;
srv_mem_pool_size = (ulint) innobase_additional_mem_pool_size;
@@ -750,6 +751,14 @@ innobase_init(void)
default_charset_info->sort_order, 256);
}
+ /* Since we in this module access directly the fields of a trx
+ struct, and due to different headers and flags it might happen that
+ mutex_t has a different size in this module and in InnoDB
+ modules, we check at run time that the size is the same in
+ these compilation modules. */
+
+ srv_sizeof_trx_t_in_ha_innodb_cc = sizeof(trx_t);
+
err = innobase_start_or_create_for_mysql();
if (err != DB_SUCCESS) {
@@ -1147,15 +1156,15 @@ ha_innobase::open(
ib_table = dict_table_get_and_increment_handle_count(
norm_name, NULL);
if (NULL == ib_table) {
-
- 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?\n\
-Look from section 15.1 of http://www.innodb.com/ibman.html\n\
-how you can resolve the problem.\n",
+ ut_print_timestamp(stderr);
+ fprintf(stderr, " 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?\n"
+"Look from section 15.1 of http://www.innodb.com/ibman.html\n"
+"how you can resolve the problem.\n",
norm_name);
free_share(share);
@@ -1168,7 +1177,10 @@ how you can resolve the problem.\n",
((row_prebuilt_t*)innobase_prebuilt)->mysql_row_len = table->reclength;
- primary_key = MAX_KEY;
+ /* Looks like MySQL-3.23 sometimes has primary key number != 0 */
+
+ primary_key = table->primary_key;
+ key_used_on_scan = primary_key;
/* Allocate a buffer for a 'row reference'. A row reference is
a string of bytes of length ref_length which uniquely specifies
@@ -1177,13 +1189,14 @@ how you can resolve the problem.\n",
of length ref_length! */
if (!row_table_got_default_clust_index(ib_table)) {
+ if (primary_key >= MAX_KEY) {
+ fprintf(stderr,
+ "InnoDB: Error: table %s has a primary key in InnoDB\n"
+ "InnoDB: data dictionary, but not in MySQL!\n", name);
+ }
((row_prebuilt_t*)innobase_prebuilt)
->clust_index_was_generated = FALSE;
-
- primary_key = 0;
- key_used_on_scan = 0;
-
/*
MySQL allocates the buffer for ref. key_info->key_length
includes space for all key columns + one byte for each column
@@ -1192,8 +1205,14 @@ how you can resolve the problem.\n",
based on ref_length.
*/
- ref_length = table->key_info->key_length;
+ ref_length = table->key_info[primary_key].key_length;
} else {
+ if (primary_key != MAX_KEY) {
+ fprintf(stderr,
+ "InnoDB: Error: table %s has no primary key in InnoDB\n"
+ "InnoDB: data dictionary, but has one in MySQL!\n", name);
+ }
+
((row_prebuilt_t*)innobase_prebuilt)
->clust_index_was_generated = TRUE;
@@ -1501,7 +1520,8 @@ ha_innobase::store_key_val_for_row(
are equal
*/
bzero(buff, (ref_length- (uint) (buff - buff_start)));
- DBUG_RETURN(ref_length);
+
+ DBUG_RETURN((uint)(buff - buff_start));
}
/******************************************************************
@@ -1679,6 +1699,7 @@ ha_innobase::write_row(
longlong dummy;
ibool incremented_auto_inc_for_stat = FALSE;
ibool incremented_auto_inc_counter = FALSE;
+ ibool skip_auto_inc_decr;
DBUG_ENTER("ha_innobase::write_row");
@@ -1843,13 +1864,31 @@ ha_innobase::write_row(
if (error != DB_SUCCESS) {
/* If the insert did not succeed we restore the value of
the auto-inc counter we used; note that this behavior was
- introduced only in version 4.0.4 */
+ introduced only in version 4.0.4.
+ NOTE that a REPLACE command handles a duplicate key error
+ itself, and we must not decrement the autoinc counter
+ if we are performing a REPLACE statement.
+ NOTE 2: if there was an error, for example a deadlock,
+ which caused InnoDB to roll back the whole transaction
+ already in the call of row_insert_for_mysql(), we may no
+ longer have the AUTO-INC lock, and cannot decrement
+ the counter here. */
+
+ skip_auto_inc_decr = FALSE;
+
+ if (error == DB_DUPLICATE_KEY) {
+ ut_a(user_thd->query);
+ dict_accept(user_thd->query, "REPLACE",
+ &skip_auto_inc_decr);
+ }
- if (incremented_auto_inc_counter) {
+ if (!skip_auto_inc_decr && incremented_auto_inc_counter
+ && prebuilt->trx->auto_inc_lock) {
dict_table_autoinc_decrement(prebuilt->table);
}
- if (incremented_auto_inc_for_stat) {
+ if (!skip_auto_inc_decr && incremented_auto_inc_for_stat
+ && prebuilt->trx->auto_inc_lock) {
auto_inc_counter_for_this_stat--;
}
}
@@ -2181,8 +2220,16 @@ convert_search_mode_to_innobase(
case HA_READ_AFTER_KEY: return(PAGE_CUR_G);
case HA_READ_BEFORE_KEY: return(PAGE_CUR_L);
case HA_READ_PREFIX: return(PAGE_CUR_GE);
- case HA_READ_PREFIX_LAST: return(PAGE_CUR_LE);
- /* HA_READ_PREFIX_LAST does not yet work in InnoDB! */
+ case HA_READ_PREFIX_LAST:
+ /* ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: Warning: Using HA_READ_PREFIX_LAST\n"); */
+ return(PAGE_CUR_LE);
+
+ /* InnoDB does not yet support ..PREFIX_LAST!
+ We have to add a new search flag
+ PAGE_CUR_LE_OR_PREFIX to InnoDB. */
+
/* the above PREFIX flags mean that the last
field in the key value may just be a prefix
of the complete fixed length field */
@@ -2751,7 +2798,11 @@ ha_innobase::position(
that len is always fixed for this table. The following assertion
checks this. */
- ut_a(len == ref_length);
+ if (len != ref_length) {
+ fprintf(stderr,
+ "InnoDB: Error: stored ref len is %lu, but table ref len is %lu\n",
+ (ulint)len, (ulint)ref_length);
+ }
}
@@ -2935,16 +2986,21 @@ ha_innobase::create(
trx->check_unique_secondary = FALSE;
}
+ if (lower_case_table_names) {
+ srv_lower_case_table_names = TRUE;
+ } else {
+ srv_lower_case_table_names = FALSE;
+ }
fn_format(name2, name, "", "",2); // Remove the .frm extension
normalize_table_name(norm_name, name2);
- /* Latch the InnoDB data dictionary exclusive so that no deadlocks
+ /* Latch the InnoDB data dictionary exclusively so that no deadlocks
or lock waits can happen in it during a table create operation.
- (Drop table etc. do this latching in row0mysql.c.) */
+ Drop table etc. do this latching in row0mysql.c. */
- row_mysql_lock_data_dictionary();
+ row_mysql_lock_data_dictionary(trx);
/* Create the table definition in InnoDB */
@@ -2953,7 +3009,7 @@ ha_innobase::create(
if (error) {
innobase_commit_low(trx);
- row_mysql_unlock_data_dictionary();
+ row_mysql_unlock_data_dictionary(trx);
trx_free_for_mysql(trx);
@@ -2983,7 +3039,7 @@ ha_innobase::create(
if (error) {
innobase_commit_low(trx);
- row_mysql_unlock_data_dictionary();
+ row_mysql_unlock_data_dictionary(trx);
trx_free_for_mysql(trx);
@@ -2998,7 +3054,7 @@ ha_innobase::create(
(uint) primary_key_no))) {
innobase_commit_low(trx);
- row_mysql_unlock_data_dictionary();
+ row_mysql_unlock_data_dictionary(trx);
trx_free_for_mysql(trx);
@@ -3014,7 +3070,7 @@ ha_innobase::create(
innobase_commit_low(trx);
- row_mysql_unlock_data_dictionary();
+ row_mysql_unlock_data_dictionary(trx);
trx_free_for_mysql(trx);
@@ -3023,24 +3079,27 @@ ha_innobase::create(
}
}
- error = row_table_add_foreign_constraints(trx,
- create_info->create_statement, norm_name);
+ if (current_thd->query != NULL) {
+
+ error = row_table_add_foreign_constraints(trx,
+ current_thd->query, norm_name);
- error = convert_error_code_to_mysql(error, NULL);
+ error = convert_error_code_to_mysql(error, NULL);
- if (error) {
- innobase_commit_low(trx);
+ if (error) {
+ innobase_commit_low(trx);
- row_mysql_unlock_data_dictionary();
+ row_mysql_unlock_data_dictionary(trx);
- trx_free_for_mysql(trx);
+ trx_free_for_mysql(trx);
- DBUG_RETURN(error);
+ DBUG_RETURN(error);
+ }
}
innobase_commit_low(trx);
- row_mysql_unlock_data_dictionary();
+ row_mysql_unlock_data_dictionary(trx);
/* Flush the log to reduce probability that the .frm files and
the InnoDB data dictionary get out-of-sync if the user runs
@@ -3082,6 +3141,12 @@ ha_innobase::delete_table(
DBUG_ENTER("ha_innobase::delete_table");
+ if (lower_case_table_names) {
+ srv_lower_case_table_names = TRUE;
+ } else {
+ srv_lower_case_table_names = FALSE;
+ }
+
trx = trx_allocate_for_mysql();
name_len = strlen(name);
@@ -3095,7 +3160,7 @@ ha_innobase::delete_table(
/* Drop the table in InnoDB */
- error = row_drop_table_for_mysql(norm_name, trx, FALSE);
+ error = row_drop_table_for_mysql(norm_name, trx);
/* Flush the log to reduce probability that the .frm files and
the InnoDB data dictionary get out-of-sync if the user runs
@@ -3192,6 +3257,12 @@ ha_innobase::rename_table(
DBUG_ENTER("ha_innobase::rename_table");
+ if (lower_case_table_names) {
+ srv_lower_case_table_names = TRUE;
+ } else {
+ srv_lower_case_table_names = FALSE;
+ }
+
trx = trx_allocate_for_mysql();
name_len1 = strlen(from);
@@ -3318,7 +3389,7 @@ ha_innobase::estimate_number_of_rows(void)
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
dict_index_t* index;
ulonglong estimate;
- ulonglong data_file_length;
+ ulonglong local_data_file_length;
/* Warning: since it is not sure that MySQL calls external_lock
before calling this function, the trx field in prebuilt can be
@@ -3328,7 +3399,7 @@ ha_innobase::estimate_number_of_rows(void)
index = dict_table_get_first_index_noninline(prebuilt->table);
- data_file_length = ((ulonglong) index->stat_n_leaf_pages)
+ local_data_file_length = ((ulonglong) index->stat_n_leaf_pages)
* UNIV_PAGE_SIZE;
/* Calculate a minimum length for a clustered index record and from
@@ -3337,7 +3408,7 @@ ha_innobase::estimate_number_of_rows(void)
by a threshold factor, we must add a safety factor 2 in front
of the formula below. */
- estimate = 2 * data_file_length / dict_index_calc_min_rec_len(index);
+ estimate = 2 * local_data_file_length / dict_index_calc_min_rec_len(index);
DBUG_RETURN((ha_rows) estimate);
}
@@ -3374,12 +3445,21 @@ ha_innobase::info(
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
dict_table_t* ib_table;
dict_index_t* index;
- ulong rec_per_key;
+ ha_rows rec_per_key;
ulong j;
ulong i;
DBUG_ENTER("info");
+ /* If we are forcing recovery at a high level, we will suppress
+ statistics calculation on tables, because that may crash the
+ server if an index is badly corrupted. */
+
+ if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
+
+ return;
+ }
+
/* Warning: since it is not sure that MySQL calls external_lock
before calling this function, the trx field in prebuilt can be
obsolete! */
@@ -3426,7 +3506,7 @@ ha_innobase::info(
rec_per_key = records;
} else {
- rec_per_key = (ulong)(records /
+ rec_per_key = (ha_rows)(records /
index->stat_n_diff_key_vals[j + 1]);
}
@@ -3441,8 +3521,9 @@ ha_innobase::info(
rec_per_key = 1;
}
- table->key_info[i].rec_per_key[j]
- = rec_per_key;
+ table->key_info[i].rec_per_key[j]=
+ rec_per_key >= ~(ulong) 0 ? ~(ulong) 0 :
+ rec_per_key;
}
index = dict_table_get_next_index_noninline(index);
@@ -3641,7 +3722,6 @@ ha_innobase::reset(void)
return(0);
}
-
/**********************************************************************
When we create a temporary table inside MySQL LOCK TABLES, MySQL will
not call external_lock for the temporary table when it uses it. Instead,
@@ -3663,12 +3743,20 @@ ha_innobase::start_stmt(
innobase_release_stat_resources(trx);
trx_mark_sql_stat_end(trx);
+ if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
+ && trx->read_view) {
+ /* At low transaction isolation levels we let
+ each consistent read set its own snapshot */
+
+ read_view_close_for_mysql(trx);
+ }
+
auto_inc_counter_for_this_stat = 0;
prebuilt->sql_stat_start = TRUE;
prebuilt->hint_no_need_to_fetch_extra_cols = TRUE;
prebuilt->read_just_key = 0;
- if (prebuilt->select_lock_type == LOCK_NONE) {
+ if (!prebuilt->mysql_has_locked) {
/* This handle is for a temporary table created inside
this same LOCK TABLES; since MySQL does NOT call external_lock
in this case, we must use x-row locks inside InnoDB to be
@@ -3683,6 +3771,24 @@ ha_innobase::start_stmt(
}
/**********************************************************************
+Maps a MySQL trx isolation level code to the InnoDB isolation level code */
+inline
+ulint
+innobase_map_isolation_level(
+/*=========================*/
+ /* out: InnoDB isolation level */
+ enum_tx_isolation iso) /* in: MySQL isolation level code */
+{
+ switch(iso) {
+ case ISO_READ_COMMITTED: return(TRX_ISO_READ_COMMITTED);
+ case ISO_REPEATABLE_READ: return(TRX_ISO_REPEATABLE_READ);
+ case ISO_SERIALIZABLE: return(TRX_ISO_SERIALIZABLE);
+ case ISO_READ_UNCOMMITTED: return(TRX_ISO_READ_UNCOMMITTED);
+ default: ut_a(0); return(0);
+ }
+}
+
+/**********************************************************************
As MySQL will execute an external lock for every new table it uses when it
starts to process an SQL statement (an exception is when MySQL calls
start_stmt for the handle) we can use this function to store the pointer to
@@ -3703,6 +3809,7 @@ ha_innobase::external_lock(
trx_t* trx;
DBUG_ENTER("ha_innobase::external_lock");
+ DBUG_PRINT("enter",("lock_type: %d", lock_type));
update_thd(thd);
@@ -3727,8 +3834,15 @@ ha_innobase::external_lock(
thd->transaction.all.innodb_active_trans = 1;
trx->n_mysql_tables_in_use++;
+ prebuilt->mysql_has_locked = TRUE;
- if (thd->variables.tx_isolation == ISO_SERIALIZABLE
+ if (thd->variables.tx_isolation != ISO_REPEATABLE_READ) {
+ trx->isolation_level = innobase_map_isolation_level(
+ (enum_tx_isolation)
+ thd->variables.tx_isolation);
+ }
+
+ if (trx->isolation_level == TRX_ISO_SERIALIZABLE
&& prebuilt->select_lock_type == LOCK_NONE) {
/* To get serializable execution we let InnoDB
@@ -3744,6 +3858,7 @@ ha_innobase::external_lock(
}
} else {
trx->n_mysql_tables_in_use--;
+ prebuilt->mysql_has_locked = FALSE;
auto_inc_counter_for_this_stat = 0;
if (trx->n_mysql_tables_in_use == 0) {
@@ -3755,6 +3870,15 @@ ha_innobase::external_lock(
innobase_release_stat_resources(trx);
+ if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
+ && trx->read_view) {
+
+ /* At low transaction isolation levels we let
+ each consistent read set its own snapshot */
+
+ read_view_close_for_mysql(trx);
+ }
+
if (!(thd->options
& (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
@@ -3779,14 +3903,13 @@ innodb_show_status(
char* buf;
DBUG_ENTER("innodb_show_status");
-
+
if (innodb_skip) {
-
- fprintf(stderr,
- "Cannot call SHOW INNODB STATUS because skip-innodb is defined\n");
-
- DBUG_RETURN(-1);
- }
+ my_message(ER_NOT_SUPPORTED_YET,
+ "Cannot call SHOW INNODB STATUS because skip-innodb is defined",
+ MYF(0));
+ DBUG_RETURN(-1);
+ }
/* We let the InnoDB Monitor to output at most 100 kB of text, add
a safety margin of 10 kB for buffer overruns */
diff --git a/sql/ha_innodb.h b/sql/ha_innodb.h
index 357fb31b5e3..d2639f39c5b 100644
--- a/sql/ha_innodb.h
+++ b/sql/ha_innodb.h
@@ -96,7 +96,7 @@ class ha_innobase: public handler
ulong index_flags(uint idx) const
{
return (HA_READ_NEXT | HA_READ_PREV | HA_READ_ORDER |
- HA_KEY_READ_ONLY | HA_NOT_READ_PREFIX_LAST);
+ HA_KEY_READ_ONLY);
}
uint max_record_length() const { return HA_MAX_REC_LENGTH; }
uint max_keys() const { return MAX_KEY; }
diff --git a/sql/ha_isam.cc b/sql/ha_isam.cc
index 052e6a4b9ec..6fa54d18aac 100644
--- a/sql/ha_isam.cc
+++ b/sql/ha_isam.cc
@@ -380,7 +380,8 @@ int ha_isam::create(const char *name, register TABLE *form,
}
recinfo_pos->base.type= (int) FIELD_LAST; /* End of fieldinfo */
error=nisam_create(fn_format(buff,name,"","",2+4+16),form->keys,keydef,
- recinfo,form->max_rows,form->min_rows,0,0,0L);
+ recinfo,(ulong) form->max_rows, (ulong) form->min_rows,
+ 0, 0, 0L);
my_free((gptr) recinfo,MYF(0));
DBUG_RETURN(error);
diff --git a/sql/ha_isammrg.cc b/sql/ha_isammrg.cc
index b110ffba2f9..94e394e7665 100644
--- a/sql/ha_isammrg.cc
+++ b/sql/ha_isammrg.cc
@@ -190,13 +190,15 @@ THR_LOCK_DATA **ha_isammrg::store_lock(THD *thd,
THR_LOCK_DATA **to,
enum thr_lock_type lock_type)
{
- MRG_TABLE *table;
+ MRG_TABLE *open_table;
- for (table=file->open_tables ; table != file->end_table ; table++)
+ for (open_table=file->open_tables ;
+ open_table != file->end_table ;
+ open_table++)
{
- *(to++)= &table->table->lock;
- if (lock_type != TL_IGNORE && table->table->lock.type == TL_UNLOCK)
- table->table->lock.type=lock_type;
+ *(to++)= &open_table->table->lock;
+ if (lock_type != TL_IGNORE && open_table->table->lock.type == TL_UNLOCK)
+ open_table->table->lock.type=lock_type;
}
return to;
}
diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc
index c7f0ccf69ee..ae71e362875 100644
--- a/sql/ha_myisam.cc
+++ b/sql/ha_myisam.cc
@@ -576,7 +576,6 @@ int ha_myisam::repair(THD *thd, MI_CHECK &param, bool optimize)
}
if (!optimize ||
- //memcmp(file->state, & share->state.state, sizeof(MI_STATUS_INFO)) ||
((file->state->del || share->state.split != file->state->records) &&
(!(param.testflag & T_QUICK) ||
!(share->state.changed & STATE_NOT_OPTIMIZED_KEYS))))
@@ -635,7 +634,12 @@ int ha_myisam::repair(THD *thd, MI_CHECK &param, bool optimize)
STATE_CRASHED_ON_REPAIR);
file->update|=HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
}
- //file->save_state=file->s->state.state;
+ /*
+ the following 'if', thought conceptually wrong,
+ is a useful optimization nevertheless.
+ */
+ if (file->state != &file->s->state.state);
+ file->s->state.state = *file->state;
if (file->s->base.auto_key)
update_auto_increment_key(&param, file, 1);
if (optimize_done)
@@ -914,7 +918,7 @@ void ha_myisam::info(uint flag)
if (table->key_parts)
memcpy((char*) table->key_info[0].rec_per_key,
(char*) info.rec_per_key,
- sizeof(ulong)*table->key_parts);
+ sizeof(table->key_info[0].rec_per_key)*table->key_parts);
raid_type=info.raid_type;
raid_chunks=info.raid_chunks;
raid_chunksize=info.raid_chunksize;
@@ -1014,7 +1018,7 @@ void ha_myisam::update_create_info(HA_CREATE_INFO *create_info)
}
-int ha_myisam::create(const char *name, register TABLE *table,
+int ha_myisam::create(const char *name, register TABLE *table_arg,
HA_CREATE_INFO *info)
{
int error;
@@ -1026,20 +1030,20 @@ int ha_myisam::create(const char *name, register TABLE *table,
MI_KEYDEF *keydef;
MI_COLUMNDEF *recinfo,*recinfo_pos;
HA_KEYSEG *keyseg;
- uint options=table->db_options_in_use;
+ uint options=table_arg->db_options_in_use;
DBUG_ENTER("ha_myisam::create");
type=HA_KEYTYPE_BINARY; // Keep compiler happy
if (!(my_multi_malloc(MYF(MY_WME),
- &recinfo,(table->fields*2+2)*sizeof(MI_COLUMNDEF),
- &keydef, table->keys*sizeof(MI_KEYDEF),
+ &recinfo,(table_arg->fields*2+2)*sizeof(MI_COLUMNDEF),
+ &keydef, table_arg->keys*sizeof(MI_KEYDEF),
&keyseg,
- ((table->key_parts + table->keys) * sizeof(HA_KEYSEG)),
+ ((table_arg->key_parts + table_arg->keys) * sizeof(HA_KEYSEG)),
0)))
DBUG_RETURN(1);
- pos=table->key_info;
- for (i=0; i < table->keys ; i++, pos++)
+ pos=table_arg->key_info;
+ for (i=0; i < table_arg->keys ; i++, pos++)
{
keydef[i].flag= (pos->flags & (HA_NOSAME | HA_FULLTEXT | HA_SPATIAL));
keydef[i].key_alg=pos->algorithm == HA_KEY_ALG_UNDEF ?
@@ -1084,7 +1088,7 @@ int ha_myisam::create(const char *name, register TABLE *table,
{
keydef[i].seg[j].null_bit=field->null_bit;
keydef[i].seg[j].null_pos= (uint) (field->null_ptr-
- (uchar*) table->record[0]);
+ (uchar*) table_arg->record[0]);
}
else
{
@@ -1102,19 +1106,19 @@ int ha_myisam::create(const char *name, register TABLE *table,
keydef[i].seg[j].flag|=HA_BLOB_PART;
/* save number of bytes used to pack length */
keydef[i].seg[j].bit_start= (uint) (field->pack_length() -
- table->blob_ptr_size);
+ table_arg->blob_ptr_size);
}
}
keyseg+=pos->key_parts;
}
recpos=0; recinfo_pos=recinfo;
- while (recpos < (uint) table->reclength)
+ while (recpos < (uint) table_arg->reclength)
{
Field **field,*found=0;
- minpos=table->reclength; length=0;
+ minpos=table_arg->reclength; length=0;
- for (field=table->field ; *field ; field++)
+ for (field=table_arg->field ; *field ; field++)
{
if ((fieldpos=(*field)->offset()) >= recpos &&
fieldpos <= minpos)
@@ -1160,7 +1164,7 @@ int ha_myisam::create(const char *name, register TABLE *table,
{
recinfo_pos->null_bit=found->null_bit;
recinfo_pos->null_pos= (uint) (found->null_ptr-
- (uchar*) table->record[0]);
+ (uchar*) table_arg->record[0]);
}
else
{
@@ -1175,13 +1179,13 @@ int ha_myisam::create(const char *name, register TABLE *table,
}
MI_CREATE_INFO create_info;
bzero((char*) &create_info,sizeof(create_info));
- create_info.max_rows=table->max_rows;
- create_info.reloc_rows=table->min_rows;
+ create_info.max_rows=table_arg->max_rows;
+ create_info.reloc_rows=table_arg->min_rows;
create_info.auto_increment=(info->auto_increment_value ?
info->auto_increment_value -1 :
(ulonglong) 0);
- create_info.data_file_length= ((ulonglong) table->max_rows *
- table->avg_row_length);
+ create_info.data_file_length= ((ulonglong) table_arg->max_rows *
+ table_arg->avg_row_length);
create_info.raid_type=info->raid_type;
create_info.raid_chunks= (info->raid_chunks ? info->raid_chunks :
RAID_DEFAULT_CHUNKS);
@@ -1191,7 +1195,7 @@ int ha_myisam::create(const char *name, register TABLE *table,
create_info.index_file_name=info->index_file_name;
error=mi_create(fn_format(buff,name,"","",2+4),
- table->keys,keydef,
+ table_arg->keys,keydef,
(uint) (recinfo_pos-recinfo), recinfo,
0, (MI_UNIQUEDEF*) 0,
&create_info,
diff --git a/sql/ha_myisammrg.cc b/sql/ha_myisammrg.cc
index c35bf657445..07683dca73e 100644
--- a/sql/ha_myisammrg.cc
+++ b/sql/ha_myisammrg.cc
@@ -187,6 +187,19 @@ void ha_myisammrg::position(const byte *record)
ha_store_ptr(ref, ref_length, (my_off_t) position);
}
+ha_rows ha_myisammrg::records_in_range(int inx,
+ const byte *start_key,uint start_key_len,
+ enum ha_rkey_function start_search_flag,
+ const byte *end_key,uint end_key_len,
+ enum ha_rkey_function end_search_flag)
+{
+ return (ha_rows) myrg_records_in_range(file,
+ inx,
+ start_key,start_key_len,
+ start_search_flag,
+ end_key,end_key_len,
+ end_search_flag);
+}
void ha_myisammrg::info(uint flag)
{
@@ -262,13 +275,15 @@ THR_LOCK_DATA **ha_myisammrg::store_lock(THD *thd,
THR_LOCK_DATA **to,
enum thr_lock_type lock_type)
{
- MYRG_TABLE *table;
+ MYRG_TABLE *open_table;
- for (table=file->open_tables ; table != file->end_table ; table++)
+ for (open_table=file->open_tables ;
+ open_table != file->end_table ;
+ open_table++)
{
- *(to++)= &table->table->lock;
- if (lock_type != TL_IGNORE && table->table->lock.type == TL_UNLOCK)
- table->table->lock.type=lock_type;
+ *(to++)= &open_table->table->lock;
+ if (lock_type != TL_IGNORE && open_table->table->lock.type == TL_UNLOCK)
+ open_table->table->lock.type=lock_type;
}
return to;
}
@@ -279,14 +294,16 @@ void ha_myisammrg::update_create_info(HA_CREATE_INFO *create_info)
DBUG_ENTER("ha_myisammrg::update_create_info");
if (!(create_info->used_fields & HA_CREATE_USED_UNION))
{
- MYRG_TABLE *table;
+ MYRG_TABLE *open_table;
THD *thd=current_thd;
create_info->merge_list.next= &create_info->merge_list.first;
create_info->merge_list.elements=0;
- for (table=file->open_tables ; table != file->end_table ; table++)
+ for (open_table=file->open_tables ;
+ open_table != file->end_table ;
+ open_table++)
{
- char *name=table->table->filename;
+ char *name=open_table->table->filename;
char buff[FN_REFLEN];
TABLE_LIST *ptr;
if (!(ptr = (TABLE_LIST *) thd->calloc(sizeof(TABLE_LIST))))
@@ -323,7 +340,28 @@ int ha_myisammrg::create(const char *name, register TABLE *form,
sizeof(char*))))
DBUG_RETURN(1);
for (pos=table_names ; tables ; tables=tables->next)
- *pos++= tables->real_name;
+ {
+ char *table_name;
+ if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
+ {
+ TABLE **tbl=find_temporary_table(current_thd,
+ tables->db, tables->real_name);
+ if (!tbl)
+ {
+ table_name=sql_alloc(1+
+ my_snprintf(buff,FN_REFLEN,"%s/%s/%s",mysql_real_data_home,
+ tables->db, tables->real_name));
+ if (!table_name)
+ DBUG_RETURN(1);
+ strcpy(table_name, buff);
+ }
+ else
+ table_name=(*tbl)->path;
+ }
+ else
+ table_name=tables->real_name;
+ *pos++= table_name;
+ }
*pos=0;
DBUG_RETURN(myrg_create(fn_format(buff,name,"","",2+4+16),
(const char **) table_names,
@@ -340,13 +378,15 @@ void ha_myisammrg::append_create_info(String *packet)
packet->append(get_type(&merge_insert_method,file->merge_insert_method-1));
}
packet->append(" UNION=(",8);
- MYRG_TABLE *table,*first;
+ MYRG_TABLE *open_table,*first;
- for (first=table=file->open_tables ; table != file->end_table ; table++)
+ for (first=open_table=file->open_tables ;
+ open_table != file->end_table ;
+ open_table++)
{
- char *name=table->table->filename;
+ char *name= open_table->table->filename;
fn_format(buff,name,"","",3);
- if (table != first)
+ if (open_table != first)
packet->append(',');
packet->append(buff,(uint) strlen(buff));
}
diff --git a/sql/ha_myisammrg.h b/sql/ha_myisammrg.h
index b75d5360097..8e33b99e418 100644
--- a/sql/ha_myisammrg.h
+++ b/sql/ha_myisammrg.h
@@ -69,6 +69,11 @@ class ha_myisammrg: public handler
int rnd_next(byte *buf);
int rnd_pos(byte * buf, byte *pos);
void position(const byte *record);
+ ha_rows ha_myisammrg::records_in_range(int inx,
+ const byte *start_key,uint start_key_len,
+ enum ha_rkey_function start_search_flag,
+ const byte *end_key,uint end_key_len,
+ enum ha_rkey_function end_search_flag);
my_off_t row_position() { return myrg_position(file); }
void info(uint);
int extra(enum ha_extra_function operation);
diff --git a/sql/handler.cc b/sql/handler.cc
index f60c3449075..b2cf86a6abc 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -294,7 +294,8 @@ int ha_commit_trans(THD *thd, THD_TRANS* trans)
error=1;
}
else
- transaction_commited= 1;
+ if (!(thd->options & OPTION_BEGIN))
+ transaction_commited= 1;
trans->bdb_tid=0;
}
#endif
diff --git a/sql/handler.h b/sql/handler.h
index fbc27f4729b..6cbd83af282 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -153,7 +153,6 @@ typedef struct st_ha_create_information
CHARSET_INFO *table_charset;
char *comment,*password;
char *data_file_name, *index_file_name;
- char *create_statement;
ulonglong max_rows,min_rows;
ulonglong auto_increment_value;
ulong table_options;
@@ -230,7 +229,7 @@ public:
void change_table_ptr(TABLE *table_arg) { table=table_arg; }
virtual double scan_time()
{ return ulonglong2double(data_file_length) / IO_SIZE + 1; }
- virtual double read_time(ha_rows rows) { return rows; }
+ virtual double read_time(ha_rows rows) { return rows2double(rows); }
virtual bool fast_key_read() { return 0;}
virtual key_map keys_to_use_for_scanning() { return 0; }
virtual bool has_transactions(){ return 0;}
diff --git a/sql/hash_filo.h b/sql/hash_filo.h
index 4d746d9b9bd..f7384cc6e32 100644
--- a/sql/hash_filo.h
+++ b/sql/hash_filo.h
@@ -40,7 +40,7 @@ class hash_filo
{
const uint size, key_offset, key_length;
const hash_get_key get_key;
- void (*free_element)(void*);
+ hash_free_key free_element;
bool init;
hash_filo_element *first_link,*last_link;
@@ -49,7 +49,7 @@ public:
HASH cache;
hash_filo(uint size_arg, uint key_offset_arg , uint key_length_arg,
- hash_get_key get_key_arg,void (*free_element_arg)(void*))
+ hash_get_key get_key_arg, hash_free_key free_element_arg)
:size(size_arg), key_offset(key_offset_arg), key_length(key_length_arg),
get_key(get_key_arg), free_element(free_element_arg),init(0)
{
diff --git a/sql/hostname.cc b/sql/hostname.cc
index 3da752f3b64..609532a67d6 100644
--- a/sql/hostname.cc
+++ b/sql/hostname.cc
@@ -63,7 +63,7 @@ bool hostname_cache_init()
if (!(hostname_cache=new hash_filo(HOST_CACHE_SIZE, offset,
sizeof(struct in_addr),NULL,
- (void (*)(void*)) free)))
+ (hash_free_key) free)))
return 1;
hostname_cache->clear();
return 0;
diff --git a/sql/item.h b/sql/item.h
index c67c16c50ad..5eeaa22a2a2 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -89,8 +89,8 @@ public:
virtual CHARSET_INFO *charset() const { return str_value.charset(); };
virtual bool binary() const { return str_value.charset()->state & MY_CS_BINSORT ? 1 : 0 ; }
virtual void set_charset(CHARSET_INFO *cs) { str_value.set_charset(cs); }
-
virtual bool check_loop(uint id);
+ virtual void top_level_item() {}
};
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 74eb5734ecf..1065c8cf023 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -27,8 +27,8 @@
/*
Test functions
- These returns 0LL if false and 1LL if true and null if some arg is null
- 'AND' and 'OR' never return null
+ Most of these returns 0LL if false and 1LL if true and
+ NULL if some arg is NULL.
*/
longlong Item_func_not::val_int()
@@ -362,13 +362,19 @@ void Item_func_between::fix_length_and_dec()
*/
if (!args[0] || !args[1] || !args[2])
return;
- cmp_type=args[0]->result_type();
- if (args[0]->binary())
+ cmp_type=item_cmp_type(args[0]->result_type(),
+ item_cmp_type(args[1]->result_type(),
+ args[2]->result_type()));
+ if (args[0]->binary() | args[1]->binary() | args[2]->binary())
string_compare=stringcmp;
else
string_compare=sortcmp;
- // Make a special case of compare with fields to get nicer DATE comparisons
+ /*
+ Make a special case of compare with date/time and longlong fields.
+ They are compared as integers, so for const item this time-consuming
+ conversion can be done only once, not for every single comparison
+ */
if (args[0]->type() == FIELD_ITEM)
{
Field *field=((Item_field*) args[0])->field;
@@ -1141,6 +1147,8 @@ Item_cond::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
#endif
item= *li.ref(); // new current item
}
+ if (abort_on_null)
+ item->top_level_item();
if (item->fix_fields(thd, tables, li.ref()))
return 1; /* purecov: inspected */
used_tables_cache|=item->used_tables();
@@ -1230,28 +1238,41 @@ void Item_cond::print(String *str)
str->append(')');
}
+/*
+ Evalution of AND(expr, expr, expr ...)
+
+ NOTES:
+ abort_if_null is set for AND expressions for which we don't care if the
+ result is NULL or 0. This is set for:
+ - WHERE clause
+ - HAVING clause
+ - IF(expression)
+
+ RETURN VALUES
+ 1 If all expressions are true
+ 0 If all expressions are false or if we find a NULL expression and
+ 'abort_on_null' is set.
+ NULL if all expression are either 1 or NULL
+*/
+
longlong Item_cond_and::val_int()
{
List_iterator_fast<Item> li(list);
Item *item;
+ null_value= 0;
while ((item=li++))
{
if (item->val_int() == 0)
{
- /*
- TODO: In case of NULL, ANSI would require us to continue evaluation
- until we get a FALSE value or run out of values; This would
- require a lot of unnecessary evaluation, which we skip for now
- */
- null_value=item->null_value;
- return 0;
+ if (abort_on_null || !(null_value= item->null_value))
+ return 0; // return FALSE
}
}
- null_value=0;
- return 1;
+ return null_value ? 0 : 1;
}
+
longlong Item_cond_or::val_int()
{
List_iterator_fast<Item> li(list);
@@ -1270,6 +1291,45 @@ longlong Item_cond_or::val_int()
return 0;
}
+/*
+ Create an AND expression from two expressions
+
+ SYNOPSIS
+ and_expressions()
+ a expression or NULL
+ b expression.
+ org_item Don't modify a if a == *org_item
+ If a == NULL, org_item is set to point at b,
+ to ensure that future calls will not modify b.
+
+ NOTES
+ This will not modify item pointed to by org_item or b
+ The idea is that one can call this in a loop and create and
+ 'and' over all items without modifying any of the original items.
+
+ RETURN
+ NULL Error
+ Item
+*/
+
+Item *and_expressions(Item *a, Item *b, Item **org_item)
+{
+ if (!a)
+ return (*org_item= b);
+ if (a == *org_item)
+ {
+ Item_cond *res;
+ if ((res= new Item_cond_and(a, b)))
+ res->used_tables_cache= a->used_tables() | b->used_tables();
+ return res;
+ }
+ if (((Item_cond_and*) a)->add(b))
+ return 0;
+ ((Item_cond_and*) a)->used_tables_cache|= b->used_tables();
+ return a;
+}
+
+
longlong Item_func_isnull::val_int()
{
/*
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 489d54ae786..a9dc6c87f95 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -213,6 +213,11 @@ public:
longlong val_int();
String *val_str(String *str);
enum Item_result result_type () const { return cached_result_type; }
+ bool fix_fields(THD *thd,struct st_table_list *tlist)
+ {
+ args[0]->top_level_item();
+ return Item_func::fix_fields(thd,tlist);
+ }
void fix_length_and_dec();
const char *func_name() const { return "if"; }
};
@@ -286,9 +291,9 @@ public:
virtual void set(uint pos,Item *item)=0;
virtual byte *get_value(Item *item)=0;
void sort()
- {
- qsort(base,used_count,size,compare);
- }
+ {
+ qsort(base,used_count,size,compare);
+ }
int find(Item *item);
};
@@ -557,10 +562,12 @@ class Item_cond :public Item_bool_func
{
protected:
List<Item> list;
+ bool abort_on_null;
public:
- Item_cond() : Item_bool_func() { const_item_cache=0; }
- Item_cond(Item *i1,Item *i2) :Item_bool_func()
- { list.push_back(i1); list.push_back(i2); }
+ /* Item_cond() is only used to create top level items */
+ Item_cond() : Item_bool_func(), abort_on_null(1) { const_item_cache=0; }
+ Item_cond(Item *i1,Item *i2) :Item_bool_func(), abort_on_null(0)
+ { list.push_back(i1); list.push_back(i2); }
~Item_cond() { list.delete_elements(); }
bool add(Item *item) { return list.push_back(item); }
bool fix_fields(THD *, struct st_table_list *, Item **ref);
@@ -573,6 +580,7 @@ public:
void split_sum_func(List<Item> &fields);
friend int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds);
bool check_loop(uint id);
+ void top_level_item() { abort_on_null=1; }
};
@@ -620,6 +628,7 @@ inline Item *and_conds(Item *a,Item *b)
return cond;
}
+Item *and_expressions(Item *a, Item *b, Item **org_item);
/**************************************************************
Spatial relations
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 4c7985cd1bf..75260065be6 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -787,13 +787,14 @@ double Item_func_rand::val()
}
else if (!thd->rand_used)
{
- // no need to send a Rand log event if seed was given eg: RAND(seed),
- // as it will be replicated in the query as such.
-
- // save the seed only the first time RAND() is used in the query
+ /*
+ No need to send a Rand log event if seed was given eg: RAND(seed),
+ as it will be replicated in the query as such.
- // once events are forwarded rather than recreated,
- // the following can be skipped if inside the slave thread
+ Save the seed only the first time RAND() is used in the query
+ Once events are forwarded rather than recreated,
+ the following can be skipped if inside the slave thread
+ */
thd->rand_used=1;
thd->rand_saved_seed1=thd->rand.seed1;
thd->rand_saved_seed2=thd->rand.seed2;
@@ -1606,7 +1607,7 @@ void item_user_lock_release(ULL *ull)
tmp.copy(command, strlen(command), tmp.charset());
tmp.append(ull->key,ull->key_length);
tmp.append("\")");
- Query_log_event qev(current_thd,tmp.ptr(), tmp.length());
+ Query_log_event qev(current_thd, tmp.ptr(), tmp.length(),1);
qev.error_code=0; // this query is always safe to run on slave
mysql_bin_log.write(&qev);
}
@@ -2051,13 +2052,13 @@ void Item_func_set_user_var::print(String *str)
user_var_entry *Item_func_get_user_var::get_entry()
{
- if (!entry || ! entry->value)
+ if (!var_entry || ! var_entry->value)
{
null_value=1;
return 0;
}
null_value=0;
- return entry;
+ return var_entry;
}
@@ -2126,8 +2127,8 @@ void Item_func_get_user_var::fix_length_and_dec()
maybe_null=1;
decimals=NOT_FIXED_DEC;
max_length=MAX_BLOB_WIDTH;
- if ((entry= get_variable(&thd->user_vars, name, 0)))
- const_var_flag= thd->query_id != entry->update_query_id;
+ if ((var_entry= get_variable(&thd->user_vars, name, 0)))
+ const_var_flag= thd->query_id != var_entry->update_query_id;
}
@@ -2317,18 +2318,18 @@ bool Item_func_match::fix_index()
{
List_iterator_fast<Item> li(fields);
Item_field *item;
- uint ft_to_key[MAX_KEY], ft_cnt[MAX_KEY], fts=0, key;
+ uint ft_to_key[MAX_KEY], ft_cnt[MAX_KEY], fts=0, keynr;
uint max_cnt=0, mkeys=0;
- if (this->key == NO_SUCH_KEY)
+ if (key == NO_SUCH_KEY)
return 0;
- for (key=0 ; key<table->keys ; key++)
+ for (keynr=0 ; keynr < table->keys ; keynr++)
{
- if ((table->key_info[key].flags & HA_FULLTEXT) &&
- (table->keys_in_use_for_query & (((key_map)1) << key)))
+ if ((table->key_info[keynr].flags & HA_FULLTEXT) &&
+ (table->keys_in_use_for_query & (((key_map)1) << keynr)))
{
- ft_to_key[fts]=key;
+ ft_to_key[fts]=keynr;
ft_cnt[fts]=0;
fts++;
}
@@ -2339,45 +2340,45 @@ bool Item_func_match::fix_index()
while ((item=(Item_field*)(li++)))
{
- for (key=0 ; key<fts ; key++)
+ for (keynr=0 ; keynr < fts ; keynr++)
{
- KEY *ft_key=&table->key_info[ft_to_key[key]];
+ KEY *ft_key=&table->key_info[ft_to_key[keynr]];
uint key_parts=ft_key->key_parts;
for (uint part=0 ; part < key_parts ; part++)
{
if (item->field->eq(ft_key->key_part[part].field))
- ft_cnt[key]++;
+ ft_cnt[keynr]++;
}
}
}
- for (key=0 ; key<fts ; key++)
+ for (keynr=0 ; keynr < fts ; keynr++)
{
- if (ft_cnt[key] > max_cnt)
+ if (ft_cnt[keynr] > max_cnt)
{
mkeys=0;
- max_cnt=ft_cnt[mkeys]=ft_cnt[key];
- ft_to_key[mkeys]=ft_to_key[key];
+ max_cnt=ft_cnt[mkeys]=ft_cnt[keynr];
+ ft_to_key[mkeys]=ft_to_key[keynr];
continue;
}
- if (max_cnt && ft_cnt[key] == max_cnt)
+ if (max_cnt && ft_cnt[keynr] == max_cnt)
{
mkeys++;
- ft_cnt[mkeys]=ft_cnt[key];
- ft_to_key[mkeys]=ft_to_key[key];
+ ft_cnt[mkeys]=ft_cnt[keynr];
+ ft_to_key[mkeys]=ft_to_key[keynr];
continue;
}
}
- for (key=0 ; key<=mkeys ; key++)
+ for (keynr=0 ; keynr <= mkeys ; keynr++)
{
// for now, partial keys won't work. SerG
if (max_cnt < fields.elements ||
- max_cnt < table->key_info[ft_to_key[key]].key_parts)
+ max_cnt < table->key_info[ft_to_key[keynr]].key_parts)
continue;
- this->key=ft_to_key[key];
+ key=ft_to_key[keynr];
return 0;
}
@@ -2385,7 +2386,7 @@ bool Item_func_match::fix_index()
err:
if (mode == FT_BOOL)
{
- this->key=NO_SUCH_KEY;
+ key=NO_SUCH_KEY;
return 0;
}
my_printf_error(ER_FT_MATCHING_KEY_NOT_FOUND,
diff --git a/sql/item_func.h b/sql/item_func.h
index 8996919e284..b659a6d69d2 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -918,7 +918,7 @@ public:
class Item_func_get_user_var :public Item_func
{
LEX_STRING name;
- user_var_entry *entry;
+ user_var_entry *var_entry;
bool const_var_flag;
public:
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index cec83428e24..7c085a1b25a 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -198,15 +198,28 @@ longlong Item_func_second::val_int()
}
-// Returns the week of year in the range of 0 - 53
+/*
+ Returns the week of year.
+
+ The bits in week_format has the following meaning:
+ 0 If not set: USA format: Sunday is first day of week
+ If set: ISO format: Monday is first day of week
+ 1 If not set: Week is in range 0-53
+ If set Week is in range 1-53.
+*/
longlong Item_func_week::val_int()
{
uint year;
+ uint week_format;
TIME ltime;
if (get_arg0_date(&ltime,0))
return 0;
- return (longlong) calc_week(&ltime, 0, args[1]->val_int() == 0, &year);
+ week_format= (uint) args[1]->val_int();
+ return (longlong) calc_week(&ltime,
+ (week_format & 2) != 0,
+ (week_format & 1) == 0,
+ &year);
}
@@ -216,7 +229,7 @@ longlong Item_func_yearweek::val_int()
TIME ltime;
if (get_arg0_date(&ltime,0))
return 0;
- week=calc_week(&ltime, 1, args[1]->val_int() == 0, &year);
+ week=calc_week(&ltime, 1, (args[1]->val_int() & 1) == 0, &year);
return week+year*100;
}
diff --git a/sql/lex.h b/sql/lex.h
index d4c64d08da4..0d0d60fe204 100644
--- a/sql/lex.h
+++ b/sql/lex.h
@@ -267,6 +267,7 @@ static SYMBOL symbols[] = {
{ "NOT", SYM(NOT),0,0},
{ "NULL", SYM(NULL_SYM),0,0},
{ "NUMERIC", SYM(NUMERIC_SYM),0,0},
+ { "OFFSET", SYM(OFFSET_SYM),0,0},
{ "ON", SYM(ON),0,0},
{ "OPEN", SYM(OPEN_SYM),0,0},
{ "OPTIMIZE", SYM(OPTIMIZE),0,0},
diff --git a/sql/lock.cc b/sql/lock.cc
index 3b2444c8e9d..74d1109b203 100644
--- a/sql/lock.cc
+++ b/sql/lock.cc
@@ -80,7 +80,7 @@ extern HASH open_cache;
static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table,uint count,
bool unlock, TABLE **write_locked);
-static int lock_external(TABLE **table,uint count);
+static int lock_external(THD *thd, TABLE **table,uint count);
static int unlock_external(THD *thd, TABLE **table,uint count);
static void print_lock_error(int error);
@@ -116,14 +116,14 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd,TABLE **tables,uint count)
}
thd->proc_info="System lock";
- if (lock_external(tables,count))
+ if (lock_external(thd, tables, count))
{
my_free((gptr) sql_lock,MYF(0));
sql_lock=0;
thd->proc_info=0;
break;
}
- thd->proc_info=0;
+ thd->proc_info="Table lock";
thd->locked=1;
if (thr_multi_lock(sql_lock->locks,sql_lock->lock_count))
{
@@ -142,6 +142,7 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd,TABLE **tables,uint count)
thd->locked=0;
break;
}
+ thd->proc_info=0;
/* some table was altered or deleted. reopen tables marked deleted */
mysql_unlock_tables(thd,sql_lock);
@@ -151,6 +152,7 @@ retry:
if (wait_for_tables(thd))
break; // Couldn't open tables
}
+ thd->proc_info=0;
if (thd->killed)
{
my_error(ER_SERVER_SHUTDOWN,MYF(0));
@@ -166,15 +168,15 @@ retry:
}
-static int lock_external(TABLE **tables,uint count)
+static int lock_external(THD *thd, TABLE **tables, uint count)
{
reg1 uint i;
int lock_type,error;
- THD *thd=current_thd;
DBUG_ENTER("lock_external");
for (i=1 ; i <= count ; i++, tables++)
{
+ DBUG_ASSERT((*tables)->reginfo.lock_type >= TL_READ);
lock_type=F_WRLCK; /* Lock exclusive */
if ((*tables)->db_stat & HA_READ_ONLY ||
((*tables)->reginfo.lock_type >= TL_READ &&
diff --git a/sql/log.cc b/sql/log.cc
index 286dba3f79b..0e1af8e5dae 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -1026,9 +1026,13 @@ bool MYSQL_LOG::write(THD *thd,enum enum_server_command command,
bool MYSQL_LOG::write(Log_event* event_info)
{
bool error=0;
+ DBUG_ENTER("MYSQL_LOG::write(event)");
if (!inited) // Can't use mutex if not init
- return 0;
+ {
+ DBUG_PRINT("error",("not initied"));
+ DBUG_RETURN(0);
+ }
pthread_mutex_lock(&LOCK_log);
/* In most cases this is only called if 'is_open()' is true */
@@ -1036,7 +1040,7 @@ bool MYSQL_LOG::write(Log_event* event_info)
{
bool should_rotate = 0;
THD *thd=event_info->thd;
- const char* db = event_info->get_db();
+ const char *local_db = event_info->get_db();
#ifdef USING_TRANSACTIONS
IO_CACHE *file = ((event_info->get_cache_stmt()) ?
&thd->transaction.trans_log :
@@ -1046,10 +1050,11 @@ bool MYSQL_LOG::write(Log_event* event_info)
#endif
if ((thd && !(thd->options & OPTION_BIN_LOG) &&
(thd->master_access & SUPER_ACL)) ||
- (db && !db_ok(db, binlog_do_db, binlog_ignore_db)))
+ (local_db && !db_ok(local_db, binlog_do_db, binlog_ignore_db)))
{
VOID(pthread_mutex_unlock(&LOCK_log));
- return 0;
+ DBUG_PRINT("error",("!db_ok"));
+ DBUG_RETURN(0);
}
error=1;
@@ -1087,7 +1092,7 @@ bool MYSQL_LOG::write(Log_event* event_info)
char buf[1024] = "SET CHARACTER SET ";
char* p = strend(buf);
p = strmov(p, thd->variables.convert_set->name);
- Query_log_event e(thd, buf, (ulong)(p - buf));
+ Query_log_event e(thd, buf, (ulong)(p - buf), 0);
e.set_log_pos(this);
if (e.write(file))
goto err;
@@ -1135,7 +1140,7 @@ err:
}
pthread_mutex_unlock(&LOCK_log);
- return error;
+ DBUG_RETURN(error);
}
@@ -1165,6 +1170,7 @@ uint MYSQL_LOG::next_file_id()
bool MYSQL_LOG::write(THD *thd, IO_CACHE *cache)
{
VOID(pthread_mutex_lock(&LOCK_log));
+ DBUG_ENTER("MYSQL_LOG::write(cache");
if (is_open()) // Should always be true
{
@@ -1223,7 +1229,7 @@ bool MYSQL_LOG::write(THD *thd, IO_CACHE *cache)
signal_update();
}
VOID(pthread_mutex_unlock(&LOCK_log));
- return 0;
+ DBUG_RETURN(0);
err:
if (!write_error)
@@ -1232,7 +1238,7 @@ err:
sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno);
}
VOID(pthread_mutex_unlock(&LOCK_log));
- return 1;
+ DBUG_RETURN(1);
}
@@ -1242,7 +1248,7 @@ err:
*/
bool MYSQL_LOG::write(THD *thd,const char *query, uint query_length,
- time_t query_start)
+ time_t query_start_arg)
{
bool error=0;
if (is_open())
@@ -1260,7 +1266,7 @@ bool MYSQL_LOG::write(THD *thd,const char *query, uint query_length,
VOID(pthread_mutex_unlock(&LOCK_log));
return 0;
}
- if ((specialflag & SPECIAL_LONG_LOG_FORMAT) || query_start)
+ if ((specialflag & SPECIAL_LONG_LOG_FORMAT) || query_start_arg)
{
current_time=time(NULL);
if (current_time != last_time)
@@ -1288,13 +1294,13 @@ bool MYSQL_LOG::write(THD *thd,const char *query, uint query_length,
thd->ip ? thd->ip : "") == (uint) -1)
tmp_errno=errno;
}
- if (query_start)
+ if (query_start_arg)
{
/* For slow query log */
if (my_b_printf(&log_file,
"# Query_time: %lu Lock_time: %lu Rows_sent: %lu Rows_examined: %lu\n",
- (ulong) (current_time - query_start),
- (ulong) (thd->time_after_lock - query_start),
+ (ulong) (current_time - query_start_arg),
+ (ulong) (thd->time_after_lock - query_start_arg),
(ulong) thd->sent_row_count,
(ulong) thd->examined_row_count) == (uint) -1)
tmp_errno=errno;
@@ -1321,11 +1327,11 @@ bool MYSQL_LOG::write(THD *thd,const char *query, uint query_length,
}
if (thd->query_start_used)
{
- if (query_start != thd->query_start())
+ if (query_start_arg != thd->query_start())
{
- query_start=thd->query_start();
+ query_start_arg=thd->query_start();
end=strmov(end,",timestamp=");
- end=int10_to_str((long) query_start,end,10);
+ end=int10_to_str((long) query_start_arg,end,10);
}
}
if (end != buff)
diff --git a/sql/log_event.cc b/sql/log_event.cc
index c168c951c8f..3747af22922 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -235,22 +235,25 @@ const char* Log_event::get_type_str()
****************************************************************************/
#ifndef MYSQL_CLIENT
-Log_event::Log_event(THD* thd_arg, uint16 flags_arg)
- :exec_time(0), flags(flags_arg), cached_event_len(0),
- temp_buf(0), thd(thd_arg)
+Log_event::Log_event(THD* thd_arg, uint16 flags_arg, bool using_trans)
+ :temp_buf(0), exec_time(0), cached_event_len(0), flags(flags_arg),
+ thd(thd_arg)
{
- if (thd)
- {
- server_id = thd->server_id;
- when = thd->start_time;
- log_pos = thd->log_pos;
- }
- else
- {
- server_id = ::server_id;
- when = time(NULL);
- log_pos =0;
- }
+ server_id= thd->server_id;
+ when= thd->start_time;
+ log_pos= thd->log_pos;
+ cache_stmt= (using_trans &&
+ (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)));
+}
+
+
+Log_event::Log_event()
+ :temp_buf(0), exec_time(0), cached_event_len(0), flags(0), cache_stmt(0),
+ thd(0)
+{
+ server_id= ::server_id;
+ when= time(NULL);
+ log_pos= 0;
}
#endif // !MYSQL_CLIENT
@@ -260,7 +263,7 @@ Log_event::Log_event(THD* thd_arg, uint16 flags_arg)
****************************************************************************/
Log_event::Log_event(const char* buf, bool old_format)
- :cached_event_len(0), temp_buf(0)
+ :temp_buf(0), cached_event_len(0), cache_stmt(0)
{
when = uint4korr(buf);
server_id = uint4korr(buf + SERVER_ID_OFFSET);
@@ -330,11 +333,11 @@ void Log_event::init_show_field_list(List<Item>* field_list)
Only called by SHOW BINLOG EVENTS
****************************************************************************/
-int Log_event::net_send(THD* thd, const char* log_name, my_off_t pos)
+int Log_event::net_send(THD* thd_arg, const char* log_name, my_off_t pos)
{
- String* packet = &thd->packet;
- const char* p = strrchr(log_name, FN_LIBCHAR);
- const char* event_type;
+ String* packet = &thd_arg->packet;
+ const char *p= strrchr(log_name, FN_LIBCHAR);
+ const char *event_type;
if (p)
log_name = p + 1;
@@ -346,7 +349,7 @@ int Log_event::net_send(THD* thd, const char* log_name, my_off_t pos)
net_store_data(packet, server_id);
net_store_data(packet, (longlong) log_pos);
pack_info(packet);
- return my_net_write(&thd->net, (char*) packet->ptr(), packet->length());
+ return my_net_write(&thd_arg->net, (char*) packet->ptr(), packet->length());
}
#endif // !MYSQL_CLIENT
@@ -725,12 +728,10 @@ int Query_log_event::write_data(IO_CACHE* file)
#ifndef MYSQL_CLIENT
Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg,
ulong query_length, bool using_trans)
- :Log_event(thd_arg), data_buf(0), query(query_arg), db(thd_arg->db),
- q_len((uint32) query_length),
+ :Log_event(thd_arg, 0, using_trans), data_buf(0), query(query_arg),
+ db(thd_arg->db), q_len((uint32) query_length),
error_code(thd_arg->killed ? ER_SERVER_SHUTDOWN: thd_arg->net.last_errno),
- thread_id(thd_arg->thread_id),
- cache_stmt(using_trans &&
- (thd_arg->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))
+ thread_id(thd_arg->thread_id)
{
time_t end_time;
time(&end_time);
@@ -1155,18 +1156,18 @@ int Load_log_event::write_data_body(IO_CACHE* file)
****************************************************************************/
#ifndef MYSQL_CLIENT
-Load_log_event::Load_log_event(THD* thd, sql_exchange* ex,
- const char* db_arg, const char* table_name_arg,
- List<Item>& fields_arg,
+Load_log_event::Load_log_event(THD *thd_arg, sql_exchange *ex,
+ const char *db_arg, const char *table_name_arg,
+ List<Item> &fields_arg,
enum enum_duplicates handle_dup)
- :Log_event(thd),thread_id(thd->thread_id), num_fields(0),fields(0),
+ :Log_event(thd_arg),thread_id(thd_arg->thread_id), num_fields(0),fields(0),
field_lens(0),field_block_len(0),
table_name(table_name_arg ? table_name_arg : ""),
db(db_arg), fname(ex->file_name)
{
time_t end_time;
time(&end_time);
- exec_time = (ulong) (end_time - thd->start_time);
+ exec_time = (ulong) (end_time - thd_arg->start_time);
/* db can never be a zero pointer in 4.0 */
db_len = (uint32) strlen(db);
table_name_len = (uint32) strlen(table_name);
@@ -1236,11 +1237,11 @@ Load_log_event::Load_log_event(THD* thd, sql_exchange* ex,
constructed event.
****************************************************************************/
-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)
+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)
{
if (!event_len) // derived class, will call copy_log_event() itself
return;
@@ -1390,14 +1391,14 @@ void Load_log_event::print(FILE* file, bool short_form, char* last_db)
****************************************************************************/
#ifndef MYSQL_CLIENT
-void Load_log_event::set_fields(List<Item> &fields)
+void Load_log_event::set_fields(List<Item> &field_list)
{
uint i;
- const char* field = this->fields;
- for (i = 0; i < num_fields; i++)
+ const char* field = fields;
+ for (i= 0; i < num_fields; i++)
{
- fields.push_back(new Item_field(db, table_name, field));
- field += field_lens[i] + 1;
+ field_list.push_back(new Item_field(db, table_name, field));
+ field+= field_lens[i] + 1;
}
}
#endif // !MYSQL_CLIENT
@@ -1458,8 +1459,8 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli)
ex.field_term->length(0);
ex.skip_lines = skip_lines;
- List<Item> fields;
- set_fields(fields);
+ List<Item> field_list;
+ set_fields(field_list);
thd->slave_proxy_id = thd->thread_id;
if (net)
{
@@ -1470,7 +1471,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, fields, handle_dup, net != 0,
+ if (mysql_load(thd, &ex, &tables, field_list, handle_dup, net != 0,
TL_WRITE))
thd->query_error = 1;
if (thd->cuted_fields)
@@ -1795,14 +1796,12 @@ int Intvar_log_event::exec_event(struct st_relay_log_info* rli)
#ifndef MYSQL_CLIENT
void Rand_log_event::pack_info(String* packet)
{
- char buf1[256], buf[22];
- String tmp(buf1, sizeof(buf1), system_charset_info);
- tmp.length(0);
- tmp.append("randseed1=");
- tmp.append(llstr(seed1, buf));
- tmp.append(",randseed2=");
- tmp.append(llstr(seed2, buf));
- net_store_data(packet, tmp.ptr(), tmp.length());
+ char buf1[256], *pos;
+ pos= strmov(buf1,"rand_seed1=");
+ pos= int10_to_str((long) seed1, pos, 10);
+ pos= strmov(pos, ",rand_seed2=");
+ pos= int10_to_str((long) seed2, pos, 10);
+ net_store_data(packet, buf1, (uint) (pos-buf1));
}
#endif // !MYSQL_CLIENT
@@ -1846,8 +1845,8 @@ void Rand_log_event::print(FILE* file, bool short_form, char* last_db)
print_header(file);
fprintf(file, "\tRand\n");
}
- fprintf(file, "SET RAND SEED1=%s;\n", llstr(seed1, llbuff));
- fprintf(file, "SET RAND SEED2=%s;\n", llstr(seed2, llbuff));
+ fprintf(file, "SET @@RAND_SEED1=%s, @@RAND_SEED2=%s;\n",
+ llstr(seed1, llbuff),llstr(seed2, llbuff));
fflush(file);
}
#endif // MYSQL_CLIENT
@@ -1860,8 +1859,8 @@ void Rand_log_event::print(FILE* file, bool short_form, char* last_db)
#ifndef MYSQL_CLIENT
int Rand_log_event::exec_event(struct st_relay_log_info* rli)
{
- thd->rand.seed1 = seed1;
- thd->rand.seed2 = seed2;
+ thd->rand.seed1= (ulong) seed1;
+ thd->rand.seed2= (ulong) seed2;
rli->inc_pending(get_event_len());
return 0;
}
@@ -1907,8 +1906,8 @@ void Slave_log_event::pack_info(String* packet)
****************************************************************************/
#ifndef MYSQL_CLIENT
Slave_log_event::Slave_log_event(THD* thd_arg,
- struct st_relay_log_info* rli):
- Log_event(thd_arg),mem_pool(0),master_host(0)
+ struct st_relay_log_info* rli)
+ :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 ?
@@ -2120,11 +2119,13 @@ int Stop_log_event::exec_event(struct st_relay_log_info* rli)
****************************************************************************/
#ifndef MYSQL_CLIENT
-Create_file_log_event::Create_file_log_event(THD* thd_arg, sql_exchange* ex,
- const char* db_arg, const char* table_name_arg,
- List<Item>& fields_arg, enum enum_duplicates handle_dup,
- char* block_arg, uint block_len_arg)
- :Load_log_event(thd_arg,ex,db_arg,table_name_arg,fields_arg,handle_dup),
+Create_file_log_event::
+Create_file_log_event(THD* thd_arg, sql_exchange* ex,
+ const char* db_arg, const char* table_name_arg,
+ List<Item>& fields_arg, enum enum_duplicates handle_dup,
+ char* block_arg, uint block_len_arg, bool using_trans)
+ :Load_log_event(thd_arg,ex,db_arg,table_name_arg,fields_arg,handle_dup,
+ using_trans),
fake_base(0),block(block_arg),block_len(block_len_arg),
file_id(thd_arg->file_id = mysql_bin_log.next_file_id())
{
@@ -2327,9 +2328,10 @@ err:
****************************************************************************/
#ifndef MYSQL_CLIENT
Append_block_log_event::Append_block_log_event(THD* thd_arg, char* block_arg,
- uint block_len_arg)
- :Log_event(thd_arg), block(block_arg),block_len(block_len_arg),
- file_id(thd_arg->file_id)
+ uint block_len_arg,
+ bool using_trans)
+ :Log_event(thd_arg,0, using_trans), block(block_arg),
+ block_len(block_len_arg), file_id(thd_arg->file_id)
{
}
#endif // !MYSQL_CLIENT
@@ -2447,8 +2449,8 @@ err:
****************************************************************************/
#ifndef MYSQL_CLIENT
-Delete_file_log_event::Delete_file_log_event(THD* thd_arg)
- :Log_event(thd_arg),file_id(thd_arg->file_id)
+Delete_file_log_event::Delete_file_log_event(THD *thd_arg, bool using_trans)
+ :Log_event(thd_arg, 0, using_trans),file_id(thd_arg->file_id)
{
}
#endif // !MYSQL_CLIENT
@@ -2545,8 +2547,8 @@ int Delete_file_log_event::exec_event(struct st_relay_log_info* rli)
****************************************************************************/
#ifndef MYSQL_CLIENT
-Execute_load_log_event::Execute_load_log_event(THD* thd_arg)
- :Log_event(thd_arg),file_id(thd_arg->file_id)
+Execute_load_log_event::Execute_load_log_event(THD *thd_arg, bool using_trans)
+ :Log_event(thd_arg, 0, using_trans), file_id(thd_arg->file_id)
{
}
#endif // !MYSQL_CLIENT
@@ -2556,8 +2558,8 @@ Execute_load_log_event::Execute_load_log_event(THD* thd_arg)
Execute_load_log_event ctor
****************************************************************************/
-Execute_load_log_event::Execute_load_log_event(const char* buf,int len)
- :Log_event(buf, 0),file_id(0)
+Execute_load_log_event::Execute_load_log_event(const char* buf, int len)
+ :Log_event(buf, 0), file_id(0)
{
if ((uint)len < EXEC_LOAD_EVENT_OVERHEAD)
return;
diff --git a/sql/log_event.h b/sql/log_event.h
index bf04c480729..20a134ab3cc 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -247,18 +247,19 @@ struct st_relay_log_info;
class Log_event
{
public:
+ my_off_t log_pos;
+ char *temp_buf;
time_t when;
ulong exec_time;
uint32 server_id;
- my_off_t log_pos;
+ uint cached_event_len;
uint16 flags;
- int cached_event_len;
- char* temp_buf;
-
+ bool cache_stmt;
#ifndef MYSQL_CLIENT
THD* thd;
- Log_event(THD* thd_arg, uint16 flags_arg = 0);
+ Log_event(THD* thd_arg, uint16 flags_arg, bool cache_stmt);
+ Log_event();
// if mutex is 0, the read will proceed without mutex
static Log_event* read_log_event(IO_CACHE* file,
pthread_mutex_t* log_lock,
@@ -301,7 +302,7 @@ public:
{ return 0; }
virtual Log_event_type get_type_code() = 0;
virtual bool is_valid() = 0;
- virtual bool get_cache_stmt() { return 0; }
+ inline bool get_cache_stmt() { return cache_stmt; }
Log_event(const char* buf, bool old_format);
virtual ~Log_event() { free_temp_buf();}
void register_temp_buf(char* buf) { temp_buf = buf; }
@@ -350,14 +351,12 @@ public:
uint16 error_code;
ulong thread_id;
#ifndef MYSQL_CLIENT
- bool cache_stmt;
Query_log_event(THD* thd_arg, const char* query_arg, ulong query_length,
- bool using_trans=0);
+ bool using_trans);
const char* get_db() { return db; }
void pack_info(String* packet);
int exec_event(struct st_relay_log_info* rli);
- bool get_cache_stmt() { return cache_stmt; }
#else
void print(FILE* file, bool short_form = 0, char* last_db = 0);
#endif
@@ -445,14 +444,15 @@ public:
const char* fname;
uint32 skip_lines;
sql_ex_info sql_ex;
-
+
#ifndef MYSQL_CLIENT
String field_lens_buf;
String fields_buf;
Load_log_event(THD* thd, sql_exchange* ex, const char* db_arg,
const char* table_name_arg,
- List<Item>& fields_arg, enum enum_duplicates handle_dup);
+ List<Item>& fields_arg, enum enum_duplicates handle_dup,
+ bool using_trans);
void set_fields(List<Item> &fields_arg);
void pack_info(String* packet);
const char* get_db() { return db; }
@@ -468,8 +468,10 @@ public:
Load_log_event(const char* buf, int event_len, bool old_format);
~Load_log_event()
{}
- Log_event_type get_type_code() { return sql_ex.new_format() ?
- NEW_LOAD_EVENT: LOAD_EVENT; }
+ Log_event_type get_type_code()
+ {
+ return sql_ex.new_format() ? NEW_LOAD_EVENT: LOAD_EVENT;
+ }
int write_data_header(IO_CACHE* file);
int write_data_body(IO_CACHE* file);
bool is_valid() { return table_name != 0; }
@@ -500,7 +502,7 @@ public:
char server_version[ST_SERVER_VER_LEN];
#ifndef MYSQL_CLIENT
- Start_log_event() :Log_event((THD*)0),binlog_version(BINLOG_VERSION)
+ Start_log_event() :Log_event(), binlog_version(BINLOG_VERSION)
{
created = (uint32) when;
memcpy(server_version, ::server_version, ST_SERVER_VER_LEN);
@@ -538,7 +540,7 @@ public:
#ifndef MYSQL_CLIENT
Intvar_log_event(THD* thd_arg,uchar type_arg, ulonglong val_arg)
- :Log_event(thd_arg),val(val_arg),type(type_arg)
+ :Log_event(),val(val_arg),type(type_arg)
{}
void pack_info(String* packet);
int exec_event(struct st_relay_log_info* rli);
@@ -570,7 +572,7 @@ class Rand_log_event: public Log_event
#ifndef MYSQL_CLIENT
Rand_log_event(THD* thd_arg, ulonglong seed1_arg, ulonglong seed2_arg)
- :Log_event(thd_arg),seed1(seed1_arg),seed2(seed2_arg)
+ :Log_event(thd_arg,0,0),seed1(seed1_arg),seed2(seed2_arg)
{}
void pack_info(String* packet);
int exec_event(struct st_relay_log_info* rli);
@@ -596,7 +598,7 @@ class Stop_log_event: public Log_event
{
public:
#ifndef MYSQL_CLIENT
- Stop_log_event() :Log_event((THD*)0)
+ Stop_log_event() :Log_event()
{}
int exec_event(struct st_relay_log_info* rli);
#else
@@ -628,8 +630,9 @@ public:
bool alloced;
#ifndef MYSQL_CLIENT
Rotate_log_event(THD* thd_arg, const char* new_log_ident_arg,
- uint ident_len_arg = 0,ulonglong pos_arg = 4)
- : Log_event(thd_arg), new_log_ident(new_log_ident_arg),
+ uint ident_len_arg = 0,
+ ulonglong pos_arg = LOG_EVENT_OFFSET)
+ :Log_event(thd_arg,0,0), new_log_ident(new_log_ident_arg),
pos(pos_arg),ident_len(ident_len_arg ? ident_len_arg :
(uint) strlen(new_log_ident_arg)), alloced(0)
{}
@@ -678,7 +681,8 @@ public:
const char* table_name_arg,
List<Item>& fields_arg,
enum enum_duplicates handle_dup,
- char* block_arg, uint block_len_arg);
+ char* block_arg, uint block_len_arg,
+ bool using_trans);
void pack_info(String* packet);
int exec_event(struct st_relay_log_info* rli);
#else
@@ -728,7 +732,7 @@ public:
#ifndef MYSQL_CLIENT
Append_block_log_event(THD* thd, char* block_arg,
- uint block_len_arg);
+ uint block_len_arg, bool using_trans);
int exec_event(struct st_relay_log_info* rli);
void pack_info(String* packet);
#else
@@ -754,7 +758,7 @@ public:
uint file_id;
#ifndef MYSQL_CLIENT
- Delete_file_log_event(THD* thd);
+ Delete_file_log_event(THD* thd, bool using_trans);
void pack_info(String* packet);
int exec_event(struct st_relay_log_info* rli);
#else
@@ -780,7 +784,7 @@ public:
uint file_id;
#ifndef MYSQL_CLIENT
- Execute_load_log_event(THD* thd);
+ Execute_load_log_event(THD* thd, bool using_trans);
void pack_info(String* packet);
int exec_event(struct st_relay_log_info* rli);
#else
diff --git a/sql/mini_client.cc b/sql/mini_client.cc
index aa84a52eb0b..0f20587ec24 100644
--- a/sql/mini_client.cc
+++ b/sql/mini_client.cc
@@ -295,11 +295,11 @@ static int mc_sock_connect(my_socket s, const struct sockaddr *name,
FD_SET(s, &sfds);
tv.tv_sec = (long) to;
tv.tv_usec = 0;
-#ifdef HPUX
+#ifdef HPUX10
res = select(s+1, NULL, (int*) &sfds, NULL, &tv);
#else
res = select(s+1, NULL, &sfds, NULL, &tv);
-#endif
+#endif /* HPUX10 */
if (res <= 0) /* Never became writable */
return(-1);
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 392333a4971..4317ea05041 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -85,6 +85,7 @@ char* query_table_status(THD *thd,const char *db,const char *table_name);
*/
#define MIN_FILE_LENGTH_TO_USE_ROW_CACHE (16L*1024*1024)
#define MIN_ROWS_TO_USE_TABLE_CACHE 100
+#define MIN_ROWS_TO_USE_BULK_INSERT 100
/*
The following is used to decide if MySQL should use table scanning
@@ -326,9 +327,8 @@ void mysql_init_multi_delete(LEX *lex);
void init_max_user_conn(void);
void init_update_queries(void);
void free_max_user_conn(void);
-pthread_handler_decl(handle_one_connection,arg);
-pthread_handler_decl(handle_bootstrap,arg);
-sig_handler end_thread_signal(int sig);
+extern "C" pthread_handler_decl(handle_one_connection,arg);
+extern "C" pthread_handler_decl(handle_bootstrap,arg);
void end_thread(THD *thd,bool put_in_cache);
void flush_thread_cache();
void mysql_execute_command(THD *thd);
@@ -441,14 +441,12 @@ int mysql_drop_index(THD *thd, TABLE_LIST *table_list,
int mysql_update(THD *thd,TABLE_LIST *tables,List<Item> &fields,
List<Item> &values,COND *conds,
ORDER *order, ha_rows limit,
- enum enum_duplicates handle_duplicates,
- thr_lock_type lock_type);
+ enum enum_duplicates handle_duplicates);
int mysql_insert(THD *thd,TABLE_LIST *table,List<Item> &fields,
- List<List_item> &values, enum_duplicates flag,
- thr_lock_type lock_type);
+ List<List_item> &values, enum_duplicates flag);
void kill_delayed_threads(void);
int mysql_delete(THD *thd, TABLE_LIST *table, COND *conds, ORDER *order,
- ha_rows rows, thr_lock_type lock_type, ulong options);
+ ha_rows rows, ulong options);
int mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok=0);
TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type update);
TABLE *open_table(THD *thd,const char *db,const char *table,const char *alias,
@@ -543,6 +541,7 @@ bool add_field_to_list(char *field_name, enum enum_field_types type,
char *change, TYPELIB *interval,CHARSET_INFO *cs);
void store_position_for_column(const char *name);
bool add_to_list(SQL_LIST &list,Item *group,bool asc=0);
+void set_lock_for_tables(thr_lock_type lock_type);
void add_join_on(TABLE_LIST *b,Item *expr);
void add_join_natural(TABLE_LIST *a,TABLE_LIST *b);
bool add_proc_to_list(Item *item);
@@ -609,7 +608,7 @@ int write_record(TABLE *table,COPY_INFO *info);
extern ulong volatile manager_status;
extern bool volatile manager_thread_in_use, mqh_used;
extern pthread_t manager_thread;
-pthread_handler_decl(handle_manager, arg);
+extern "C" pthread_handler_decl(handle_manager, arg);
/* sql_test.cc */
#ifndef DBUG_OFF
@@ -637,6 +636,8 @@ bool open_log(MYSQL_LOG *log, const char *hostname,
const char *index_file_name,
enum_log_type type, bool read_append = 0,
bool no_auto_events = 0);
+/* mysqld.cc */
+void clear_error_message(THD *thd);
/*
External variables
@@ -762,7 +763,7 @@ bool wait_for_locked_table_names(THD *thd, TABLE_LIST *table_list);
/* old unireg functions */
void unireg_init(ulong options);
-void unireg_end(int signal);
+void unireg_end(void);
int rea_create_table(THD *thd, my_string file_name,HA_CREATE_INFO *create_info,
List<create_field> &create_field,
uint key_count,KEY *key_info);
@@ -791,7 +792,7 @@ timestamp_type str_to_TIME(const char *str, uint length, TIME *l_time,
int test_if_number(char *str,int *res,bool allow_wildcards);
void change_byte(byte *,uint,char,char);
-void unireg_abort(int exit_code);
+extern "C" void unireg_abort(int exit_code);
void init_read_record(READ_RECORD *info, THD *thd, TABLE *reg_form,
SQL_SELECT *select,
int use_record_cache, bool print_errors);
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 755998bb8ba..ebda24b404a 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -279,7 +279,7 @@ static char* pidfile_name_ptr= pidfile_name;
static pthread_t select_thread;
static my_bool opt_noacl=0, opt_bootstrap=0, opt_myisam_log=0;
my_bool opt_safe_user_create = 0, opt_no_mix_types = 0;
-my_bool opt_safe_show_db=0, lower_case_table_names, opt_old_rpl_compat;
+my_bool lower_case_table_names, opt_old_rpl_compat;
my_bool opt_show_slave_auth_info, opt_sql_bin_update = 0;
my_bool opt_log_slave_updates= 0;
@@ -349,7 +349,7 @@ volatile ulong cached_thread_count=0;
my_string master_user = (char*) "test", master_password = 0, master_host=0,
master_info_file = (char*) "master.info",
relay_log_info_file = (char*) "relay-log.info",
- master_ssl_key=0, master_ssl_cert=0;
+ master_ssl_key=0, master_ssl_cert=0, master_ssl_capath=0, master_ssl_cipher=0;
my_string report_user = 0, report_password = 0, report_host=0;
const char *localhost=LOCAL_HOST;
@@ -458,23 +458,23 @@ pthread_cond_t eventShutdown;
#endif
static void start_signal_handler(void);
-static void *signal_hand(void *arg);
+extern "C" pthread_handler_decl(signal_hand, arg);
static void set_options(void);
static void get_options(int argc,char **argv);
static char *get_relative_path(const char *path);
static void fix_paths(void);
-static pthread_handler_decl(handle_connections_sockets,arg);
-static pthread_handler_decl(kill_server_thread,arg);
+extern "C" pthread_handler_decl(handle_connections_sockets,arg);
+extern "C" pthread_handler_decl(kill_server_thread,arg);
static int bootstrap(FILE *file);
static void close_server_sock();
static bool read_init_file(char *file_name);
#ifdef __NT__
-static pthread_handler_decl(handle_connections_namedpipes,arg);
+extern "C" pthread_handler_decl(handle_connections_namedpipes,arg);
#endif
#ifdef HAVE_SMEM
static pthread_handler_decl(handle_connections_shared_memory,arg);
#endif
-extern pthread_handler_decl(handle_slave,arg);
+extern "C" pthread_handler_decl(handle_slave,arg);
#ifdef SET_RLIMIT_NOFILE
static uint set_maximum_open_files(uint max_file_limit);
#endif
@@ -781,14 +781,14 @@ static void __cdecl kill_server(int sig_ptr)
if (sig != MYSQL_KILL_SIGNAL && sig != 0)
unireg_abort(1); /* purecov: inspected */
else
- unireg_end(0);
+ unireg_end();
pthread_exit(0); /* purecov: deadcode */
RETURN_FROM_KILL_SERVER;
}
#ifdef USE_ONE_SIGNAL_HAND
-static pthread_handler_decl(kill_server_thread,arg __attribute__((unused)))
+extern "C" pthread_handler_decl(kill_server_thread,arg __attribute__((unused)))
{
SHUTDOWN_THD;
my_thread_init(); // Initialize new thread
@@ -803,7 +803,7 @@ static pthread_handler_decl(kill_server_thread,arg __attribute__((unused)))
#define sigset signal
#endif
-static sig_handler print_signal_warning(int sig)
+extern "C" sig_handler print_signal_warning(int sig)
{
if (!DBUG_IN_USE)
{
@@ -820,16 +820,33 @@ static sig_handler print_signal_warning(int sig)
#endif
}
+/*
+ cleanup all memory and end program nicely
+
+ SYNOPSIS
+ unireg_end()
+
+ NOTES
+ This function never returns.
-void unireg_end(int signal_number __attribute__((unused)))
+ If SIGNALS_DONT_BREAK_READ is defined, this function is called
+ by the main thread. To get MySQL to shut down nicely in this case
+ (Mac OS X) we have to call exit() instead if pthread_exit().
+*/
+
+void unireg_end(void)
{
clean_up();
my_thread_end();
+#ifdef SIGNALS_DONT_BREAK_READ
+ exit(0);
+#else
pthread_exit(0); // Exit is in main thread
+#endif
}
-void unireg_abort(int exit_code)
+extern "C" void unireg_abort(int exit_code)
{
DBUG_ENTER("unireg_abort");
if (exit_code)
@@ -875,6 +892,9 @@ void clean_up(bool print_message)
bitmap_free(&temp_pool);
free_max_user_conn();
end_slave_list();
+#ifdef USE_REGEX
+ regex_end();
+#endif
#if !defined(__WIN__) && !defined(EMBEDDED_LIBRARY)
if (!opt_bootstrap)
@@ -1176,7 +1196,7 @@ void close_connection(NET *net,uint errcode,bool lock)
/* Called when a thread is aborted */
/* ARGSUSED */
-sig_handler end_thread_signal(int sig __attribute__((unused)))
+extern "C" sig_handler end_thread_signal(int sig __attribute__((unused)))
{
THD *thd=current_thd;
DBUG_ENTER("end_thread_signal");
@@ -1267,7 +1287,7 @@ void flush_thread_cache()
*/
#ifdef THREAD_SPECIFIC_SIGPIPE
-static sig_handler abort_thread(int sig __attribute__((unused)))
+extern "C" sig_handler abort_thread(int sig __attribute__((unused)))
{
THD *thd=current_thd;
DBUG_ENTER("abort_thread");
@@ -1341,7 +1361,7 @@ static void start_signal_handler(void)
#define UNSAFE_DEFAULT_LINUX_THREADS 200
#endif
-static sig_handler handle_segfault(int sig)
+extern "C" sig_handler handle_segfault(int sig)
{
THD *thd=current_thd;
/*
@@ -1418,7 +1438,11 @@ information that should help you find out what is causing the crash.\n");
#endif /* HAVE_STACKTRACE */
if (test_flags & TEST_CORE_ON_SIGNAL)
+ {
+ fprintf(stderr, "Writing a core file\n");
+ fflush(stderr);
write_core(sig);
+ }
exit(1);
}
@@ -1526,7 +1550,7 @@ static void start_signal_handler(void)
/* This threads handles all signals and alarms */
/* ARGSUSED */
-static void *signal_hand(void *arg __attribute__((unused)))
+extern "C" void *signal_hand(void *arg __attribute__((unused)))
{
sigset_t set;
int sig;
@@ -1654,8 +1678,8 @@ static void *signal_hand(void *arg __attribute__((unused)))
/* ARGSUSED */
-static int my_message_sql(uint error, const char *str,
- myf MyFlags __attribute__((unused)))
+extern "C" int my_message_sql(uint error, const char *str,
+ myf MyFlags __attribute__((unused)))
{
THD *thd;
DBUG_ENTER("my_message_sql");
@@ -1675,6 +1699,17 @@ static int my_message_sql(uint error, const char *str,
DBUG_RETURN(0);
}
+
+/*
+ Forget last error message (if we got one)
+*/
+
+void clear_error_message(THD *thd)
+{
+ thd->net.last_error[0]= 0;
+}
+
+
#ifdef __WIN__
struct utsname
@@ -1690,7 +1725,7 @@ int uname(struct utsname *a)
#ifdef __WIN__
-pthread_handler_decl(handle_shutdown,arg)
+extern "C" pthread_handler_decl(handle_shutdown,arg)
{
MSG msg;
SHUTDOWN_THD;
@@ -1718,7 +1753,7 @@ int __stdcall handle_kill(ulong ctrl_type)
#endif
#ifdef OS2
-pthread_handler_decl(handle_shutdown,arg)
+extern "C" pthread_handler_decl(handle_shutdown,arg)
{
SHUTDOWN_THD;
my_thread_init();
@@ -1902,8 +1937,6 @@ int main(int argc, char **argv)
if (!ssl_acceptor_fd)
opt_use_ssl = 0;
}
- if (des_key_file)
- load_des_key_file(des_key_file);
#endif /* HAVE_OPENSSL */
#ifdef HAVE_LIBWRAP
@@ -1976,6 +2009,10 @@ int main(int argc, char **argv)
reset_floating_point_exceptions();
init_thr_lock();
init_slave_list();
+#ifdef HAVE_OPENSSL
+ if (des_key_file)
+ load_des_key_file(des_key_file);
+#endif /* HAVE_OPENSSL */
/* Setup log files */
if (opt_log)
@@ -2002,6 +2039,8 @@ int main(int argc, char **argv)
if (ha_init())
{
sql_print_error("Can't init databases");
+ if (unix_sock != INVALID_SOCKET)
+ unlink(mysql_unix_port);
exit(1);
}
ha_key_cache();
@@ -2037,10 +2076,12 @@ int main(int argc, char **argv)
pthread_key_create(&THR_MALLOC,NULL))
{
sql_print_error("Can't create thread-keys");
+ if (unix_sock != INVALID_SOCKET)
+ unlink(mysql_unix_port);
exit(1);
}
start_signal_handler(); // Creates pidfile
- if (acl_init(opt_noacl))
+ if (acl_init((THD*) 0, opt_noacl))
{
abort_loop=1;
select_thread_in_use=0;
@@ -2049,10 +2090,12 @@ int main(int argc, char **argv)
if (!opt_bootstrap)
(void) my_delete(pidfile_name,MYF(MY_WME)); // Not needed anymore
#endif
+ if (unix_sock != INVALID_SOCKET)
+ unlink(mysql_unix_port);
exit(1);
}
if (!opt_noacl)
- (void) grant_init();
+ (void) grant_init((THD*) 0);
init_max_user_conn();
init_update_queries();
@@ -2521,7 +2564,7 @@ inline void kill_broken_server()
/* Handle new connections and spawn new process to handle them */
-pthread_handler_decl(handle_connections_sockets,arg __attribute__((unused)))
+extern "C" pthread_handler_decl(handle_connections_sockets,arg __attribute__((unused)))
{
my_socket sock,new_sock;
uint error_count=0;
@@ -2557,7 +2600,7 @@ pthread_handler_decl(handle_connections_sockets,arg __attribute__((unused)))
while (!abort_loop)
{
readFDs=clientFDs;
-#ifdef HPUX
+#ifdef HPUX10
if (select(max_used_connection,(int*) &readFDs,0,0,0) < 0)
continue;
#else
@@ -2571,7 +2614,7 @@ pthread_handler_decl(handle_connections_sockets,arg __attribute__((unused)))
MAYBE_BROKEN_SYSCALL
continue;
}
-#endif /* HPUX */
+#endif /* HPUX10 */
if (abort_loop)
{
MAYBE_BROKEN_SYSCALL;
@@ -2728,7 +2771,7 @@ pthread_handler_decl(handle_connections_sockets,arg __attribute__((unused)))
#ifdef __NT__
-pthread_handler_decl(handle_connections_namedpipes,arg)
+extern "C" pthread_handler_decl(handle_connections_namedpipes,arg)
{
HANDLE hConnectedPipe;
BOOL fConnected;
@@ -3053,8 +3096,9 @@ enum options {
OPT_MASTER_PASSWORD, OPT_MASTER_PORT,
OPT_MASTER_INFO_FILE, OPT_MASTER_CONNECT_RETRY,
OPT_MASTER_RETRY_COUNT,
- OPT_MASTER_SSL, OPT_MASTER_SSL_KEY,
- OPT_MASTER_SSL_CERT,
+ OPT_MASTER_SSL, OPT_MASTER_SSL_KEY,
+ OPT_MASTER_SSL_CERT, OPT_MASTER_SSL_CAPATH,
+ OPT_MASTER_SSL_CIPHER,
OPT_SQL_BIN_UPDATE_SAME, OPT_REPLICATE_DO_DB,
OPT_REPLICATE_IGNORE_DB, OPT_LOG_SLAVE_UPDATES,
OPT_BINLOG_DO_DB, OPT_BINLOG_IGNORE_DB,
@@ -3371,6 +3415,14 @@ struct my_option my_long_options[] =
"Master SSL certificate file name. Only applies if you have enabled master-ssl.",
(gptr*) &master_ssl_cert, (gptr*) &master_ssl_cert, 0, GET_STR, OPT_ARG,
0, 0, 0, 0, 0, 0},
+ {"master-ssl-capath", OPT_MASTER_SSL_CAPATH,
+ "Master SSL CA path. Only applies if you have enabled master-ssl.",
+ (gptr*) &master_ssl_capath, (gptr*) &master_ssl_capath, 0, GET_STR, OPT_ARG,
+ 0, 0, 0, 0, 0, 0},
+ {"master-ssl-cipher", OPT_MASTER_SSL_CIPHER,
+ "Master SSL cipher. Only applies if you have enabled master-ssl.",
+ (gptr*) &master_ssl_cipher, (gptr*) &master_ssl_capath, 0, GET_STR, OPT_ARG,
+ 0, 0, 0, 0, 0, 0},
{"myisam-recover", OPT_MYISAM_RECOVER,
"Syntax: myisam-recover[=option[,option...]], where option can be DEFAULT, BACKUP or FORCE.",
(gptr*) &myisam_recover_options_str, (gptr*) &myisam_recover_options_str, 0,
@@ -3460,7 +3512,7 @@ struct my_option my_long_options[] =
(gptr*) &report_port, (gptr*) &report_port, 0, GET_UINT, REQUIRED_ARG,
MYSQL_PORT, 0, 0, 0, 0, 0},
{"rpl-recovery-rank", OPT_RPL_RECOVERY_RANK, "Undocumented",
- (gptr*) &rpl_recovery_rank, (gptr*) &rpl_recovery_rank, 0, GET_UINT,
+ (gptr*) &rpl_recovery_rank, (gptr*) &rpl_recovery_rank, 0, GET_ULONG,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"relay-log", OPT_RELAY_LOG, "Undocumented",
(gptr*) &opt_relay_logname, (gptr*) &opt_relay_logname, 0,
@@ -3473,8 +3525,7 @@ struct my_option my_long_options[] =
#ifndef TO_BE_DELETED
{"safe-show-database", OPT_SAFE_SHOW_DB,
"Deprecated option; One should use GRANT SHOW DATABASES instead...",
- (gptr*) &opt_safe_show_db, (gptr*) &opt_safe_show_db, 0, GET_BOOL, NO_ARG,
- 0, 0, 0, 0, 0, 0},
+ 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
#endif
{"safe-user-create", OPT_SAFE_USER_CREATE,
"Don't allow new user creation by the user who has no write privileges to the mysql.user table",
@@ -4029,6 +4080,7 @@ struct show_var_st status_vars[]= {
{"Qcache_queries_in_cache", (char*) &query_cache.queries_in_cache, SHOW_LONG_CONST},
{"Qcache_inserts", (char*) &query_cache.inserts, SHOW_LONG},
{"Qcache_hits", (char*) &query_cache.hits, SHOW_LONG},
+ {"Qcache_lowmem_prunes", (char*) &query_cache.lowmem_prunes, SHOW_LONG},
{"Qcache_not_cached", (char*) &query_cache.refused, SHOW_LONG},
{"Qcache_free_memory", (char*) &query_cache.free_memory,
SHOW_LONG_CONST},
@@ -4149,7 +4201,7 @@ static void set_options(void)
/* Set default values for some variables */
global_system_variables.table_type=DB_TYPE_MYISAM;
- global_system_variables.tx_isolation=ISO_READ_COMMITTED;
+ global_system_variables.tx_isolation=ISO_REPEATABLE_READ;
global_system_variables.select_limit= (ulonglong) HA_POS_ERROR;
max_system_variables.select_limit= (ulong) HA_POS_ERROR;
global_system_variables.max_join_size= (ulonglong) HA_POS_ERROR;
@@ -4176,7 +4228,7 @@ static void set_options(void)
}
-static my_bool
+extern "C" my_bool
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
char *argument)
{
@@ -4621,7 +4673,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
}
global_system_variables.tx_isolation= ((opt_sql_mode & MODE_SERIALIZABLE) ?
ISO_SERIALIZABLE :
- ISO_READ_COMMITTED);
+ ISO_REPEATABLE_READ);
break;
}
case OPT_MASTER_PASSWORD:
@@ -4719,9 +4771,17 @@ fn_format_relative_to_data_home(my_string to, const char *name,
static void fix_paths(void)
{
- char buff[FN_REFLEN];
- (void) fn_format(mysql_home,mysql_home,"","",16); // Remove symlinks
+ char buff[FN_REFLEN],*pos;
convert_dirname(mysql_home,mysql_home,NullS);
+ /* Resolve symlinks to allow 'mysql_home' to be a relative symlink */
+ my_realpath(mysql_home,mysql_home,MYF(0));
+ /* Ensure that mysql_home ends in FN_LIBCHAR */
+ pos=strend(mysql_home);
+ if (pos[-1] != FN_LIBCHAR)
+ {
+ pos[0]= FN_LIBCHAR;
+ pos[1]= 0;
+ }
convert_dirname(mysql_real_data_home,mysql_real_data_home,NullS);
convert_dirname(language,language,NullS);
(void) my_load_path(mysql_home,mysql_home,""); // Resolve current dir
diff --git a/sql/nt_servc.cc b/sql/nt_servc.cc
index 2d0eae125d6..b917c91ce15 100644
--- a/sql/nt_servc.cc
+++ b/sql/nt_servc.cc
@@ -568,31 +568,3 @@ BOOL NTService::is_super_user()
FreeSid(psidAdministrators);
return ret_value;
}
-/* ------------------------------------------------------------------------
- -------------------------------------------------------------------------- */
-BOOL NTService::IsService(LPCSTR ServiceName)
-{
- BOOL ret_value=FALSE;
- SC_HANDLE service, scm;
-
- if (scm = OpenSCManager(0, 0,SC_MANAGER_ENUMERATE_SERVICE))
- {
- if ((service = OpenService(scm,ServiceName, SERVICE_ALL_ACCESS )))
- {
- ret_value=TRUE;
- CloseServiceHandle(service);
- }
- CloseServiceHandle(scm);
- }
- return ret_value;
-}
-/* ------------------------------------------------------------------------
- -------------------------------------------------------------------------- */
-BOOL NTService::got_service_option(char **argv, char *service_option)
-{
- char *option;
- for (option= argv[1]; *option; option++)
- if (!strcmp(option, service_option))
- return TRUE;
- return FALSE;
-}
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 13c2f6333b1..b6f81ab07eb 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -2463,9 +2463,9 @@ int QUICK_SELECT::get_next()
if (range->flag & NO_MIN_RANGE) // Read first record
{
- int error;
- if ((error=file->index_first(record)))
- DBUG_RETURN(error); // Empty table
+ int local_error;
+ if ((local_error=file->index_first(record)))
+ DBUG_RETURN(local_error); // Empty table
if (cmp_next(range) == 0)
DBUG_RETURN(0);
range=0; // No matching records; go to next range
@@ -2499,13 +2499,13 @@ int QUICK_SELECT::get_next()
/* compare if found key is over max-value */
/* Returns 0 if key <= range->max_key */
-int QUICK_SELECT::cmp_next(QUICK_RANGE *range)
+int QUICK_SELECT::cmp_next(QUICK_RANGE *range_arg)
{
- if (range->flag & NO_MAX_RANGE)
- return (0); /* key can't be to large */
+ if (range_arg->flag & NO_MAX_RANGE)
+ return 0; /* key can't be to large */
KEY_PART *key_part=key_parts;
- for (char *key=range->max_key, *end=key+range->max_length;
+ for (char *key=range_arg->max_key, *end=key+range_arg->max_length;
key < end;
key+= key_part++->part_length)
{
@@ -2526,7 +2526,7 @@ int QUICK_SELECT::cmp_next(QUICK_RANGE *range)
if (cmp > 0)
return 1;
}
- return (range->flag & NEAR_MAX) ? 1 : 0; // Exact match
+ return (range_arg->flag & NEAR_MAX) ? 1 : 0; // Exact match
}
@@ -2610,9 +2610,9 @@ int QUICK_SELECT_DESC::get_next()
if (range->flag & NO_MAX_RANGE) // Read last record
{
- int error;
- if ((error=file->index_last(record)))
- DBUG_RETURN(error); // Empty table
+ int local_error;
+ if ((local_error=file->index_last(record)))
+ DBUG_RETURN(local_error); // Empty table
if (cmp_prev(range) == 0)
DBUG_RETURN(0);
range=0; // No matching records; go to next range
@@ -2666,16 +2666,18 @@ int QUICK_SELECT_DESC::get_next()
}
}
+
/*
- * Returns 0 if found key is inside range (found key >= range->min_key).
- */
-int QUICK_SELECT_DESC::cmp_prev(QUICK_RANGE *range)
+ Returns 0 if found key is inside range (found key >= range->min_key).
+*/
+
+int QUICK_SELECT_DESC::cmp_prev(QUICK_RANGE *range_arg)
{
- if (range->flag & NO_MIN_RANGE)
- return (0); /* key can't be to small */
+ if (range_arg->flag & NO_MIN_RANGE)
+ return 0; /* key can't be to small */
KEY_PART *key_part = key_parts;
- for (char *key = range->min_key, *end = key + range->min_length;
+ for (char *key = range_arg->min_key, *end = key + range_arg->min_length;
key < end;
key += key_part++->part_length)
{
@@ -2699,42 +2701,45 @@ int QUICK_SELECT_DESC::cmp_prev(QUICK_RANGE *range)
if (cmp < 0)
return 1;
}
- return (range->flag & NEAR_MIN) ? 1 : 0; // Exact match
+ return (range_arg->flag & NEAR_MIN) ? 1 : 0; // Exact match
}
+
/*
* True if this range will require using HA_READ_AFTER_KEY
See comment in get_next() about this
*/
-bool QUICK_SELECT_DESC::range_reads_after_key(QUICK_RANGE *range)
+bool QUICK_SELECT_DESC::range_reads_after_key(QUICK_RANGE *range_arg)
{
- return ((range->flag & (NO_MAX_RANGE | NEAR_MAX)) ||
- !(range->flag & EQ_RANGE) ||
- head->key_info[index].key_length != range->max_length) ? 1 : 0;
+ return ((range_arg->flag & (NO_MAX_RANGE | NEAR_MAX)) ||
+ !(range_arg->flag & EQ_RANGE) ||
+ head->key_info[index].key_length != range_arg->max_length) ? 1 : 0;
}
+
/* True if we are reading over a key that may have a NULL value */
-bool QUICK_SELECT_DESC::test_if_null_range(QUICK_RANGE *range,
+bool QUICK_SELECT_DESC::test_if_null_range(QUICK_RANGE *range_arg,
uint used_key_parts)
{
uint offset,end;
KEY_PART *key_part = key_parts,
*key_part_end= key_part+used_key_parts;
- for (offset= 0, end = min(range->min_length, range->max_length) ;
+ for (offset= 0, end = min(range_arg->min_length, range_arg->max_length) ;
offset < end && key_part != key_part_end ;
offset += key_part++->part_length)
{
uint null_length=test(key_part->null_bit);
- if (!memcmp((char*) range->min_key+offset, (char*) range->max_key+offset,
+ if (!memcmp((char*) range_arg->min_key+offset,
+ (char*) range_arg->max_key+offset,
key_part->part_length + null_length))
{
offset+=null_length;
continue;
}
- if (null_length && range->min_key[offset])
+ if (null_length && range_arg->min_key[offset])
return 1; // min_key is null and max_key isn't
// Range doesn't cover NULL. This is ok if there is no more null parts
break;
@@ -2747,7 +2752,7 @@ bool QUICK_SELECT_DESC::test_if_null_range(QUICK_RANGE *range,
*/
if (key_part != key_part_end && key_part->null_bit)
{
- if (offset >= range->min_length || range->min_key[offset])
+ if (offset >= range_arg->min_length || range_arg->min_key[offset])
return 1; // Could be null
key_part++;
}
diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc
index 38365dbb546..1477d46e756 100644
--- a/sql/opt_sum.cc
+++ b/sql/opt_sum.cc
@@ -37,6 +37,19 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
bool recalc_const_item=0;
table_map removed_tables=0;
Item *item;
+ COND *org_conds= conds;
+
+ /* Add all ON conditions to WHERE condition */
+ for (TABLE_LIST *tl=tables; tl ; tl= tl->next)
+ {
+ if (tl->on_expr)
+ conds= and_expressions(conds, tl->on_expr, &org_conds);
+ }
+
+ /*
+ Iterate through item is select part and replace COUNT(), MIN() and MAX()
+ with constants (if possible)
+ */
while ((item= it++))
{
diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc
index 4295a16c547..785a253b1ac 100644
--- a/sql/repl_failsafe.cc
+++ b/sql/repl_failsafe.cc
@@ -188,14 +188,15 @@ err2:
return 1;
}
-static uint32* slave_list_key(SLAVE_INFO* si, uint* len,
- my_bool not_used __attribute__((unused)))
+extern "C" uint32
+*slave_list_key(SLAVE_INFO* si, uint* len,
+ my_bool not_used __attribute__((unused)))
{
*len = 4;
return &si->server_id;
}
-static void slave_info_free(void *s)
+extern "C" void slave_info_free(void *s)
{
my_free((gptr) s, MYF(MY_WME));
}
@@ -203,7 +204,7 @@ static void slave_info_free(void *s)
void init_slave_list()
{
hash_init(&slave_list, system_charset_info, SLAVE_LIST_CHUNK, 0, 0,
- (hash_get_key) slave_list_key, slave_info_free, 0);
+ (hash_get_key) slave_list_key, (hash_free_key) slave_info_free, 0);
pthread_mutex_init(&LOCK_slave_list, MY_MUTEX_INIT_FAST);
}
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 141320cc3f6..599c4af06cc 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -202,8 +202,6 @@ sys_var_thd_enum sys_query_cache_type("query_cache_type",
&SV::query_cache_type,
&query_cache_type_typelib);
#endif /* HAVE_QUERY_CACHE */
-sys_var_bool_ptr sys_safe_show_db("safe_show_database",
- &opt_safe_show_db);
sys_var_long_ptr sys_server_id("server_id",&server_id);
sys_var_bool_ptr sys_slave_compressed_protocol("slave_compressed_protocol",
&opt_slave_compressed_protocol);
@@ -299,6 +297,8 @@ static sys_var_readonly sys_warning_count("warning_count",
/* alias for last_insert_id() to be compatible with Sybase */
static sys_var_slave_skip_counter sys_slave_skip_counter("sql_slave_skip_counter");
+static sys_var_rand_seed1 sys_rand_seed1("rand_seed1");
+static sys_var_rand_seed2 sys_rand_seed2("rand_seed2");
/*
@@ -370,10 +370,11 @@ sys_var *sys_variables[]=
&sys_query_cache_type,
#endif /* HAVE_QUERY_CACHE */
&sys_quote_show_create,
+ &sys_rand_seed1,
+ &sys_rand_seed2,
&sys_read_buff_size,
&sys_read_rnd_buff_size,
&sys_rpl_recovery_rank,
- &sys_safe_show_db,
&sys_safe_updates,
&sys_select_limit,
&sys_server_id,
@@ -448,7 +449,7 @@ struct show_var_st init_vars[]= {
{"innodb_file_io_threads", (char*) &innobase_file_io_threads, SHOW_LONG },
{"innodb_force_recovery", (char*) &innobase_force_recovery, SHOW_LONG },
{"innodb_thread_concurrency", (char*) &innobase_thread_concurrency, SHOW_LONG },
- {"innodb_flush_log_at_trx_commit", (char*) &innobase_flush_log_at_trx_commit, SHOW_LONG},
+ {"innodb_flush_log_at_trx_commit", (char*) &innobase_flush_log_at_trx_commit, SHOW_INT},
{"innodb_fast_shutdown", (char*) &innobase_fast_shutdown, SHOW_MY_BOOL},
{"innodb_flush_method", (char*) &innobase_unix_file_flush_method, SHOW_CHAR_PTR},
{"innodb_lock_wait_timeout", (char*) &innobase_lock_wait_timeout, SHOW_LONG },
@@ -519,7 +520,6 @@ struct show_var_st init_vars[]= {
{sys_query_cache_size.name, (char*) &sys_query_cache_size, SHOW_SYS},
{sys_query_cache_type.name, (char*) &sys_query_cache_type, SHOW_SYS},
#endif /* HAVE_QUERY_CACHE */
- {sys_safe_show_db.name, (char*) &sys_safe_show_db, SHOW_SYS},
#ifdef HAVE_SMEM
{"shared_memory", (char*) &opt_enable_shared_memory, SHOW_MY_BOOL},
{"shared_memory_base_name", (char*) &shared_memory_base_name, SHOW_CHAR_PTR},
@@ -530,7 +530,9 @@ struct show_var_st init_vars[]= {
{"skip_networking", (char*) &opt_disable_networking, SHOW_BOOL},
{"skip_show_database", (char*) &opt_skip_show_db, SHOW_BOOL},
{sys_slow_launch_time.name, (char*) &sys_slow_launch_time, SHOW_SYS},
+#ifdef HAVE_SYS_UN_H
{"socket", (char*) &mysql_unix_port, SHOW_CHAR_PTR},
+#endif
{sys_sort_buffer.name, (char*) &sys_sort_buffer, SHOW_SYS},
{"sql_mode", (char*) &opt_sql_mode, SHOW_LONG},
{"table_cache", (char*) &table_cache_size, SHOW_LONG},
@@ -1073,6 +1075,19 @@ bool sys_var_slave_skip_counter::update(THD *thd, set_var *var)
}
+bool sys_var_rand_seed1::update(THD *thd, set_var *var)
+{
+ thd->rand.seed1= (ulong) var->value->val_int();
+ return 0;
+}
+
+bool sys_var_rand_seed2::update(THD *thd, set_var *var)
+{
+ thd->rand.seed2= (ulong) var->value->val_int();
+ return 0;
+}
+
+
/*
Functions to update thd->options bits
*/
diff --git a/sql/set_var.h b/sql/set_var.h
index 62fa977eb06..de1e27e0da8 100644
--- a/sql/set_var.h
+++ b/sql/set_var.h
@@ -337,6 +337,23 @@ public:
};
+class sys_var_rand_seed1 :public sys_var
+{
+public:
+ sys_var_rand_seed1(const char *name_arg) :sys_var(name_arg) {}
+ bool update(THD *thd, set_var *var);
+ bool check_type(enum_var_type type) { return type == OPT_GLOBAL; }
+};
+
+class sys_var_rand_seed2 :public sys_var
+{
+public:
+ sys_var_rand_seed2(const char *name_arg) :sys_var(name_arg) {}
+ bool update(THD *thd, set_var *var);
+ bool check_type(enum_var_type type) { return type == OPT_GLOBAL; }
+};
+
+
class sys_var_thd_conv_charset :public sys_var_thd
{
public:
diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt
index 0eef4ae9cad..1b1f90abfb3 100644
--- a/sql/share/czech/errmsg.txt
+++ b/sql/share/czech/errmsg.txt
@@ -188,7 +188,7 @@
"Update tabulky bez WHERE s kl-Bíèem není v módu bezpeèných update dovoleno",
"Kl-Bíè '%-.64s' v tabulce '%-.64s' neexistuje",
"Nemohu otev-Bøít tabulku",
-"Handler tabulky nepodporuje check/repair",
+"Handler tabulky nepodporuje %s",
"Proveden-Bí tohoto pøíkazu není v transakci dovoleno",
"Chyba %d p-Bøi COMMIT",
"Chyba %d p-Bøi ROLLBACK",
diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt
index c2e0ddb064f..65eb190b48b 100644
--- a/sql/share/danish/errmsg.txt
+++ b/sql/share/danish/errmsg.txt
@@ -182,7 +182,7 @@
"Du bruger sikker opdaterings modus ('safe update mode') og du forsøgte at opdatere en tabel uden en WHERE klausul, der gør brug af et KEY felt",
"Nøglen '%-.64s' eksisterer ikke i tabellen '%-.64s'",
"Kan ikke åbne tabellen",
-"Denne tabeltype understøtter ikke CHECK/REPAIR",
+"Denne tabeltype understøtter ikke %s",
"Du må ikke bruge denne kommando i en transaktion",
"Modtog fejl %d mens kommandoen COMMIT blev udført",
"Modtog fejl %d mens kommandoen ROLLBACK blev udført",
diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt
index 7a3f7b787b2..965221dd83f 100644
--- a/sql/share/dutch/errmsg.txt
+++ b/sql/share/dutch/errmsg.txt
@@ -190,7 +190,7 @@
"U gebruikt 'safe update mode' en u probeerde een tabel te updaten zonder een WHERE met een KEY kolom",
"Zoeksleutel '%-.64s' bestaat niet in tabel '%-.64s'",
"Kan tabel niet openen",
-"De 'handler' voor de tabel ondersteund geen check/repair",
+"De 'handler' voor de tabel ondersteund geen %s",
"Het is u niet toegestaan dit commando uit te voeren binnen een transactie",
"Kreeg fout %d tijdens COMMIT",
"Kreeg fout %d tijdens ROLLBACK",
diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt
index e746b461a6d..7472fe14365 100644
--- a/sql/share/english/errmsg.txt
+++ b/sql/share/english/errmsg.txt
@@ -179,7 +179,7 @@
"You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column",
"Key '%-.64s' doesn't exist in table '%-.64s'",
"Can't open table",
-"The handler for the table doesn't support check/repair",
+"The handler for the table doesn't support %s",
"You are not allowed to execute this command in a transaction",
"Got error %d during COMMIT",
"Got error %d during ROLLBACK",
diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt
index ee20b9890c4..3f2745a8809 100644
--- a/sql/share/estonian/errmsg.txt
+++ b/sql/share/estonian/errmsg.txt
@@ -184,7 +184,7 @@
"Katse muuta tabelit turvalises rezhiimis ilma WHERE klauslita",
"Võti '%-.64s' ei eksisteeri tabelis '%-.64s'",
"Ei suuda avada tabelit",
-"Antud tabelitüüp ei toeta CHECK/REPAIR käske",
+"Antud tabelitüüp ei toeta %s käske",
"Seda käsku ei saa kasutada transaktsiooni sees",
"Viga %d käsu COMMIT täitmisel",
"Viga %d käsu ROLLBACK täitmisel",
diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt
index 89b82b3851b..f1df0c0c2f2 100644
--- a/sql/share/french/errmsg.txt
+++ b/sql/share/french/errmsg.txt
@@ -179,7 +179,7 @@
"Vous êtes en mode 'safe update' et vous essayez de faire un UPDATE sans clause WHERE utilisant un index",
"L'index '%-.64s' n'existe pas sur la table '%-.64s'",
"Impossible d'ouvrir la table",
-"Ce type de table ne supporte pas les check/repair",
+"Ce type de table ne supporte pas les %s",
"Vous n'êtes pas autorisé à exécute cette commande dans une transaction",
"Erreur %d lors du COMMIT",
"Erreur %d lors du ROLLBACK",
diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt
index 3b354ee3298..bd51de5a257 100644
--- a/sql/share/german/errmsg.txt
+++ b/sql/share/german/errmsg.txt
@@ -182,7 +182,7 @@
"Unter Verwendung des Sicheren Updatemodes wurde versucht eine Tabelle zu updaten ohne eine KEY-Spalte in der WHERE-Klausel",
"Schlüssel '%-.64s' existiert nicht in der Tabelle '%-.64s'",
"Kann Tabelle nicht öffnen",
-"Der Tabellen-Handler für diese Tabelle unterstützt kein check/repair",
+"Der Tabellen-Handler für diese Tabelle unterstützt kein %s",
"Keine Berechtigung dieses Kommando in einer Transaktion auszuführen",
"Fehler %d wärend COMMIT",
"Fehler %d wärend ROLLBACK",
diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt
index 38ce4217888..915b4e9f64b 100644
--- a/sql/share/greek/errmsg.txt
+++ b/sql/share/greek/errmsg.txt
@@ -179,7 +179,7 @@
"You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column",
"Key '%-.64s' doesn't exist in table '%-.64s'",
"Can't open table",
-"The handler for the table doesn't support check/repair",
+"The handler for the table doesn't support %s",
"You are not allowed to execute this command in a transaction",
"Got error %d during COMMIT",
"Got error %d during ROLLBACK",
diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt
index f2fd63765d9..aa8567dac87 100644
--- a/sql/share/hungarian/errmsg.txt
+++ b/sql/share/hungarian/errmsg.txt
@@ -181,7 +181,7 @@
"On a biztonsagos update modot hasznalja, es WHERE that uses a KEY column",
"A '%-.64s' kulcs nem letezik a '%-.64s' tablaban",
"Nem tudom megnyitni a tablat",
-"A tabla kezeloje (handler) nem tamogatja az ellenorzest/helyreallitast",
+"A tabla kezeloje (handler) nem tamogatja az %s",
"Az On szamara nem engedelyezett a parancs vegrehajtasa a tranzakcioban",
"%d hiba a COMMIT vegrehajtasa soran",
"%d hiba a ROLLBACK vegrehajtasa soran",
diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt
index 2b24a123e25..20430757590 100644
--- a/sql/share/italian/errmsg.txt
+++ b/sql/share/italian/errmsg.txt
@@ -179,7 +179,7 @@
"In modalita` 'safe update' si e` cercato di aggiornare una tabella senza clausola WHERE su una chiave",
"La chiave '%-.64s' non esiste nella tabella '%-.64s'",
"Impossibile aprire la tabella",
-"Il gestore per la tabella non supporta il controllo/riparazione",
+"Il gestore per la tabella non supporta il %s",
"Non puoi eseguire questo comando in una transazione",
"Rilevato l'errore %d durante il COMMIT",
"Rilevato l'errore %d durante il ROLLBACK",
diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt
index 7b428cae703..2f3c61c1fe1 100644
--- a/sql/share/japanese/errmsg.txt
+++ b/sql/share/japanese/errmsg.txt
@@ -181,7 +181,7 @@
"You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column",
"Key '%-.64s' doesn't exist in table '%-.64s'",
"Can't open table",
-"The handler for the table doesn't support check/repair",
+"The handler for the table doesn't support %s",
"You are not allowed to execute this command in a transaction",
"Got error %d during COMMIT",
"Got error %d during ROLLBACK",
diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt
index 8fbc33bf690..277e53895c3 100644
--- a/sql/share/korean/errmsg.txt
+++ b/sql/share/korean/errmsg.txt
@@ -179,7 +179,7 @@
"You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column",
"Key '%-.64s' doesn't exist in table '%-.64s'",
"Can't open table",
-"The handler for the table doesn't support check/repair",
+"The handler for the table doesn't support %s",
"You are not allowed to execute this command in a transaction",
"Got error %d during COMMIT",
"Got error %d during ROLLBACK",
diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt
index 1c3cf11e10c..4c3a12d6557 100644
--- a/sql/share/norwegian-ny/errmsg.txt
+++ b/sql/share/norwegian-ny/errmsg.txt
@@ -181,7 +181,7 @@
"You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column",
"Key '%-.64s' doesn't exist in table '%-.64s'",
"Can't open table",
-"The handler for the table doesn't support check/repair",
+"The handler for the table doesn't support %s",
"You are not allowed to execute this command in a transaction",
"Got error %d during COMMIT",
"Got error %d during ROLLBACK",
diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt
index 1db0068685c..46bf84c409e 100644
--- a/sql/share/norwegian/errmsg.txt
+++ b/sql/share/norwegian/errmsg.txt
@@ -181,7 +181,7 @@
"You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column",
"Key '%-.64s' doesn't exist in table '%-.64s'",
"Can't open table",
-"The handler for the table doesn't support check/repair",
+"The handler for the table doesn't support %s",
"You are not allowed to execute this command in a transaction",
"Got error %d during COMMIT",
"Got error %d during ROLLBACK",
diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt
index bda25b01065..e4d9832725d 100644
--- a/sql/share/polish/errmsg.txt
+++ b/sql/share/polish/errmsg.txt
@@ -183,7 +183,7 @@
"You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column",
"Key '%-.64s' doesn't exist in table '%-.64s'",
"Can't open table",
-"The handler for the table doesn't support check/repair",
+"The handler for the table doesn't support %s",
"You are not allowed to execute this command in a transaction",
"Got error %d during COMMIT",
"Got error %d during ROLLBACK",
diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt
index 947f935fd33..1c5adc96560 100644
--- a/sql/share/portuguese/errmsg.txt
+++ b/sql/share/portuguese/errmsg.txt
@@ -179,7 +179,7 @@
"Você está usando modo de atualização seguro e tentou atualizar uma tabela sem uma cláusula WHERE que use uma coluna chave",
"Chave '%-.64s' não existe na tabela '%-.64s'",
"Não pode abrir a tabela",
-"O manipulador de tabela não suporta checagem/reparação (check/repair)",
+"O manipulador de tabela não suporta %s",
"Não lhe é permitido executar este comando em uma transação",
"Obteve erro %d durante COMMIT",
"Obteve erro %d durante ROLLBACK",
diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt
index 71baf4ca098..313af2e5f14 100644
--- a/sql/share/romanian/errmsg.txt
+++ b/sql/share/romanian/errmsg.txt
@@ -183,7 +183,7 @@
"You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column",
"Key '%-.64s' doesn't exist in table '%-.64s'",
"Can't open table",
-"The handler for the table doesn't support check/repair",
+"The handler for the table doesn't support %s",
"You are not allowed to execute this command in a transaction",
"Got error %d during COMMIT",
"Got error %d during ROLLBACK",
diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt
index 03ea8b74ce5..3b636aacae7 100644
--- a/sql/share/russian/errmsg.txt
+++ b/sql/share/russian/errmsg.txt
@@ -182,7 +182,7 @@
"MySQL ÒÁÂÏÔÁÅÔ × ÒÅÖÉÍÅ ÚÁÝÉÔÙ ÏÔ ÄÕÒÁËÏ× (safe_mode) - ÎÅ ÍÏÇÕ UPDATE ÂÅÚ WHERE Ó ËÁËÉÍ-ÎÅÂÕÄØ KEY",
"éÎÄÅËÓ '%-.64s' ÎÅ ÎÁÊÄÅÎ × ÔÁÂÌÉÃÅ '%-.64s'",
"îÅ ÍÏÇÕ ÏÔËÒÙÔØ ÔÁÂÌÉÃÕ",
-"äÁÎÎÙÊ ÔÉÐ ÔÁÂÌÉà ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔ check/repair",
+"äÁÎÎÙÊ ÔÉÐ ÔÁÂÌÉà ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔ ËÏÍÁÎÄÕ %s",
"üÔÁ ËÏÍÁÎÄÁ ×ÎÕÔÒÉ ÔÒÁÎÚÁËÃÉÉ ÚÁÐÒÅÝÅÎÁ",
"ïÛÉÂËÁ %d ×Ï ×ÒÅÍÑ COMMIT",
"ïÛÉÂËÁ %d ×Ï ×ÒÅÍÑ ROLLBACK",
diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt
index 36f5e421561..9f610a84bd9 100644
--- a/sql/share/slovak/errmsg.txt
+++ b/sql/share/slovak/errmsg.txt
@@ -187,7 +187,7 @@
"You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column",
"Key '%-.64s' doesn't exist in table '%-.64s'",
"Can't open table",
-"The handler for the table doesn't support check/repair",
+"The handler for the table doesn't support %s",
"You are not allowed to execute this command in a transaction",
"Got error %d during COMMIT",
"Got error %d during ROLLBACK",
diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt
index 5a087d6fa17..ab4e3e93a25 100644
--- a/sql/share/spanish/errmsg.txt
+++ b/sql/share/spanish/errmsg.txt
@@ -180,7 +180,7 @@
"Tu estás usando modo de actualización segura y tentado actualizar una tabla sin un WHERE que usa una KEY columna",
"Clave '%-.64s' no existe en la tabla '%-.64s'",
"No puedo abrir tabla",
-"El manipulador de la tabla no permite soporte para check/repair",
+"El manipulador de la tabla no permite soporte para %s",
"No tienes el permiso para ejecutar este comando en una transición",
"Obtenido error %d durante COMMIT",
"Obtenido error %d durante ROLLBACK",
diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt
index 42f2e72ec45..3d91522bf0f 100644
--- a/sql/share/swedish/errmsg.txt
+++ b/sql/share/swedish/errmsg.txt
@@ -179,7 +179,7 @@
"Du använder 'säker uppdaterings mod' och försökte uppdatera en table utan en WHERE sats som använder sig av en nyckel",
"Nyckel '%-.64s' finns inte in tabell '%-.64s'",
"Kan inte öppna tabellen",
-"Tabellhanteraren för denna tabell kan inte göra check/repair",
+"Tabellhanteraren för denna tabell kan inte göra %s",
"Du får inte utföra detta kommando i en transaktion",
"Fick fel %d vid COMMIT",
"Fick fel %d vid ROLLBACK",
diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt
index f41041de2bb..d16a8e678d1 100644
--- a/sql/share/ukrainian/errmsg.txt
+++ b/sql/share/ukrainian/errmsg.txt
@@ -184,7 +184,7 @@
"÷É Õ ÒÅÖÉͦ ÂÅÚÐÅÞÎÏÇÏ ÏÎÏ×ÌÅÎÎÑ ÔÁ ÎÁÍÁÇÁ¤ÔÅÓØ ÏÎÏ×ÉÔÉ ÔÁÂÌÉÃÀ ÂÅÚ ÏÐÅÒÁÔÏÒÁ WHERE, ÝÏ ×ÉËÏÒÉÓÔÏ×Õ¤ KEY ÓÔÏ×ÂÅÃØ",
"ëÌÀÞ '%-.64s' ÎÅ ¦ÓÎÕ¤ × ÔÁÂÌÉæ '%-.64s'",
"îÅ ÍÏÖÕ ×¦ÄËÒÉÔÉ ÔÁÂÌÉÃÀ",
-"÷ËÁÚ¦×ÎÉË ÔÁÂÌÉæ ΊЦÄÔÒÉÍÕÅ ÐÅÒÅצÒËÕ/צÄÎÏ×ÌÅÎÎÑ",
+"÷ËÁÚ¦×ÎÉË ÔÁÂÌÉæ ΊЦÄÔÒÉÍÕÅ %s",
"÷ÁÍ ÎÅ ÄÏÚ×ÏÌÅÎÏ ×ÉËÏÎÕ×ÁÔÉ ÃÀ ËÏÍÁÎÄÕ × ÔÒÁÎÚÁËæ§",
"ïÔÒÉÍÁÎÏ ÐÏÍÉÌËÕ %d Ð¦Ä ÞÁÓ COMMIT",
"ïÔÒÉÍÁÎÏ ÐÏÍÉÌËÕ %d Ð¦Ä ÞÁÓ ROLLBACK",
diff --git a/sql/slave.cc b/sql/slave.cc
index a9c1b15a982..f8acc592afa 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -608,7 +608,7 @@ void init_table_rule_hash(HASH* h, bool* h_inited)
{
hash_init(h, system_charset_info,TABLE_RULE_HASH_SIZE,0,0,
(hash_get_key) get_table_key,
- (void (*)(void*)) free_table_ent, 0);
+ (hash_free_key) free_table_ent, 0);
*h_inited = 1;
}
@@ -1637,7 +1637,7 @@ bool flush_master_info(MASTER_INFO* mi)
DBUG_PRINT("enter",("master_pos: %ld", (long) mi->master_log_pos));
my_b_seek(file, 0L);
- my_b_printf(file, "%s\n%s\n%s\n%s\n%s\n%d\n%d\n%d\n",
+ my_b_printf(file, "%s\n%s\n%s\n%s\n%s\n%d\n%d\n",
mi->master_log_name, llstr(mi->master_log_pos, lbuf),
mi->host, mi->user,
mi->password, mi->port, mi->connect_retry
@@ -1945,7 +1945,7 @@ int check_expected_error(THD* thd, RELAY_LOG_INFO* rli, int expected_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 and then restart the slave with SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1;\
SLAVE START;", thd->query);
rli->last_slave_errno = expected_error;
sql_print_error("%s",rli->last_slave_error);
@@ -2025,11 +2025,10 @@ This may also be a network problem, or just a bug in the master or slave code.\
}
/*****************************************************************************
-
Slave I/O Thread entry point
-
*****************************************************************************/
-pthread_handler_decl(handle_slave_io,arg)
+
+extern "C" pthread_handler_decl(handle_slave_io,arg)
{
THD *thd; // needs to be first for thread_stack
MYSQL *mysql;
@@ -2298,11 +2297,10 @@ err:
}
/*****************************************************************************
-
Slave SQL Thread entry point
-
*****************************************************************************/
-pthread_handler_decl(handle_slave_sql,arg)
+
+extern "C" pthread_handler_decl(handle_slave_sql,arg)
{
THD *thd; /* needs to be first for thread_stack */
char llbuff[22],llbuff1[22];
@@ -2478,7 +2476,7 @@ static int process_io_create_file(MASTER_INFO* mi, Create_file_log_event* cev)
in the loop
*/
{
- Append_block_log_event aev(thd,0,0);
+ Append_block_log_event aev(thd,0,0,0);
for (;;)
{
@@ -2491,7 +2489,7 @@ static int process_io_create_file(MASTER_INFO* mi, Create_file_log_event* cev)
if (unlikely(!num_bytes)) /* eof */
{
net_write_command(net, 0, "", 0, "", 0);/* 3.23 master wants it */
- Execute_load_log_event xev(thd);
+ Execute_load_log_event xev(thd,0);
xev.log_pos = mi->master_log_pos;
if (unlikely(mi->rli.relay_log.append(&xev)))
{
diff --git a/sql/slave.h b/sql/slave.h
index 74c89f9d755..2c750e415bc 100644
--- a/sql/slave.h
+++ b/sql/slave.h
@@ -436,8 +436,8 @@ int init_relay_log_pos(RELAY_LOG_INFO* rli,const char* log,ulonglong pos,
int purge_relay_logs(RELAY_LOG_INFO* rli, THD *thd, bool just_reset,
const char** errmsg);
-pthread_handler_decl(handle_slave_io,arg);
-pthread_handler_decl(handle_slave_sql,arg);
+extern "C" pthread_handler_decl(handle_slave_io,arg);
+extern "C" pthread_handler_decl(handle_slave_sql,arg);
extern bool volatile abort_loop;
extern MASTER_INFO main_mi, *active_mi; /* active_mi for multi-master */
extern volatile int active_mi_in_use;
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 5f8cf42c2bf..8ccd7dbde68 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -119,6 +119,7 @@ static bool compare_hostname(const acl_host_and_ip *host, const char *hostname,
SYNOPSIS
acl_init()
+ thd Thread handler
dont_read_acl_tables Set to 1 if run with --skip-grant
RETURN VALUES
@@ -127,9 +128,9 @@ static bool compare_hostname(const acl_host_and_ip *host, const char *hostname,
*/
-my_bool acl_init(bool dont_read_acl_tables)
+my_bool acl_init(THD *org_thd, bool dont_read_acl_tables)
{
- THD *thd, *org_thd;
+ THD *thd;
TABLE_LIST tables[3];
TABLE *table;
READ_RECORD read_record_info;
@@ -140,14 +141,13 @@ my_bool acl_init(bool dont_read_acl_tables)
if (!acl_cache)
acl_cache=new hash_filo(ACL_CACHE_SIZE,0,0,
(hash_get_key) acl_entry_get_key,
- (void (*)(void*)) free);
+ (hash_free_key) free);
if (dont_read_acl_tables)
DBUG_RETURN(0); /* purecov: tested */
/*
To be able to run this from boot, we allocate a temporary THD
*/
- org_thd=current_thd; // Save for restore
if (!(thd=new THD))
DBUG_RETURN(1); /* purecov: inspected */
thd->store_globals();
@@ -339,6 +339,11 @@ end:
delete thd;
if (org_thd)
org_thd->store_globals(); /* purecov: inspected */
+ else
+ {
+ /* Remember that we don't have a THD */
+ my_pthread_setspecific_ptr(THR_THD, 0);
+ }
DBUG_RETURN(return_val);
}
@@ -385,7 +390,7 @@ void acl_reload(THD *thd)
delete_dynamic(&acl_wild_hosts);
hash_free(&acl_check_hosts);
- if (acl_init(0))
+ if (acl_init(thd, 0))
{ // Error. Revert to old list
acl_free(); /* purecov: inspected */
acl_hosts=old_acl_hosts;
@@ -1089,7 +1094,7 @@ bool change_password(THD *thd, const char *host, const char *user,
acl_user->host.hostname ? acl_user->host.hostname : "",
new_password));
mysql_update_log.write(thd, buff, query_length);
- Query_log_event qinfo(thd, buff, query_length);
+ Query_log_event qinfo(thd, buff, query_length, 0);
mysql_bin_log.write(&qinfo);
DBUG_RETURN(0);
}
@@ -1352,8 +1357,13 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
strlen(thd->lex.x509_subject), system_charset_info);
break;
case SSL_TYPE_NOT_SPECIFIED:
- case SSL_TYPE_NONE: // Impossible
- break; // Nothing to do
+ break;
+ case SSL_TYPE_NONE:
+ table->field[24]->store("",0);
+ table->field[25]->store("",0);
+ table->field[26]->store("",0);
+ table->field[27]->store("",0);
+ break;
}
USER_RESOURCES mqh = thd->lex.mqh;
@@ -2275,9 +2285,9 @@ void grant_free(void)
/* Init grant array if possible */
-my_bool grant_init(void)
+my_bool grant_init(THD *org_thd)
{
- THD *thd, *org_thd;
+ THD *thd;
TABLE_LIST tables[2];
MYSQL_LOCK *lock;
my_bool return_val= 1;
@@ -2294,7 +2304,6 @@ my_bool grant_init(void)
if (!initialized)
DBUG_RETURN(0); /* purecov: tested */
- org_thd=current_thd;
if (!(thd=new THD))
DBUG_RETURN(1); /* purecov: deadcode */
thd->store_globals();
@@ -2352,13 +2361,18 @@ end:
delete thd;
if (org_thd)
org_thd->store_globals();
+ else
+ {
+ /* Remember that we don't have a THD */
+ my_pthread_setspecific_ptr(THR_THD, 0);
+ }
DBUG_RETURN(return_val);
}
/* Reload grant array if possible */
-void grant_reload(void)
+void grant_reload(THD *thd)
{
HASH old_hash_tables;bool old_grant_option;
MEM_ROOT old_mem;
@@ -2372,7 +2386,7 @@ void grant_reload(void)
old_grant_option = grant_option;
old_mem = memex;
- if (grant_init())
+ if (grant_init(thd))
{ // Error. Revert to old hash
grant_free(); /* purecov: deadcode */
hash_tables=old_hash_tables; /* purecov: deadcode */
diff --git a/sql/sql_acl.h b/sql/sql_acl.h
index 326a55ddd0c..6925b6b406c 100644
--- a/sql/sql_acl.h
+++ b/sql/sql_acl.h
@@ -81,7 +81,7 @@
/* prototypes */
-my_bool acl_init(bool dont_read_acl_tables);
+my_bool acl_init(THD *thd, bool dont_read_acl_tables);
void acl_reload(THD *thd);
void acl_free(bool end=0);
ulong acl_get(const char *host, const char *ip, const char *bin_ip,
@@ -98,9 +98,9 @@ int mysql_grant(THD *thd, const char *db, List <LEX_USER> &user_list,
int mysql_table_grant(THD *thd, TABLE_LIST *table, List <LEX_USER> &user_list,
List <LEX_COLUMN> &column_list, ulong rights,
bool revoke);
-my_bool grant_init(void);
+my_bool grant_init(THD *thd);
void grant_free(void);
-void grant_reload(void);
+void grant_reload(THD *thd);
bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
uint show_command=0, bool dont_print_error=0);
bool check_grant_column (THD *thd,TABLE *table, const char *name, uint length,
diff --git a/sql/sql_analyse.cc b/sql/sql_analyse.cc
index 5c735ab35d5..f98eb0e0b26 100644
--- a/sql/sql_analyse.cc
+++ b/sql/sql_analyse.cc
@@ -677,7 +677,7 @@ bool analyse::end_of_records()
case FIELD_TYPE_DECIMAL:
ans.append("DECIMAL", 7);
// if item is FIELD_ITEM, it _must_be_ Field_num in this case
- if (((Field_num*) (*f)->item)->zerofill)
+ if (((Field_num*) ((Item_field*) (*f)->item)->field)->zerofill)
ans.append(" ZEROFILL");
break;
default:
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index fd6c2c48020..59310fb00de 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -39,8 +39,8 @@ static key_map get_key_map_from_key_list(TABLE *table,
List<String> *index_list);
-static byte *cache_key(const byte *record,uint *length,
- my_bool not_used __attribute__((unused)))
+extern "C" byte *table_cache_key(const byte *record,uint *length,
+ my_bool not_used __attribute__((unused)))
{
TABLE *entry=(TABLE*) record;
*length=entry->key_length;
@@ -50,8 +50,8 @@ static byte *cache_key(const byte *record,uint *length,
void table_cache_init(void)
{
VOID(hash_init(&open_cache,system_charset_info,
- table_cache_size+16,0,0,cache_key,
- (void (*)(void*)) free_cache_entry,0));
+ table_cache_size+16,0,0,table_cache_key,
+ (hash_free_key) free_cache_entry,0));
mysql_rm_tmp_tables();
}
@@ -536,14 +536,14 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh,
if (!found)
if_wait_for_refresh=0; // Nothing to wait for
}
+ if (!tables)
+ kill_delayed_threads();
if (if_wait_for_refresh)
{
/*
If there is any table that has a lower refresh_version, wait until
this is closed (or this thread is killed) before returning
*/
- if (!tables)
- kill_delayed_threads();
thd->mysys_var->current_mutex= &LOCK_open;
thd->mysys_var->current_cond= &COND_refresh;
thd->proc_info="Flushing tables";
@@ -699,26 +699,20 @@ void close_temporary_tables(THD *thd)
{
TABLE *table,*next;
char *query, *end;
- const uint init_query_buf_size = 11; // "drop table "
uint query_buf_size;
bool found_user_tables = 0;
+ if (!thd->temporary_tables)
+ return;
+
LINT_INIT(end);
- query_buf_size = init_query_buf_size;
+ query_buf_size= 50; // Enough for DROP ... TABLE
for (table=thd->temporary_tables ; table ; table=table->next)
- {
query_buf_size += table->key_length;
- }
-
- if (query_buf_size == init_query_buf_size)
- return; // no tables to close
if ((query = alloc_root(&thd->mem_root, query_buf_size)))
- {
- memcpy(query, "drop table ", init_query_buf_size);
- end = query + init_query_buf_size;
- }
+ end=strmov(query, "DROP /*!40005 TEMPORARY */ TABLE ");
for (table=thd->temporary_tables ; table ; table=next)
{
@@ -727,12 +721,14 @@ void close_temporary_tables(THD *thd)
// skip temporary tables not created directly by the user
if (table->real_name[0] != '#')
{
- end = strxmov(end,table->table_cache_key,".",
- table->real_name,",", NullS);
- // here we assume table_cache_key always starts
- // with \0 terminated db name
+ /*
+ Here we assume table_cache_key always starts
+ with \0 terminated db name
+ */
found_user_tables = 1;
}
+ end = strxmov(end,table->table_cache_key,".",
+ table->real_name,",", NullS);
}
next=table->next;
close_temporary(table);
@@ -740,7 +736,7 @@ void close_temporary_tables(THD *thd)
if (query && found_user_tables && mysql_bin_log.is_open())
{
/* The -1 is to remove last ',' */
- Query_log_event qinfo(thd, query, (ulong)(end-query)-1);
+ Query_log_event qinfo(thd, query, (ulong)(end-query)-1, 0);
qinfo.error_code=0;
mysql_bin_log.write(&qinfo);
}
@@ -1435,7 +1431,7 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db,
int error;
DBUG_ENTER("open_unireg_entry");
- (void) sprintf(path,"%s/%s/%s",mysql_data_home,db,name);
+ strxmov(path, mysql_data_home, "/", db, "/", name, NullS);
if (openfrm(path,alias,
(uint) (HA_OPEN_KEYFILE | HA_OPEN_RNDFILE | HA_GET_INDEX |
HA_TRY_READ_ONLY),
@@ -1564,6 +1560,61 @@ int open_tables(THD *thd,TABLE_LIST *start)
}
+/*
+ Check that lock is ok for tables; Call start stmt if ok
+
+ SYNOPSIS
+ check_lock_and_start_stmt()
+ thd Thread handle
+ table_list Table to check
+ lock_type Lock used for table
+
+ RETURN VALUES
+ 0 ok
+ 1 error
+*/
+
+static bool check_lock_and_start_stmt(THD *thd, TABLE *table,
+ thr_lock_type lock_type)
+{
+ int error;
+ DBUG_ENTER("check_lock_and_start_stmt");
+
+ if ((int) lock_type >= (int) TL_WRITE_ALLOW_READ &&
+ (int) table->reginfo.lock_type < (int) TL_WRITE_ALLOW_READ)
+ {
+ my_printf_error(ER_TABLE_NOT_LOCKED_FOR_WRITE,
+ ER(ER_TABLE_NOT_LOCKED_FOR_WRITE),
+ MYF(0),table->table_name);
+ DBUG_RETURN(1);
+ }
+ if ((error=table->file->start_stmt(thd)))
+ {
+ table->file->print_error(error,MYF(0));
+ DBUG_RETURN(1);
+ }
+ DBUG_RETURN(0);
+}
+
+
+/*
+ Open and lock one table
+
+ SYNOPSIS
+ open_ltable()
+ thd Thread handler
+ table_list Table to open is first table in this list
+ lock_type Lock to use for open
+
+ RETURN VALUES
+ table Opened table
+ 0 Error
+
+ If ok, the following are also set:
+ table_list->lock_type lock_type
+ table_list->table table
+*/
+
TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type)
{
TABLE *table;
@@ -1576,8 +1627,6 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type)
&refresh)) && refresh) ;
if (table)
{
- int error;
-
#if defined( __WIN__) || defined(OS2)
/* Win32 can't drop a file that is open */
if (lock_type == TL_WRITE_ALLOW_READ)
@@ -1585,39 +1634,29 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type)
lock_type= TL_WRITE;
}
#endif /* __WIN__ || OS2 */
-
- table_list->table=table;
+ table_list->lock_type= lock_type;
+ table_list->table= table;
table->grant= table_list->grant;
if (thd->locked_tables)
{
- thd->proc_info=0;
- if ((int) lock_type >= (int) TL_WRITE_ALLOW_READ &&
- (int) table->reginfo.lock_type < (int) TL_WRITE_ALLOW_READ)
- {
- my_printf_error(ER_TABLE_NOT_LOCKED_FOR_WRITE,
- ER(ER_TABLE_NOT_LOCKED_FOR_WRITE),
- MYF(0),table_list->alias);
- table=0;
- }
- else if ((error=table->file->start_stmt(thd)))
- {
- table->file->print_error(error,MYF(0));
- table=0;
- }
- thd->proc_info=0;
- DBUG_RETURN(table);
+ if (check_lock_and_start_stmt(thd, table, lock_type))
+ table= 0;
+ }
+ else
+ {
+ if ((table->reginfo.lock_type= lock_type) != TL_UNLOCK)
+ if (!(thd->lock=mysql_lock_tables(thd,&table_list->table,1)))
+ table= 0;
}
- if ((table->reginfo.lock_type=lock_type) != TL_UNLOCK)
- if (!(thd->lock=mysql_lock_tables(thd,&table_list->table,1)))
- DBUG_RETURN(0);
}
thd->proc_info=0;
DBUG_RETURN(table);
}
+
/*
-** Open all tables in list and locks them for read.
-** The lock will automaticly be freed by the close_thread_tables
+ Open all tables in list and locks them for read.
+ The lock will automaticly be freed by close_thread_tables()
*/
int open_and_lock_tables(THD *thd,TABLE_LIST *tables)
@@ -1627,10 +1666,27 @@ int open_and_lock_tables(THD *thd,TABLE_LIST *tables)
return 0;
}
+
+/*
+ Lock all tables in list
+
+ SYNOPSIS
+ lock_tables()
+ thd Thread handler
+ tables Tables to lock
+
+ RETURN VALUES
+ 0 ok
+ -1 Error
+*/
+
int lock_tables(THD *thd,TABLE_LIST *tables)
{
TABLE_LIST *table;
- if (tables && !thd->locked_tables)
+ if (!tables)
+ return 0;
+
+ if (!thd->locked_tables)
{
uint count=0;
for (table = tables ; table ; table=table->next)
@@ -1647,10 +1703,9 @@ int lock_tables(THD *thd,TABLE_LIST *tables)
{
for (table = tables ; table ; table=table->next)
{
- int error;
- if ((error=table->table->file->start_stmt(thd)))
+ if (check_lock_and_start_stmt(thd, table->table, table->lock_type))
{
- table->table->file->print_error(error,MYF(0));
+ ha_rollback_stmt(thd);
return -1;
}
}
@@ -1658,10 +1713,11 @@ int lock_tables(THD *thd,TABLE_LIST *tables)
return 0;
}
+
/*
-** Open a single table without table caching and don't set it in open_list
-** Used by alter_table to open a temporary table and when creating
-** a temporary table with CREATE TEMPORARY ...
+ Open a single table without table caching and don't set it in open_list
+ Used by alter_table to open a temporary table and when creating
+ a temporary table with CREATE TEMPORARY ...
*/
TABLE *open_temporary_table(THD *thd, const char *path, const char *db,
@@ -1670,11 +1726,13 @@ TABLE *open_temporary_table(THD *thd, const char *path, const char *db,
TABLE *tmp_table;
DBUG_ENTER("open_temporary_table");
- // the extra size in my_malloc() is for table_cache_key
- // 4 bytes for master thread id if we are in the slave
- // 1 byte to terminate db
- // 1 byte to terminate table_name
- // total of 6 extra bytes in my_malloc in addition to table/db stuff
+ /*
+ The extra size in my_malloc() is for table_cache_key
+ 4 bytes for master thread id if we are in the slave
+ 1 byte to terminate db
+ 1 byte to terminate table_name
+ total of 6 extra bytes in my_malloc in addition to table/db stuff
+ */
if (!(tmp_table=(TABLE*) my_malloc(sizeof(*tmp_table)+(uint) strlen(db)+
(uint) strlen(table_name)+6,
MYF(MY_WME))))
@@ -2071,6 +2129,7 @@ bool setup_tables(TABLE_LIST *tables)
DBUG_RETURN(1);
table->keys_in_use_for_query &= ~map;
}
+ table->used_keys &= table->keys_in_use_for_query;
if (table_list->shared)
{
/* Clear query_id that may have been set by previous select */
@@ -2202,6 +2261,7 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
Item_cond_and *cond_and=new Item_cond_and();
if (!cond_and) // If not out of memory
DBUG_RETURN(1);
+ cond_and->top_level_item();
uint i,j;
for (i=0 ; i < t1->fields ; i++)
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index 2f236da2aa3..ef584f4364e 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -473,33 +473,6 @@ byte *query_cache_table_get_key(const byte *record, uint *length,
Query_cache_query methods
*****************************************************************************/
-void Query_cache_query::init_n_lock()
-{
- DBUG_ENTER("Query_cache_query::init_n_lock");
- res=0; wri = 0; len = 0;
- my_rwlock_init(&lock, NULL);
- lock_writing();
- DBUG_PRINT("qcache", ("inited & locked query for block 0x%lx",
- ((byte*) this)-ALIGN_SIZE(sizeof(Query_cache_block))));
- DBUG_VOID_RETURN;
-}
-
-
-void Query_cache_query::unlock_n_destroy()
-{
- DBUG_ENTER("Query_cache_query::unlock_n_destroy");
- DBUG_PRINT("qcache", ("destroyed & unlocked query for block 0x%lx",
- ((byte*)this)-ALIGN_SIZE(sizeof(Query_cache_block))));
- /*
- The following call is not needed on system where one can destroy an
- active semaphore
- */
- this->unlock_writing();
- rwlock_destroy(&lock);
- DBUG_VOID_RETURN;
-}
-
-
/*
Following methods work for block read/write locking only in this
particular case and in interaction with structure_guard_mutex.
@@ -551,6 +524,34 @@ inline void Query_cache_query::unlock_reading()
RW_UNLOCK(&lock);
}
+
+void Query_cache_query::init_n_lock()
+{
+ DBUG_ENTER("Query_cache_query::init_n_lock");
+ res=0; wri = 0; len = 0;
+ my_rwlock_init(&lock, NULL);
+ lock_writing();
+ DBUG_PRINT("qcache", ("inited & locked query for block 0x%lx",
+ ((byte*) this)-ALIGN_SIZE(sizeof(Query_cache_block))));
+ DBUG_VOID_RETURN;
+}
+
+
+void Query_cache_query::unlock_n_destroy()
+{
+ DBUG_ENTER("Query_cache_query::unlock_n_destroy");
+ DBUG_PRINT("qcache", ("destroyed & unlocked query for block 0x%lx",
+ ((byte*)this)-ALIGN_SIZE(sizeof(Query_cache_block))));
+ /*
+ The following call is not needed on system where one can destroy an
+ active semaphore
+ */
+ this->unlock_writing();
+ rwlock_destroy(&lock);
+ DBUG_VOID_RETURN;
+}
+
+
extern "C"
{
byte *query_cache_query_get_key(const byte *record, uint *length,
@@ -714,19 +715,19 @@ void query_cache_invalidate_by_MyISAM_filename(const char *filename)
Query_cache methods
*****************************************************************************/
-Query_cache::Query_cache(ulong query_cache_limit,
- ulong min_allocation_unit,
- ulong min_result_data_size,
- uint def_query_hash_size ,
- uint def_table_hash_size)
+Query_cache::Query_cache(ulong query_cache_limit_arg,
+ ulong min_allocation_unit_arg,
+ ulong min_result_data_size_arg,
+ uint def_query_hash_size_arg,
+ uint def_table_hash_size_arg)
:query_cache_size(0),
- query_cache_limit(query_cache_limit),
+ query_cache_limit(query_cache_limit_arg),
queries_in_cache(0), hits(0), inserts(0), refused(0),
- total_blocks(0),
- min_allocation_unit(ALIGN_SIZE(min_allocation_unit)),
- min_result_data_size(ALIGN_SIZE(min_result_data_size)),
- def_query_hash_size(ALIGN_SIZE(def_query_hash_size)),
- def_table_hash_size(ALIGN_SIZE(def_table_hash_size)),
+ total_blocks(0), lowmem_prunes(0),
+ min_allocation_unit(ALIGN_SIZE(min_allocation_unit_arg)),
+ min_result_data_size(ALIGN_SIZE(min_result_data_size_arg)),
+ def_query_hash_size(ALIGN_SIZE(def_query_hash_size_arg)),
+ def_table_hash_size(ALIGN_SIZE(def_table_hash_size_arg)),
initialized(0)
{
ulong min_needed= (ALIGN_SIZE(sizeof(Query_cache_block)) +
@@ -751,13 +752,13 @@ ulong Query_cache::resize(ulong query_cache_size_arg)
void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used)
{
- TABLE_COUNTER_TYPE tables;
+ TABLE_COUNTER_TYPE local_tables;
ulong tot_length;
DBUG_ENTER("Query_cache::store_query");
if (query_cache_size == 0)
DBUG_VOID_RETURN;
- if ((tables = is_cacheable(thd, thd->query_length,
+ if ((local_tables = is_cacheable(thd, thd->query_length,
thd->query, &thd->lex, tables_used)))
{
NET *net = &thd->net;
@@ -803,7 +804,7 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used)
Query_cache_block *query_block;
query_block= write_block_data(tot_length, (gptr) thd->query,
ALIGN_SIZE(sizeof(Query_cache_query)),
- Query_cache_block::QUERY, tables, 1);
+ Query_cache_block::QUERY, local_tables, 1);
if (query_block != 0)
{
DBUG_PRINT("qcache", ("query block 0x%lx allocated, %lu",
@@ -820,7 +821,7 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used)
STRUCT_UNLOCK(&structure_guard_mutex);
goto end;
}
- if (!register_all_tables(query_block, tables_used, tables))
+ if (!register_all_tables(query_block, tables_used, local_tables))
{
refused++;
DBUG_PRINT("warning", ("tables list including failed"));
@@ -1527,6 +1528,7 @@ my_bool Query_cache::free_old_query()
if (query_block != 0)
{
free_query(query_block);
+ lowmem_prunes++;
DBUG_RETURN(0);
}
}
@@ -1796,7 +1798,7 @@ inline ulong Query_cache::get_min_append_result_data_size()
my_bool Query_cache::allocate_data_chain(Query_cache_block **result_block,
ulong data_len,
Query_cache_block *query_block,
- my_bool first_block)
+ my_bool first_block_arg)
{
ulong all_headers_len = (ALIGN_SIZE(sizeof(Query_cache_block)) +
ALIGN_SIZE(sizeof(Query_cache_result)));
@@ -1806,7 +1808,7 @@ my_bool Query_cache::allocate_data_chain(Query_cache_block **result_block,
DBUG_PRINT("qcache", ("data_len %lu, all_headers_len %lu",
data_len, all_headers_len));
- ulong min_size = (first_block ?
+ ulong min_size = (first_block_arg ?
get_min_first_result_data_size():
get_min_append_result_data_size());
*result_block = allocate_block(max(min_size, align_len),
@@ -1833,7 +1835,7 @@ my_bool Query_cache::allocate_data_chain(Query_cache_block **result_block,
Query_cache_block *next_block;
if ((success = allocate_data_chain(&next_block,
len - new_block->length,
- query_block, first_block)))
+ query_block, first_block_arg)))
double_linked_list_join(new_block, next_block);
}
if (success)
@@ -1902,14 +1904,23 @@ void Query_cache::invalidate_table(Query_cache_block *table_block)
}
}
+/*
+ Store all used tables
+
+ SYNOPSIS
+ register_all_tables()
+ block Store tables in this block
+ tables_used List if used tables
+ tables_arg Not used ?
+*/
my_bool Query_cache::register_all_tables(Query_cache_block *block,
TABLE_LIST *tables_used,
- TABLE_COUNTER_TYPE tables)
+ TABLE_COUNTER_TYPE tables_arg)
{
TABLE_COUNTER_TYPE n;
DBUG_PRINT("qcache", ("register tables block 0x%lx, n %d, header %x",
- (ulong) block, (int) tables,
+ (ulong) block, (int) tables_arg,
(int) ALIGN_SIZE(sizeof(Query_cache_block))));
Query_cache_block_table *block_table = block->table(0);
@@ -2201,28 +2212,28 @@ void Query_cache::split_block(Query_cache_block *block, ulong len)
Query_cache_block *
-Query_cache::join_free_blocks(Query_cache_block *first_block,
+Query_cache::join_free_blocks(Query_cache_block *first_block_arg,
Query_cache_block *block_in_list)
{
Query_cache_block *second_block;
DBUG_ENTER("Query_cache::join_free_blocks");
DBUG_PRINT("qcache",
("join first 0x%lx, pnext 0x%lx, in list 0x%lx",
- (ulong) first_block, (ulong) first_block->pnext,
+ (ulong) first_block_arg, (ulong) first_block_arg->pnext,
(ulong) block_in_list));
exclude_from_free_memory_list(block_in_list);
- second_block = first_block->pnext;
+ second_block = first_block_arg->pnext;
// May be was not free block
second_block->used=0;
second_block->destroy();
total_blocks--;
- first_block->length += second_block->length;
- first_block->pnext = second_block->pnext;
- second_block->pnext->pprev = first_block;
+ first_block_arg->length += second_block->length;
+ first_block_arg->pnext = second_block->pnext;
+ second_block->pnext->pprev = first_block_arg;
- DBUG_RETURN(first_block);
+ DBUG_RETURN(first_block_arg);
}
@@ -2439,7 +2450,7 @@ TABLE_COUNTER_TYPE Query_cache::is_cacheable(THD *thd, uint32 query_len,
char *query,
LEX *lex, TABLE_LIST *tables_used)
{
- TABLE_COUNTER_TYPE tables = 0;
+ TABLE_COUNTER_TYPE table_count = 0;
DBUG_ENTER("Query_cache::is_cacheable");
if (lex->sql_command == SQLCOM_SELECT &&
@@ -2456,7 +2467,7 @@ TABLE_COUNTER_TYPE Query_cache::is_cacheable(THD *thd, uint32 query_len,
for (; tables_used; tables_used= tables_used->next)
{
- tables++;
+ table_count++;
DBUG_PRINT("qcache", ("table %s, db %s, type %u",
tables_used->real_name,
tables_used->db, tables_used->table->db_type));
@@ -2480,7 +2491,7 @@ TABLE_COUNTER_TYPE Query_cache::is_cacheable(THD *thd, uint32 query_len,
{
ha_myisammrg *handler = (ha_myisammrg *)tables_used->table->file;
MYRG_INFO *file = handler->myrg_info();
- tables+= (file->end_table - file->open_tables);
+ table_count+= (file->end_table - file->open_tables);
}
}
@@ -2490,8 +2501,8 @@ TABLE_COUNTER_TYPE Query_cache::is_cacheable(THD *thd, uint32 query_len,
DBUG_PRINT("qcache", ("not in autocommin mode"));
DBUG_RETURN(0);
}
- DBUG_PRINT("qcache", ("select is using %d tables", tables));
- DBUG_RETURN(tables);
+ DBUG_PRINT("qcache", ("select is using %d tables", table_count));
+ DBUG_RETURN(table_count);
}
DBUG_PRINT("qcache",
diff --git a/sql/sql_cache.h b/sql/sql_cache.h
index f19e6630da5..b15df28f54b 100644
--- a/sql/sql_cache.h
+++ b/sql/sql_cache.h
@@ -178,7 +178,7 @@ extern "C"
my_bool not_used);
}
void query_cache_insert(NET *thd, const char *packet, ulong length);
-void query_cache_invalidate_by_MyISAM_filename(const char* filename);
+extern "C" void query_cache_invalidate_by_MyISAM_filename(const char* filename);
struct Query_cache_memory_bin
@@ -219,7 +219,7 @@ public:
ulong query_cache_size, query_cache_limit;
/* statistics */
ulong free_memory, queries_in_cache, hits, inserts, refused,
- free_memory_blocks, total_blocks;
+ free_memory_blocks, total_blocks, lowmem_prunes;
protected:
/*
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index b7cca50ffb5..e3ee0fb9f72 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -59,14 +59,14 @@ template class List_iterator<Alter_column>;
** User variables
****************************************************************************/
-static byte* get_var_key(user_var_entry *entry, uint *length,
- my_bool not_used __attribute__((unused)))
+extern "C" byte *get_var_key(user_var_entry *entry, uint *length,
+ my_bool not_used __attribute__((unused)))
{
*length=(uint) entry->name.length;
return (byte*) entry->name.str;
}
-static void free_var(user_var_entry *entry)
+extern "C" void free_user_var(user_var_entry *entry)
{
char *pos= (char*) entry+ALIGN_SIZE(sizeof(*entry));
if (entry->value && entry->value != pos)
@@ -88,9 +88,6 @@ THD::THD():user_time(0), fatal_error(0),
host_or_ip="unknown ip";
locked=killed=count_cuted_fields=some_tables_deleted=no_errors=password=
query_start_used=safe_to_cache_query=prepare_command=0;
- pthread_mutex_lock(&LOCK_global_system_variables);
- variables= global_system_variables;
- pthread_mutex_unlock(&LOCK_global_system_variables);
db_length=query_length=col_access=0;
query_error=0;
next_insert_id=last_insert_id=0;
@@ -133,19 +130,12 @@ THD::THD():user_time(0), fatal_error(0),
server_id = ::server_id;
slave_net = 0;
log_pos = 0;
- server_status= SERVER_STATUS_AUTOCOMMIT;
- update_lock_default= (variables.low_priority_updates ?
- TL_WRITE_LOW_PRIORITY :
- TL_WRITE);
- options= thd_startup_options;
- sql_mode=(uint) opt_sql_mode;
- open_options=ha_open_options;
- session_tx_isolation= (enum_tx_isolation) variables.tx_isolation;
command=COM_CONNECT;
set_query_id=1;
db_access=NO_ACCESS;
version=refresh_version; // For boot
+ init();
/* Initialize sub structures */
bzero((char*) &mem_root,sizeof(mem_root));
bzero((char*) &transaction.mem_root,sizeof(transaction.mem_root));
@@ -157,7 +147,7 @@ THD::THD():user_time(0), fatal_error(0),
user_connect=(USER_CONN *)0;
hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0,
(hash_get_key) get_var_key,
- (void (*)(void*)) free_var,0);
+ (hash_free_key) free_user_var,0);
/* Prepared statements */
last_prepared_stmt= 0;
@@ -190,6 +180,48 @@ THD::THD():user_time(0), fatal_error(0),
}
}
+
+/*
+ Init common variables that has to be reset on start and on change_user
+*/
+
+void THD::init(void)
+{
+ server_status= SERVER_STATUS_AUTOCOMMIT;
+ update_lock_default= (variables.low_priority_updates ?
+ TL_WRITE_LOW_PRIORITY :
+ TL_WRITE);
+ options= thd_startup_options;
+ sql_mode=(uint) opt_sql_mode;
+ open_options=ha_open_options;
+ pthread_mutex_lock(&LOCK_global_system_variables);
+ variables= global_system_variables;
+ pthread_mutex_unlock(&LOCK_global_system_variables);
+ session_tx_isolation= (enum_tx_isolation) variables.tx_isolation;
+}
+
+/*
+ Do what's needed when one invokes change user
+
+ SYNOPSIS
+ change_user()
+
+ IMPLEMENTATION
+ Reset all resources that are connection specific
+*/
+
+
+void THD::change_user(void)
+{
+ cleanup();
+ cleanup_done=0;
+ init();
+ hash_init(&user_vars, USER_VARS_HASH_SIZE, 0, 0,
+ (hash_get_key) get_var_key,
+ (hash_free_key) free_user_var,0);
+}
+
+
/* Do operations that may take a long time */
void THD::cleanup(void)
@@ -207,17 +239,21 @@ void THD::cleanup(void)
close_thread_tables(this);
}
close_temporary_tables(this);
-#ifdef USING_TRANSACTIONS
- if (opt_using_transactions)
+ hash_free(&user_vars);
+ if (global_read_lock)
+ unlock_global_read_lock(this);
+ if (ull)
{
- close_cached_file(&transaction.trans_log);
- ha_close_connection(this);
+ pthread_mutex_lock(&LOCK_user_locks);
+ item_user_lock_release(ull);
+ pthread_mutex_unlock(&LOCK_user_locks);
+ ull= 0;
}
-#endif
cleanup_done=1;
DBUG_VOID_RETURN;
}
+
THD::~THD()
{
THD_CHECK_SENTRY(this);
@@ -234,15 +270,13 @@ THD::~THD()
}
if (!cleanup_done)
cleanup();
- if (global_read_lock)
- unlock_global_read_lock(this);
- if (ull)
+#ifdef USING_TRANSACTIONS
+ if (opt_using_transactions)
{
- pthread_mutex_lock(&LOCK_user_locks);
- item_user_lock_release(ull);
- pthread_mutex_unlock(&LOCK_user_locks);
+ close_cached_file(&transaction.trans_log);
+ ha_close_connection(this);
}
- hash_free(&user_vars);
+#endif
DBUG_PRINT("info", ("freeing host"));
if (host != localhost) // If not pointer to constant
@@ -338,20 +372,21 @@ void THD::add_changed_table(TABLE *table)
DBUG_VOID_RETURN;
}
+
void THD::add_changed_table(const char *key, long key_length)
{
DBUG_ENTER("THD::add_changed_table(key)");
- CHANGED_TABLE_LIST** prev = &transaction.changed_tables;
- CHANGED_TABLE_LIST* curr = transaction.changed_tables;
+ CHANGED_TABLE_LIST **prev_changed = &transaction.changed_tables;
+ CHANGED_TABLE_LIST *curr = transaction.changed_tables;
- for (; curr; prev = &(curr->next), curr = curr->next)
+ for (; curr; prev_changed = &(curr->next), curr = curr->next)
{
int cmp = (long)curr->key_length - (long)key_length;
if (cmp < 0)
{
- list_include(prev, curr, changed_table_dup(key, key_length));
+ list_include(prev_changed, curr, changed_table_dup(key, key_length));
DBUG_PRINT("info",
- ("key_length %u %u", key_length, (*prev)->key_length));
+ ("key_length %u %u", key_length, (*prev_changed)->key_length));
DBUG_VOID_RETURN;
}
else if (cmp == 0)
@@ -359,10 +394,10 @@ void THD::add_changed_table(const char *key, long key_length)
cmp = memcmp(curr->key, key, curr->key_length);
if (cmp < 0)
{
- list_include(prev, curr, changed_table_dup(key, key_length));
+ list_include(prev_changed, curr, changed_table_dup(key, key_length));
DBUG_PRINT("info",
("key_length %u %u", key_length,
- (*prev)->key_length));
+ (*prev_changed)->key_length));
DBUG_VOID_RETURN;
}
else if (cmp == 0)
@@ -372,9 +407,9 @@ void THD::add_changed_table(const char *key, long key_length)
}
}
}
- *prev = changed_table_dup(key, key_length);
+ *prev_changed = changed_table_dup(key, key_length);
DBUG_PRINT("info", ("key_length %u %u", key_length,
- (*prev)->key_length));
+ (*prev_changed)->key_length));
DBUG_VOID_RETURN;
}
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 9a7ee4556e8..acdf2471ba8 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -488,6 +488,7 @@ public:
uint total_warn_count, old_total_warn_count;
ulong query_id, warn_id, version, options, thread_id, col_access;
ulong current_stmt_id;
+ ulong rand_saved_seed1, rand_saved_seed2;
long dbug_thread_id;
pthread_t real_id;
uint current_tablenr,tmp_table,cond_count;
@@ -504,7 +505,6 @@ public:
bool set_query_id,locked,count_cuted_fields,some_tables_deleted;
bool no_errors, allow_sum_func, password, fatal_error;
bool query_start_used,last_insert_id_used,insert_id_used,rand_used;
- ulonglong rand_saved_seed1, rand_saved_seed2;
bool system_thread,in_lock_tables,global_read_lock;
bool query_error, bootstrap, cleanup_done;
bool safe_to_cache_query;
@@ -534,6 +534,8 @@ public:
THD();
~THD();
+ void init(void);
+ void change_user(void);
void cleanup(void);
bool store_globals();
#ifdef SIGNAL_WITH_VIO_CLOSE
@@ -932,11 +934,9 @@ public:
ha_rows deleted;
uint num_of_tables;
int error;
- thr_lock_type lock_option;
- bool do_delete, not_trans_safe;
+ bool do_delete, transactional_tables, log_delayed, normal_tables;
public:
- multi_delete(THD *thd, TABLE_LIST *dt, thr_lock_type lock_option_arg,
- uint num_of_tables);
+ multi_delete(THD *thd, TABLE_LIST *dt, uint num_of_tables);
~multi_delete();
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
bool send_fields(List<Item> &list,
@@ -956,7 +956,6 @@ public:
ha_rows updated, found;
List<Item> fields;
List <Item> **fields_by_tables;
- thr_lock_type lock_option;
enum enum_duplicates dupl;
uint num_of_tables, num_fields, num_updated, *save_time_stamps, *field_sequence;
int error;
@@ -964,7 +963,7 @@ public:
public:
multi_update(THD *thd_arg, TABLE_LIST *ut, List<Item> &fs,
enum enum_duplicates handle_duplicates,
- thr_lock_type lock_option_arg, uint num);
+ uint num);
~multi_update();
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
bool send_fields(List<Item> &list,
diff --git a/sql/sql_db.cc b/sql/sql_db.cc
index b80e25c9f40..cefad6a0805 100644
--- a/sql/sql_db.cc
+++ b/sql/sql_db.cc
@@ -220,7 +220,7 @@ int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info,
if (!thd->query) // Only in replication
{
query= path;
- query_length= (uint) (strxmov(path,"create database ", db, NullS) -
+ query_length= (uint) (strxmov(path,"create database `", db, "`", NullS) -
path);
}
else
@@ -231,7 +231,7 @@ int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info,
mysql_update_log.write(thd, query, query_length);
if (mysql_bin_log.is_open())
{
- Query_log_event qinfo(thd, query, query_length);
+ Query_log_event qinfo(thd, query, query_length, 0);
mysql_bin_log.write(&qinfo);
}
send_ok(thd, result);
@@ -346,22 +346,25 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
query_cache_invalidate1(db);
if (!silent)
{
+ const char *query;
+ ulong query_length;
if (!thd->query)
{
- thd->query = path;
- thd->query_length = (uint) (strxmov(path,"drop database ", db, NullS)-
- path);
+ /* The client used the old obsolete mysql_drop_db() call */
+ query= path;
+ query_length = (uint) (strxmov(path,"drop database `", db, "`",
+ NullS)- path);
}
- mysql_update_log.write(thd, thd->query, thd->query_length);
- if (mysql_bin_log.is_open())
+ else
{
- Query_log_event qinfo(thd, thd->query, thd->query_length);
- mysql_bin_log.write(&qinfo);
+ query=thd->query;
+ query_length=thd->query_length;
}
- if (thd->query == path)
+ mysql_update_log.write(thd, query, query_length);
+ if (mysql_bin_log.is_open())
{
- thd->query = 0; // just in case
- thd->query_length = 0;
+ Query_log_event qinfo(thd, query, query_length, 0);
+ mysql_bin_log.write(&qinfo);
}
send_ok(thd,(ulong) deleted);
}
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index 811cc7c5f5e..cc60ebfb58d 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -28,20 +28,18 @@
#include "sql_select.h"
int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order,
- ha_rows limit, thr_lock_type lock_type, ulong options)
+ ha_rows limit, ulong options)
{
int error;
TABLE *table;
SQL_SELECT *select=0;
READ_RECORD info;
bool using_limit=limit != HA_POS_ERROR;
- bool using_transactions, safe_update, const_cond;
+ bool using_transactions, log_delayed, safe_update, const_cond;
ha_rows deleted;
DBUG_ENTER("mysql_delete");
- if (!table_list->db)
- table_list->db=thd->db;
- if (!(table = open_ltable(thd,table_list, lock_type)))
+ if (!(table = open_ltable(thd, table_list, table_list->lock_type)))
DBUG_RETURN(-1);
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
thd->proc_info="init";
@@ -162,23 +160,34 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order,
(void) table->file->extra(HA_EXTRA_NORMAL);
cleanup:
- using_transactions=table->file->has_transactions();
- if (deleted && (error <= 0 || !using_transactions))
+ transactional_table= table->file->has_transactions();
+ log_delayed= (transactional_table || table->tmp_table);
+ if (deleted && (error <= 0 || !transactional_table))
{
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,
- using_transactions);
- if (mysql_bin_log.write(&qinfo) && using_transactions)
+ log_delayed);
+ if (mysql_bin_log.write(&qinfo) && transactional_table)
error=1;
}
- if (!using_transactions)
+ if (!log_delayed)
thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
}
- if (using_transactions && ha_autocommit_or_rollback(thd,error >= 0))
- error=1;
- if (deleted)
+ if (transactional_table)
+ {
+ if (ha_autocommit_or_rollback(thd,error >= 0))
+ error=1;
+ }
+ /*
+ Only invalidate the query cache if something changed or if we
+ didn't commit the transacion (query cache is automaticly
+ invalidated on commit)
+ */
+ if (deleted &&
+ (!transactional_table ||
+ thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))
{
query_cache_invalidate3(thd, table_list, 1);
}
@@ -205,19 +214,17 @@ cleanup:
#define MEM_STRIP_BUF_SIZE current_thd->variables.sortbuff_size
-int refposcmp2(void* arg, const void *a,const void *b)
+extern "C" int refposcmp2(void* arg, const void *a,const void *b)
{
return memcmp(a,b, *(int*) arg);
}
multi_delete::multi_delete(THD *thd_arg, TABLE_LIST *dt,
- thr_lock_type lock_option_arg,
uint num_of_tables_arg)
: delete_tables (dt), thd(thd_arg), deleted(0),
- num_of_tables(num_of_tables_arg), error(0), lock_option(lock_option_arg),
- do_delete(false)
+ num_of_tables(num_of_tables_arg), error(0),
+ do_delete(0), transactional_tables(0), log_delayed(0), normal_tables(0)
{
- not_trans_safe=false;
tempfiles = (Unique **) sql_calloc(sizeof(Unique *) * (num_of_tables-1));
}
@@ -268,8 +275,12 @@ multi_delete::initialize_tables(JOIN *join)
/* Don't use KEYREAD optimization on this table */
tbl->no_keyread=1;
walk=walk->next;
- if (!not_trans_safe && !tbl->file->has_transactions())
- not_trans_safe=true;
+ if (tbl->file->has_transactions())
+ log_delayed= transactional_tables= 1;
+ else if (tbl->tmp_table != NO_TMP_TABLE)
+ log_delayed= 1;
+ else
+ normal_tables= 1;
}
}
walk= delete_tables;
@@ -375,7 +386,7 @@ void multi_delete::send_error(uint errcode,const char *err)
In all other cases do attempt deletes ...
*/
if ((table_being_deleted->table->file->has_transactions() &&
- table_being_deleted == delete_tables) || !not_trans_safe)
+ table_being_deleted == delete_tables) || !normal_tables)
ha_rollback_stmt(thd);
else if (do_delete)
{
@@ -394,7 +405,7 @@ void multi_delete::send_error(uint errcode,const char *err)
int multi_delete::do_deletes(bool from_send_error)
{
- int error = 0, counter = 0;
+ int local_error= 0, counter= 0;
if (from_send_error)
{
@@ -415,27 +426,26 @@ int multi_delete::do_deletes(bool from_send_error)
TABLE *table = table_being_deleted->table;
if (tempfiles[counter]->get(table))
{
- error=1;
+ local_error=1;
break;
}
READ_RECORD info;
init_read_record(&info,thd,table,NULL,0,0);
- while (!(error=info.read_record(&info)) &&
- (!thd->killed || from_send_error || not_trans_safe))
+ while (!(local_error=info.read_record(&info)) && !thd->killed)
{
- if ((error=table->file->delete_row(table->record[0])))
+ if ((local_error=table->file->delete_row(table->record[0])))
{
- table->file->print_error(error,MYF(0));
+ table->file->print_error(local_error,MYF(0));
break;
}
deleted++;
}
end_read_record(&info);
- if (error == -1) // End of file
- error = 0;
+ if (local_error == -1) // End of file
+ local_error = 0;
}
- return error;
+ return local_error;
}
@@ -451,15 +461,11 @@ bool multi_delete::send_eof()
thd->proc_info="deleting from reference tables";
/* Does deletes for the last n - 1 tables, returns 0 if ok */
- int error = do_deletes(0); // returns 0 if success
+ int local_error= do_deletes(0); // returns 0 if success
/* reset used flags */
thd->proc_info="end";
- if (error)
- {
- ::send_error(thd);
- return 1;
- }
+
/*
Write the SQL statement to the binlog if we deleted
@@ -467,24 +473,25 @@ bool multi_delete::send_eof()
was a non-transaction-safe table involved, since
modifications in it cannot be rolled back.
*/
- if (deleted || not_trans_safe)
+ if (deleted)
{
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);
- if (mysql_bin_log.write(&qinfo) &&
- !not_trans_safe)
- error=1; // Log write failed: roll back the SQL statement
+ Query_log_event qinfo(thd, thd->query, thd->query_length,
+ log_delayed);
+ if (mysql_bin_log.write(&qinfo) && !normal_tables)
+ local_error=1; // Log write failed: roll back the SQL statement
}
/* Commit or rollback the current SQL statement */
- VOID(ha_autocommit_or_rollback(thd,error > 0));
- }
- if (deleted)
- {
+ VOID(ha_autocommit_or_rollback(thd,local_error > 0));
+
query_cache_invalidate3(thd, delete_tables, 1);
}
- ::send_ok(thd,deleted);
+ if (local_error)
+ ::send_error(thd);
+ else
+ ::send_ok(thd, deleted);
return 0;
}
@@ -557,8 +564,9 @@ int mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok)
if (!ha_supports_generate(table_type))
{
/* Probably InnoDB table */
- DBUG_RETURN(mysql_delete(thd,table_list, (COND*) 0, (ORDER*) 0,
- HA_POS_ERROR, TL_WRITE, 0));
+ table_list->lock_type= TL_WRITE;
+ DBUG_RETURN(mysql_delete(thd, table_list, (COND*) 0, (ORDER*) 0,
+ HA_POS_ERROR, 0));
}
if (lock_and_wait_for_table_name(thd, table_list))
DBUG_RETURN(-1);
@@ -570,6 +578,7 @@ int mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok)
*fn_ext(path)=0; // Remove the .frm extension
error= ha_create_table(path,&create_info,1) ? -1 : 0;
query_cache_invalidate3(thd, table_list, 0);
+
end:
if (!dont_send_ok)
{
@@ -578,7 +587,8 @@ end:
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);
+ Query_log_event qinfo(thd, thd->query, thd->query_length,
+ thd->tmp_table);
mysql_bin_log.write(&qinfo);
}
send_ok(thd); // This should return record count
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 0a1b4435fff..6cb146afb33 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -25,7 +25,7 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list);
static int write_delayed(THD *thd,TABLE *table, enum_duplicates dup,
char *query, uint query_length, bool log_on);
static void end_delayed_insert(THD *thd);
-static pthread_handler_decl(handle_delayed_insert,arg);
+extern "C" pthread_handler_decl(handle_delayed_insert,arg);
static void unlink_blobs(register TABLE *table);
/* Define to force use of my_malloc() if the allocated memory block is big */
@@ -98,13 +98,12 @@ check_insert_fields(THD *thd,TABLE *table,List<Item> &fields,
int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
- List<List_item> &values_list,enum_duplicates duplic,
- thr_lock_type lock_type)
+ List<List_item> &values_list,enum_duplicates duplic)
{
int error;
bool log_on= ((thd->options & OPTION_UPDATE_LOG) ||
!(thd->master_access & SUPER_ACL));
- bool using_transactions, bulk_insert=0;
+ bool transactional_table, log_delayed, bulk_insert=0;
uint value_count;
uint save_time_stamp;
ulong counter = 1;
@@ -114,6 +113,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
List_iterator_fast<List_item> its(values_list);
List_item *values;
char *query=thd->query;
+ thr_lock_type lock_type = table_list->lock_type;
DBUG_ENTER("mysql_insert");
/*
@@ -194,14 +194,19 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
thd->proc_info="update";
if (duplic == DUP_IGNORE || duplic == DUP_REPLACE)
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
- if ((bulk_insert= (values_list.elements > 1 &&
+ if ((bulk_insert= (values_list.elements >= MIN_ROWS_TO_USE_BULK_INSERT &&
lock_type != TL_WRITE_DELAYED &&
!(specialflag & SPECIAL_SAFE_MODE))))
{
table->file->extra_opt(HA_EXTRA_WRITE_CACHE,
- thd->variables.read_buff_size);
- table->file->extra_opt(HA_EXTRA_BULK_INSERT_BEGIN,
- thd->variables.bulk_insert_buff_size);
+ min(thd->variables.read_buff_size,
+ table->avg_row_length*values_list.elements));
+ if (thd->variables.bulk_insert_buff_size)
+ table->file->extra_opt(HA_EXTRA_BULK_INSERT_BEGIN,
+ min(thd->variables.bulk_insert_buff_size,
+ (table->total_key_length +
+ table->keys * TREE_ELEMENT_EXTRA_SIZE)*
+ values_list.elements));
table->bulk_insert= 1;
}
@@ -266,10 +271,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
info.copied=values_list.elements;
end_delayed_insert(thd);
}
- if (info.copied || info.deleted)
- {
- query_cache_invalidate3(thd, table_list, 1);
- }
+ query_cache_invalidate3(thd, table_list, 1);
}
else
{
@@ -297,23 +299,33 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
thd->insert_id(id); // For update log
else if (table->next_number_field)
id=table->next_number_field->val_int(); // Return auto_increment value
- using_transactions=table->file->has_transactions();
- if ((info.copied || info.deleted) && (error <= 0 || !using_transactions))
+
+ transactional_table= table->file->has_transactions();
+ log_delayed= (transactional_table || table->tmp_table);
+ if ((info.copied || info.deleted) && (error <= 0 || !transactional_table))
{
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,
- using_transactions);
- if (mysql_bin_log.write(&qinfo) && using_transactions)
+ log_delayed);
+ if (mysql_bin_log.write(&qinfo) && transactional_table)
error=1;
}
- if (!using_transactions)
+ if (!log_delayed)
thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
}
- if (using_transactions)
+ if (transactional_table)
error=ha_autocommit_or_rollback(thd,error);
- if (info.copied || info.deleted)
+
+ /*
+ Only invalidate the query cache if something changed or if we
+ didn't commit the transacion (query cache is automaticly
+ invalidated on commit)
+ */
+ if ((info.copied || info.deleted) &&
+ (!transactional_table ||
+ thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))
{
query_cache_invalidate3(thd, table_list, 1);
}
@@ -913,7 +925,7 @@ void kill_delayed_threads(void)
* Create a new delayed insert thread
*/
-static pthread_handler_decl(handle_delayed_insert,arg)
+extern "C" pthread_handler_decl(handle_delayed_insert,arg)
{
delayed_insert *di=(delayed_insert*) arg;
THD *thd= &di->thd;
@@ -1197,7 +1209,7 @@ bool delayed_insert::handle_inserts(void)
mysql_update_log.write(&thd,row->query, row->query_length);
if (using_bin_log)
{
- Query_log_event qinfo(&thd, row->query, row->query_length);
+ Query_log_event qinfo(&thd, row->query, row->query_length,0);
mysql_bin_log.write(&qinfo);
}
}
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 6bafef8a469..9f8e3200246 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -436,9 +436,9 @@ typedef struct st_lex
uint grant, grant_tot_col, which_columns;
uint fk_delete_opt, fk_update_opt, fk_match_option;
uint param_count;
- bool drop_primary, drop_if_exists, local_file, olap;
+ bool drop_primary, drop_if_exists, drop_temporary, local_file;
bool in_comment, ignore_space, verbose, simple_alter;
- bool derived_tables, describe;
+ bool derived_tables, describe, olap;
uint slave_thd_opt;
CHARSET_INFO *charset;
char *help_arg;
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index 52d1f3adf48..00450a3b86c 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -90,7 +90,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
bool is_fifo=0;
LOAD_FILE_INFO lf_info;
char * db = table_list->db ? table_list->db : thd->db;
- bool using_transactions;
+ bool transactional_table, log_delayed;
DBUG_ENTER("mysql_load");
#ifdef EMBEDDED_LIBRARY
@@ -105,6 +105,9 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
}
if (!(table = open_ltable(thd,table_list,lock_type)))
DBUG_RETURN(-1);
+ transactional_table= table->file->has_transactions();
+ log_delayed= (transactional_table || table->tmp_table);
+
if (!fields.elements)
{
Field **field;
@@ -224,6 +227,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
lf_info.handle_dup = handle_duplicates;
lf_info.wrote_create_file = 0;
lf_info.last_pos_in_file = HA_POS_ERROR;
+ lf_info.log_delayed= log_delayed;
read_info.set_io_cache_arg((void*) &lf_info);
}
restore_record(table,2);
@@ -275,16 +279,16 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
free_blobs(table); /* if pack_blob was used */
table->copy_blobs=0;
thd->count_cuted_fields=0; /* Don`t calc cuted fields */
- using_transactions = table->file->has_transactions();
+
if (error)
{
- if (using_transactions)
+ if (transactional_table)
ha_autocommit_or_rollback(thd,error);
if (!opt_old_rpl_compat && mysql_bin_log.is_open())
{
if (lf_info.wrote_create_file)
{
- Delete_file_log_event d(thd);
+ Delete_file_log_event d(thd, log_delayed);
mysql_bin_log.write(&d);
}
}
@@ -297,27 +301,30 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
if (!thd->slave_thread)
mysql_update_log.write(thd,thd->query,thd->query_length);
- if (!using_transactions)
+ if (!log_delayed)
thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
if (mysql_bin_log.is_open())
{
- if (opt_old_rpl_compat && !read_file_from_client)
+ if (opt_old_rpl_compat)
{
- Load_log_event qinfo(thd, ex, db, table->table_name, fields,
- handle_duplicates);
- mysql_bin_log.write(&qinfo);
+ if (!read_file_from_client)
+ {
+ Load_log_event qinfo(thd, ex, db, table->table_name, fields,
+ handle_duplicates, log_delayed);
+ mysql_bin_log.write(&qinfo);
+ }
}
- if (!opt_old_rpl_compat)
+ else
{
read_info.end_io_cache(); // make sure last block gets logged
if (lf_info.wrote_create_file)
{
- Execute_load_log_event e(thd);
+ Execute_load_log_event e(thd, log_delayed);
mysql_bin_log.write(&e);
}
}
}
- if (using_transactions)
+ if (transactional_table)
error=ha_autocommit_or_rollback(thd,error);
DBUG_RETURN(error);
}
diff --git a/sql/sql_manager.cc b/sql/sql_manager.cc
index 13cac83fc3f..0af6a80d4c2 100644
--- a/sql/sql_manager.cc
+++ b/sql/sql_manager.cc
@@ -32,7 +32,7 @@ pthread_t manager_thread;
pthread_mutex_t LOCK_manager;
pthread_cond_t COND_manager;
-pthread_handler_decl(handle_manager,arg __attribute__((unused)))
+extern "C" pthread_handler_decl(handle_manager,arg __attribute__((unused)))
{
int error = 0;
ulong status;
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index aebccf7a39e..4816a0539f3 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -98,7 +98,17 @@ static void init_signals(void)
}
#endif
-inline bool end_active_trans(THD *thd)
+static void unlock_locked_tables(THD *thd)
+{
+ if (thd->locked_tables)
+ {
+ thd->lock=thd->locked_tables;
+ thd->locked_tables=0; // Will be automaticly closed
+ close_thread_tables(thd); // Free tables
+ }
+}
+
+static bool end_active_trans(THD *thd)
{
int error=0;
if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN |
@@ -257,14 +267,14 @@ static bool check_user(THD *thd,enum_server_command command, const char *user,
started with corresponding variable that is greater then 0.
*/
-static byte* get_key_conn(user_conn *buff, uint *length,
- my_bool not_used __attribute__((unused)))
+extern "C" byte *get_key_conn(user_conn *buff, uint *length,
+ my_bool not_used __attribute__((unused)))
{
*length=buff->len;
return (byte*) buff->user;
}
-static void free_user(struct user_conn *uc)
+extern "C" void free_user(struct user_conn *uc)
{
my_free((char*) uc,MYF(0));
}
@@ -273,7 +283,7 @@ void init_max_user_conn(void)
{
(void) hash_init(&hash_user_connections,system_charset_info,max_connections,
0,0,
- (hash_get_key) get_key_conn, (void (*)(void*)) free_user,
+ (hash_get_key) get_key_conn, (hash_free_key) free_user,
0);
}
@@ -552,7 +562,13 @@ check_connections(THD *thd)
{
/* Do the SSL layering. */
DBUG_PRINT("info", ("IO layer change in progress..."));
- sslaccept(ssl_acceptor_fd, net->vio, thd->variables.net_wait_timeout);
+ if (sslaccept(ssl_acceptor_fd, net->vio, thd->variables.net_wait_timeout))
+ {
+ DBUG_PRINT("error", ("Failed to read user information (pkt_len= %lu)",
+ pkt_len));
+ inc_host_errors(&thd->remote.sin_addr);
+ return(ER_HANDSHAKE_ERROR);
+ }
DBUG_PRINT("info", ("Reading user information over SSL layer"));
if ((pkt_len=my_net_read(net)) == packet_error ||
pkt_len < NORMAL_HANDSHAKE_SIZE)
@@ -690,7 +706,7 @@ pthread_handler_decl(handle_one_connection,arg)
(net->last_errno ? ER(net->last_errno) :
ER(ER_UNKNOWN_ERROR)));
send_error(thd,net->last_errno,NullS);
- thread_safe_increment(aborted_threads,&LOCK_status);
+ statistic_increment(aborted_threads,&LOCK_status);
}
end_thread:
@@ -711,7 +727,7 @@ end_thread:
Used when creating the initial grant tables
*/
-pthread_handler_decl(handle_bootstrap,arg)
+extern "C" pthread_handler_decl(handle_bootstrap,arg)
{
THD *thd=(THD*) arg;
FILE *file=bootstrap_file;
@@ -903,7 +919,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
thd->lex.select_lex.options=0; // We store status here
switch (command) {
case COM_INIT_DB:
- thread_safe_increment(com_stat[SQLCOM_CHANGE_DB],&LOCK_status);
+ statistic_increment(com_stat[SQLCOM_CHANGE_DB],&LOCK_status);
if (!mysql_change_db(thd,packet))
mysql_log.write(thd,command,"%s",thd->db);
break;
@@ -915,7 +931,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
}
case COM_TABLE_DUMP:
{
- thread_safe_increment(com_other, &LOCK_status);
+ statistic_increment(com_other, &LOCK_status);
slow_command = TRUE;
uint db_len = *(uchar*)packet;
uint tbl_len = *(uchar*)(packet + db_len + 1);
@@ -932,7 +948,10 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
}
case COM_CHANGE_USER:
{
- thread_safe_increment(com_other,&LOCK_status);
+ thd->change_user();
+ clear_error_message(thd); // If errors from rollback
+
+ statistic_increment(com_other,&LOCK_status);
char *user= (char*) packet;
char *passwd= strend(user)+1;
char *db= strend(passwd)+1;
@@ -1005,7 +1024,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
{
char *fields;
TABLE_LIST table_list;
- thread_safe_increment(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))
{
@@ -1040,7 +1059,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
case COM_CREATE_DB: // QQ: To be removed
{
- thread_safe_increment(com_stat[SQLCOM_CREATE_DB],&LOCK_status);
+ statistic_increment(com_stat[SQLCOM_CREATE_DB],&LOCK_status);
char *db=thd->strdup(packet);
// null test to handle EOM
if (!db || !strip_sp(db) || check_db_name(db))
@@ -1058,7 +1077,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
}
case COM_DROP_DB: // QQ: To be removed
{
- thread_safe_increment(com_stat[SQLCOM_DROP_DB],&LOCK_status);
+ statistic_increment(com_stat[SQLCOM_DROP_DB],&LOCK_status);
char *db=thd->strdup(packet);
// null test to handle EOM
if (!db || !strip_sp(db) || check_db_name(db))
@@ -1079,7 +1098,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
}
case COM_BINLOG_DUMP:
{
- thread_safe_increment(com_other,&LOCK_status);
+ statistic_increment(com_other,&LOCK_status);
slow_command = TRUE;
if (check_global_access(thd, REPL_SLAVE_ACL))
break;
@@ -1103,7 +1122,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
}
case COM_REFRESH:
{
- thread_safe_increment(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;
@@ -1115,7 +1134,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
break;
}
case COM_SHUTDOWN:
- thread_safe_increment(com_other,&LOCK_status);
+ statistic_increment(com_other,&LOCK_status);
if (check_global_access(thd,SHUTDOWN_ACL))
break; /* purecov: inspected */
DBUG_PRINT("quit",("Got shutdown command"));
@@ -1138,7 +1157,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
case COM_STATISTICS:
{
mysql_log.write(thd,command,NullS);
- thread_safe_increment(com_stat[SQLCOM_SHOW_STATUS],&LOCK_status);
+ statistic_increment(com_stat[SQLCOM_SHOW_STATUS],&LOCK_status);
char buff[200];
ulong uptime = (ulong) (thd->start_time - start_time);
sprintf((char*) buff,
@@ -1157,11 +1176,11 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
break;
}
case COM_PING:
- thread_safe_increment(com_other,&LOCK_status);
+ statistic_increment(com_other,&LOCK_status);
send_ok(thd); // Tell client we are alive
break;
case COM_PROCESS_INFO:
- thread_safe_increment(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);
@@ -1170,13 +1189,13 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
break;
case COM_PROCESS_KILL:
{
- thread_safe_increment(com_stat[SQLCOM_KILL],&LOCK_status);
+ statistic_increment(com_stat[SQLCOM_KILL],&LOCK_status);
ulong id=(ulong) uint4korr(packet);
kill_one_thread(thd,id);
break;
}
case COM_DEBUG:
- thread_safe_increment(com_other,&LOCK_status);
+ statistic_increment(com_other,&LOCK_status);
if (check_global_access(thd, SUPER_ACL))
break; /* purecov: inspected */
mysql_print_status(thd);
@@ -1355,7 +1374,7 @@ mysql_execute_command(THD *thd)
!tables_ok(thd,tables)))
DBUG_VOID_RETURN;
- thread_safe_increment(com_stat[lex->sql_command],&LOCK_status);
+ statistic_increment(com_stat[lex->sql_command],&LOCK_status);
switch (lex->sql_command) {
case SQLCOM_SELECT:
{
@@ -1413,6 +1432,8 @@ mysql_execute_command(THD *thd)
Normal select:
Change lock if we are using SELECT HIGH PRIORITY,
FOR UPDATE or IN SHARE MODE
+
+ TODO: Delete the following loop when locks is set by sql_yacc
*/
TABLE_LIST *table;
for (table = tables ; table ; table=table->next)
@@ -1642,6 +1663,7 @@ mysql_execute_command(THD *thd)
TABLE_LIST *table;
if (check_table_access(thd, SELECT_ACL, tables->next))
goto error; // Error message is given
+ /* TODO: Delete the following loop when locks is set by sql_yacc */
for (table = tables->next ; table ; table=table->next)
table->lock_type= lex->lock_option;
}
@@ -1711,7 +1733,7 @@ mysql_execute_command(THD *thd)
#else
{
ulong priv=0;
- if (lex->name && strlen(lex->name) > NAME_LEN)
+ if (lex->name && (!lex->name[0] || strlen(lex->name) > NAME_LEN))
{
net_printf(thd,ER_WRONG_TABLE_NAME,lex->name);
res=0;
@@ -1885,18 +1907,13 @@ mysql_execute_command(THD *thd)
}
if (select_lex->table_list.elements == 1)
{
- res = mysql_update(thd,tables,
- select_lex->item_list,
- lex->value_list,
- select_lex->where,
- (ORDER *) select_lex->order_list.first,
- select_lex->select_limit,
- lex->duplicates,
- lex->lock_option);
-
-#ifdef DELETE_ITEMS
- delete select_lex->where;
-#endif
+ res= mysql_update(thd,tables,
+ select_lex->item_list,
+ lex->value_list,
+ select_lex->where,
+ (ORDER *) select_lex->order_list.first,
+ select_lex->select_limit,
+ lex->duplicates);
}
else
{
@@ -1906,11 +1923,8 @@ mysql_execute_command(THD *thd)
const char *msg=0;
lex->sql_command=SQLCOM_MULTI_UPDATE;
- for (auxi=(TABLE_LIST*) tables, table_count=0 ; auxi ; auxi=auxi->next)
- {
+ for (auxi= (TABLE_LIST*) tables, table_count=0 ; auxi ; auxi=auxi->next)
table_count++;
- auxi->lock_type=TL_WRITE;
- }
if (select_lex->order_list.elements)
msg="ORDER BY";
@@ -1932,8 +1946,7 @@ mysql_execute_command(THD *thd)
!setup_fields(thd,tables,lex->value_list,0,0,0) &&
!thd->fatal_error &&
(result=new multi_update(thd,tables,select_lex->item_list,
- lex->duplicates, lex->lock_option,
- table_count)))
+ lex->duplicates, table_count)))
{
List <Item> total_list;
List_iterator <Item> field_list(select_lex->item_list);
@@ -1964,8 +1977,7 @@ mysql_execute_command(THD *thd)
if (grant_option && check_grant(thd,INSERT_ACL,tables))
goto error;
res = mysql_insert(thd,tables,lex->field_list,lex->many_values,
- lex->duplicates,
- lex->lock_option);
+ lex->duplicates);
break;
case SQLCOM_REPLACE:
if (check_access(thd,INSERT_ACL | DELETE_ACL,
@@ -1976,8 +1988,7 @@ mysql_execute_command(THD *thd)
goto error;
res = mysql_insert(thd,tables,lex->field_list,lex->many_values,
- DUP_REPLACE,
- lex->lock_option);
+ DUP_REPLACE);
break;
case SQLCOM_REPLACE_SELECT:
case SQLCOM_INSERT_SELECT:
@@ -2012,8 +2023,8 @@ mysql_execute_command(THD *thd)
net_printf(thd,ER_INSERT_TABLE_USED,tables->real_name);
DBUG_VOID_RETURN;
}
- tables->lock_type=TL_WRITE; // update first table
{
+ /* TODO: Delete the following loop when locks is set by sql_yacc */
TABLE_LIST *table;
for (table = tables->next ; table ; table=table->next)
table->lock_type= lex->lock_option;
@@ -2056,8 +2067,7 @@ mysql_execute_command(THD *thd)
tables->grant.want_privilege=(SELECT_ACL & ~tables->grant.privilege);
res = mysql_delete(thd,tables, select_lex->where,
(ORDER*) select_lex->order_list.first,
- select_lex->select_limit, lex->lock_option,
- select_lex->options);
+ select_lex->select_limit, select_lex->options);
break;
}
case SQLCOM_DELETE_MULTI:
@@ -2093,7 +2103,7 @@ mysql_execute_command(THD *thd)
net_printf(thd,ER_NONUNIQ_TABLE,auxi->real_name);
goto error;
}
- auxi->lock_type=walk->lock_type=TL_WRITE;
+ walk->lock_type= auxi->lock_type;
auxi->table_list= walk; // Remember corresponding table
}
if (add_item_to_list(new Item_null()))
@@ -2108,7 +2118,6 @@ mysql_execute_command(THD *thd)
for (auxi=(TABLE_LIST*) aux_tables ; auxi ; auxi=auxi->next)
auxi->table= auxi->table_list->table;
if (!thd->fatal_error && (result= new multi_delete(thd,aux_tables,
- lex->lock_option,
table_count)))
{
res= mysql_select(thd,tables,select_lex->item_list,
@@ -2314,11 +2323,7 @@ mysql_execute_command(THD *thd)
send_ok(thd);
break;
case SQLCOM_UNLOCK_TABLES:
- if (thd->locked_tables)
- {
- thd->lock=thd->locked_tables;
- thd->locked_tables=0; // Will be automaticly closed
- }
+ unlock_locked_tables(thd);
if (thd->options & OPTION_TABLE_LOCK)
{
end_active_trans(thd);
@@ -2329,12 +2334,7 @@ mysql_execute_command(THD *thd)
send_ok(thd);
break;
case SQLCOM_LOCK_TABLES:
- if (thd->locked_tables)
- {
- thd->lock=thd->locked_tables;
- thd->locked_tables=0; // Will be automaticly closed
- close_thread_tables(thd);
- }
+ unlock_locked_tables(thd);
if (check_db_used(thd,tables) || end_active_trans(thd))
goto error;
if (check_table_access(thd, LOCK_TABLES_ACL | SELECT_ACL, tables))
@@ -2484,7 +2484,7 @@ mysql_execute_command(THD *thd)
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);
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
mysql_bin_log.write(&qinfo);
}
}
@@ -2504,7 +2504,7 @@ mysql_execute_command(THD *thd)
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);
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
mysql_bin_log.write(&qinfo);
}
if (mqh_used && lex->sql_command == SQLCOM_GRANT)
@@ -2874,7 +2874,7 @@ mysql_init_query(THD *thd)
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->fatal_error= thd->rand_used=0;
+ thd->fatal_error= thd->rand_used= 0;
thd->safe_to_cache_query= 1;
thd->possible_loops= 0;
DBUG_VOID_RETURN;
@@ -3476,14 +3476,50 @@ TABLE_LIST *st_select_lex::add_table_to_list(Table_ident *table,
}
+/*
+ Set lock for all tables in current select level
+
+ SYNOPSIS:
+ set_lock_for_tables()
+ lock_type Lock to set for tables
+
+ NOTE:
+ If lock is a write lock, then tables->updating is set 1
+ This is to get tables_ok to know that the table is updated by the
+ query
+*/
+
+void set_lock_for_tables(thr_lock_type lock_type)
+{
+ THD *thd=current_thd;
+ bool for_update= lock_type >= TL_READ_NO_INSERT;
+ DBUG_ENTER("set_lock_for_tables");
+ DBUG_PRINT("enter", ("lock_type: %d for_update: %d", lock_type,
+ for_update));
+
+ for (TABLE_LIST *tables= (TABLE_LIST*) thd->lex.select->table_list.first ;
+ tables ;
+ tables=tables->next)
+ {
+ tables->lock_type= lock_type;
+ tables->updating= for_update;
+ }
+ DBUG_VOID_RETURN;
+}
+
+
void add_join_on(TABLE_LIST *b,Item *expr)
{
- if (!b->on_expr)
- b->on_expr=expr;
- else
+ if (expr)
{
- // This only happens if you have both a right and left join
- b->on_expr=new Item_cond_and(b->on_expr,expr);
+ if (!b->on_expr)
+ b->on_expr=expr;
+ else
+ {
+ // 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();
}
}
@@ -3511,7 +3547,7 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables)
if (options & REFRESH_GRANT)
{
acl_reload(thd);
- grant_reload();
+ grant_reload(thd);
if (mqh_used)
reset_mqh(thd,(LEX_USER *) NULL,true);
}
diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc
index a9ab1776e19..5b0ec2ec843 100644
--- a/sql/sql_rename.cc
+++ b/sql/sql_rename.cc
@@ -94,7 +94,7 @@ end:
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);
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
mysql_bin_log.write(&qinfo);
}
send_ok(thd);
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index 93545d10268..23951cec29f 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -941,7 +941,7 @@ int show_binlog_events(THD* thd)
if (mysql_bin_log.is_open())
{
LEX_MASTER_INFO *lex_mi = &thd->lex.mi;
- uint event_count, limit_start, limit_end;
+ ha_rows event_count, limit_start, limit_end;
my_off_t pos = lex_mi->pos;
char search_file_name[FN_REFLEN], *name;
const char *log_file_name = lex_mi->log_file_name;
@@ -1133,7 +1133,8 @@ int log_loaded_block(IO_CACHE* file)
lf_info->last_pos_in_file = file->pos_in_file;
if (lf_info->wrote_create_file)
{
- Append_block_log_event a(lf_info->thd, buffer, block_len);
+ Append_block_log_event a(lf_info->thd, buffer, block_len,
+ lf_info->log_delayed);
mysql_bin_log.write(&a);
}
else
@@ -1141,7 +1142,7 @@ int log_loaded_block(IO_CACHE* file)
Create_file_log_event c(lf_info->thd,lf_info->ex,lf_info->db,
lf_info->table_name, *lf_info->fields,
lf_info->handle_dup, buffer,
- block_len);
+ block_len, lf_info->log_delayed);
mysql_bin_log.write(&c);
lf_info->wrote_create_file = 1;
DBUG_SYNC_POINT("debug_lock.created_file_event",10);
diff --git a/sql/sql_repl.h b/sql/sql_repl.h
index 197fd03ec7c..15435382b08 100644
--- a/sql/sql_repl.h
+++ b/sql/sql_repl.h
@@ -43,13 +43,13 @@ int check_binlog_magic(IO_CACHE* log, const char** errmsg);
typedef struct st_load_file_info
{
THD* thd;
+ my_off_t last_pos_in_file;
sql_exchange* ex;
List <Item> *fields;
enum enum_duplicates handle_dup;
char* db;
char* table_name;
- bool wrote_create_file;
- my_off_t last_pos_in_file;
+ bool wrote_create_file, log_delayed;
} LOAD_FILE_INFO;
int log_loaded_block(IO_CACHE* file);
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 05551980309..20b000392df 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -367,6 +367,7 @@ JOIN::optimize()
{
conds->fix_fields(thd, tables_list, &conds);
conds->change_ref_to_fields(thd, tables_list);
+ conds->top_level_item();
having= 0;
}
}
@@ -960,6 +961,7 @@ JOIN::exec()
sort_table_cond)))
DBUG_VOID_RETURN;
table->select_cond=table->select->cond;
+ table->select_cond->top_level_item();
DBUG_EXECUTE("where",print_where(table->select->cond,
"select and having"););
having_list= make_cond_for_table(having_list, ~ (table_map) 0,
@@ -1432,7 +1434,7 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
select->quick=0;
if (records != HA_POS_ERROR)
{
- s->found_records=records;
+ s->records=s->found_records=records;
s->read_time= (ha_rows) (s->quick ? s->quick->read_time : 0.0);
}
}
@@ -1965,7 +1967,7 @@ static void
find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
double read_time)
{
- ulong rec;
+ ha_rows rec;
double tmp;
THD *thd= join->thd;
@@ -2158,7 +2160,7 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
records
This gives the formula:
records= (x * (b-a) + a*c-b)/(c-1)
-
+
b = records matched by whole key
a = records matched by first key part (10% of all records?)
c = number of key parts in key
@@ -2227,7 +2229,7 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
{ // Check full join
if (s->on_expr)
{
- tmp=s->found_records; // Can't use read cache
+ tmp=rows2double(s->found_records); // Can't use read cache
}
else
{
@@ -2246,11 +2248,11 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
will ensure that this will be used
*/
best=tmp;
- records=s->found_records;
+ records= rows2double(s->found_records);
best_key=0;
}
}
- join->positions[idx].records_read=(double) records;
+ join->positions[idx].records_read= records;
join->positions[idx].key=best_key;
join->positions[idx].table= s;
if (!best_key && idx == join->const_tables &&
@@ -2587,7 +2589,7 @@ bool
store_val_in_field(Field *field,Item *item)
{
THD *thd=current_thd;
- ulong cuted_fields=thd->cuted_fields;
+ ha_rows cuted_fields=thd->cuted_fields;
thd->count_cuted_fields=1;
(void) item->save_in_field(field);
thd->count_cuted_fields=0;
@@ -2675,7 +2677,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
use_quick_range=1;
tab->use_quick=1;
tab->ref.key_parts=0; // Don't use ref key.
- join->best_positions[i].records_read=tab->quick->records;
+ join->best_positions[i].records_read= rows2double(tab->quick->records);
}
COND *tmp=make_cond_for_table(cond,used_tables,current_map);
@@ -3948,7 +3950,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
*blob_field= 0; // End marker
/* If result table is small; use a heap */
- if (blob_count || using_unique_constraint || group_null_items ||
+ if (blob_count || using_unique_constraint ||
(select_options & (OPTION_BIG_TABLES | SELECT_SMALL_RESULT)) ==
OPTION_BIG_TABLES)
{
@@ -5547,6 +5549,8 @@ end_write_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
}
else
{
+ if (end_of_records)
+ DBUG_RETURN(0);
join->first_record=1;
VOID(test_if_group_changed(join->group_fields));
}
@@ -5616,6 +5620,7 @@ make_cond_for_table(COND *cond,table_map tables,table_map used_table)
{
if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
{
+ /* Create new top level AND item */
Item_cond_and *new_cond=new Item_cond_and;
if (!new_cond)
return (COND*) 0; // OOM /* purecov: inspected */
@@ -5653,6 +5658,7 @@ make_cond_for_table(COND *cond,table_map tables,table_map used_table)
new_cond->argument_list()->push_back(fix);
}
new_cond->used_tables_cache=((Item_cond_or*) cond)->used_tables_cache;
+ new_cond->top_level_item();
return new_cond;
}
}
@@ -6004,6 +6010,7 @@ static bool fix_having(JOIN *join, Item **having)
sort_table_cond)))
return 1;
table->select_cond=table->select->cond;
+ table->select_cond->top_level_item();
DBUG_EXECUTE("where",print_where(table->select_cond,
"select and having"););
*having=make_cond_for_table(*having,~ (table_map) 0,~used_tables);
@@ -7432,56 +7439,32 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
{
if (tab->use_quick == 2)
{
- sprintf(buff_ptr,"range checked for each record (index map: %u)",
+ sprintf(buff_ptr,"; Range checked for each record (index map: %u)",
tab->keys);
buff_ptr=strend(buff_ptr);
}
else
- buff_ptr=strmov(buff_ptr,"where used");
+ buff_ptr=strmov(buff_ptr,"; Using where");
}
if (key_read)
- {
- if (buff != buff_ptr)
- {
- buff_ptr[0]=';' ; buff_ptr[1]=' '; buff_ptr+=2;
- }
- buff_ptr=strmov(buff_ptr,"Using index");
- }
+ buff_ptr= strmov(buff_ptr,"; Using index");
if (table->reginfo.not_exists_optimize)
- {
- if (buff != buff_ptr)
- {
- buff_ptr[0]=';' ; buff_ptr[1]=' '; buff_ptr+=2;
- }
- buff_ptr=strmov(buff_ptr,"Not exists");
- }
+ buff_ptr= strmov(buff_ptr,"; Not exists");
if (need_tmp_table)
{
need_tmp_table=0;
- if (buff != buff_ptr)
- {
- buff_ptr[0]=';' ; buff_ptr[1]=' '; buff_ptr+=2;
- }
- buff_ptr=strmov(buff_ptr,"Using temporary");
+ buff_ptr= strmov(buff_ptr,"; Using temporary");
}
if (need_order)
{
need_order=0;
- if (buff != buff_ptr)
- {
- buff_ptr[0]=';' ; buff_ptr[1]=' '; buff_ptr+=2;
- }
- buff_ptr=strmov(buff_ptr,"Using filesort");
+ buff_ptr= strmov(buff_ptr,"; Using filesort");
}
if (distinct & test_all_bits(used_tables,thd->used_tables))
- {
- if (buff != buff_ptr)
- {
- buff_ptr[0]=';' ; buff_ptr[1]=' '; buff_ptr+=2;
- }
- buff_ptr=strmov(buff_ptr,"Distinct");
- }
- item_list.push_back(new Item_string(buff,(uint) (buff_ptr - buff),
+ buff_ptr= strmov(buff_ptr,"; Distinct");
+ if (buff_ptr == buff)
+ buff_ptr+= 2; // Skip inital "; "
+ item_list.push_back(new Item_string(buff+2,(uint) (buff_ptr - buff)-2,
default_charset_info));
// For next iteration
used_tables|=table->map;
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index c039f84dc77..ebf5b210d6c 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -889,7 +889,7 @@ mysqld_show_keys(THD *thd, TABLE_LIST *table_list)
field_list.push_back(new Item_empty_string("Column_name",NAME_LEN));
field_list.push_back(item=new Item_empty_string("Collation",1));
item->maybe_null=1;
- field_list.push_back(item=new Item_int("Cardinality",0,11));
+ field_list.push_back(item=new Item_int("Cardinality",0,21));
item->maybe_null=1;
field_list.push_back(item=new Item_int("Sub_part",0,3));
item->maybe_null=1;
@@ -930,8 +930,8 @@ mysqld_show_keys(THD *thd, TABLE_LIST *table_list)
KEY *key=table->key_info+i;
if (key->rec_per_key[j])
{
- ulong records=(table->file->records / key->rec_per_key[j]);
- end=int10_to_str((long) records, buff, 10);
+ ha_rows records=(table->file->records / key->rec_per_key[j]);
+ end=longlong10_to_str((longlong) records, buff, 10);
net_store_data(packet,convert,buff,(uint) (end-buff));
}
else
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index abb4cf8d3f9..00077bda39f 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -110,6 +110,17 @@ int mysql_rm_table_part2_with_lock(THD *thd,
return error;
}
+/*
+ TODO:
+ When logging to the binary log, we should log
+ tmp_tables and transactional tables as separate statements if we
+ are in a transaction; This is needed to get these tables into the
+ cached binary log that is only written on COMMIT.
+
+ The current code only writes DROP statements that only uses temporary
+ tables to the cache binary log. This should be ok on most cases, but
+ not all.
+*/
int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
bool dont_log_query)
@@ -119,7 +130,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
String wrong_tables;
db_type table_type;
int error;
- bool some_tables_deleted=0;
+ bool some_tables_deleted=0, tmp_table_deleted=0;
DBUG_ENTER("mysql_rm_table_part2");
for (table=tables ; table ; table=table->next)
@@ -127,7 +138,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
char *db=table->db ? table->db : thd->db;
if (!close_temporary_table(thd, db, table->real_name))
{
- some_tables_deleted=1; // Log query
+ tmp_table_deleted=1;
continue; // removed temporary table
}
@@ -143,8 +154,8 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
DBUG_RETURN(-1);
/* remove form file and isam files */
- (void) sprintf(path,"%s/%s/%s%s",mysql_data_home,db,table->real_name,
- reg_ext);
+ strxmov(path, mysql_data_home, "/", db, "/", table->real_name, reg_ext,
+ NullS);
(void) unpack_filename(path,path);
error=0;
@@ -177,7 +188,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
wrong_tables.append(String(table->real_name,default_charset_info));
}
}
- if (some_tables_deleted)
+ if (some_tables_deleted || tmp_table_deleted)
{
query_cache_invalidate3(thd, tables, 0);
if (!dont_log_query)
@@ -185,7 +196,8 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
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);
+ Query_log_event qinfo(thd, thd->query, thd->query_length,
+ tmp_table_deleted && !some_tables_deleted);
mysql_bin_log.write(&qinfo);
}
}
@@ -271,7 +283,8 @@ static int sort_keys(KEY *a, KEY *b)
create_info Create information (like MAX_ROWS)
fields List of fields to create
keys List of keys to create
- tmp_table Set to 1 if this is a temporary table
+ tmp_table Set to 1 if this is an internal temporary table
+ (From ALTER TABLE)
no_log Don't log the query to binary log.
DESCRIPTION
@@ -784,7 +797,6 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
thd->proc_info="creating table";
- create_info->create_statement = thd->query;
create_info->table_options=db_options;
if (rea_create_table(thd, path, create_info, fields, key_count,
key_info_buffer))
@@ -792,16 +804,6 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
/* my_error(ER_CANT_CREATE_TABLE,MYF(0),table_name,my_errno); */
goto end;
}
- if (!tmp_table && !no_log)
- {
- // Must be written before unlock
- 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);
- mysql_bin_log.write(&qinfo);
- }
- }
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
{
/* Open table and put in temporary table list */
@@ -811,6 +813,18 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
goto end;
}
}
+ if (!tmp_table && !no_log)
+ {
+ // Must be written before unlock
+ 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,
+ test(create_info->options &
+ HA_LEX_CREATE_TMP_TABLE));
+ mysql_bin_log.write(&qinfo);
+ }
+ }
error=0;
end:
VOID(pthread_mutex_unlock(&LOCK_open));
@@ -1255,8 +1269,13 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
switch (result_code) {
case HA_ADMIN_NOT_IMPLEMENTED:
- net_store_data(packet, "error");
- net_store_data(packet, ER(ER_CHECK_NOT_IMPLEMENTED));
+ {
+ char buf[ERRMSGSIZE+20];
+ my_snprintf(buf, ERRMSGSIZE,
+ ER(ER_CHECK_NOT_IMPLEMENTED), operator_name);
+ net_store_data(packet, "error");
+ net_store_data(packet, buf);
+ }
break;
case HA_ADMIN_OK:
@@ -1511,7 +1530,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
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);
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
mysql_bin_log.write(&qinfo);
}
send_ok(thd);
@@ -1887,7 +1906,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
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);
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
mysql_bin_log.write(&qinfo);
}
goto end_temporary;
@@ -2016,7 +2035,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
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);
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
mysql_bin_log.write(&qinfo);
}
VOID(pthread_cond_broadcast(&COND_refresh));
diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc
index f45eca0b65f..35e33caf572 100644
--- a/sql/sql_udf.cc
+++ b/sql/sql_udf.cc
@@ -98,8 +98,8 @@ static void init_syms(udf_func *tmp)
}
}
-static byte* get_hash_key(const byte *buff,uint *length,
- my_bool not_used __attribute__((unused)))
+extern "C" byte* get_hash_key(const byte *buff,uint *length,
+ my_bool not_used __attribute__((unused)))
{
udf_func *udf=(udf_func*) buff;
*length=(uint) udf->name_length;
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index be69935a49c..73343ab1a50 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -50,11 +50,10 @@ int mysql_update(THD *thd,
COND *conds,
ORDER *order,
ha_rows limit,
- enum enum_duplicates handle_duplicates,
- thr_lock_type lock_type)
+ enum enum_duplicates handle_duplicates)
{
- bool using_limit=limit != HA_POS_ERROR;
- bool used_key_is_modified, using_transactions;
+ bool using_limit=limit != HA_POS_ERROR, safe_update= thd->options & OPTION_SAFE_UPDATES;
+ bool used_key_is_modified, transactional_table, log_delayed;
int error=0;
uint save_time_stamp, used_index, want_privilege;
ulong query_id=thd->query_id, timestamp_query_id;
@@ -66,7 +65,7 @@ int mysql_update(THD *thd,
LINT_INIT(used_index);
LINT_INIT(timestamp_query_id);
- if (!(table = open_ltable(thd,table_list,lock_type)))
+ if (!(table = open_ltable(thd,table_list,table_list->lock_type)))
DBUG_RETURN(-1); /* purecov: inspected */
save_time_stamp=table->time_stamp;
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
@@ -117,9 +116,7 @@ int mysql_update(THD *thd,
table->used_keys=0;
select=make_select(table,0,0,conds,&error);
if (error ||
- (select && select->check_quick(test(thd->options & OPTION_SAFE_UPDATES),
- limit)) ||
- !limit)
+ (select && select->check_quick(safe_update, limit)) || !limit)
{
delete select;
table->time_stamp=save_time_stamp; // Restore timestamp pointer
@@ -134,7 +131,7 @@ int mysql_update(THD *thd,
if (!table->quick_keys)
{
thd->lex.select_lex.options|=QUERY_NO_INDEX_USED;
- if ((thd->options & OPTION_SAFE_UPDATES) && limit == HA_POS_ERROR)
+ if (safe_update && !using_limit)
{
delete select;
table->time_stamp=save_time_stamp;
@@ -301,23 +298,34 @@ int mysql_update(THD *thd,
thd->proc_info="end";
VOID(table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY));
table->time_stamp=save_time_stamp; // Restore auto timestamp pointer
- using_transactions=table->file->has_transactions();
- if (updated && (error <= 0 || !using_transactions))
+ transactional_table= table->file->has_transactions();
+ log_delayed= (transactional_table || table->tmp_table);
+ if (updated && (error <= 0 || !transactional_table))
{
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,
- using_transactions);
- if (mysql_bin_log.write(&qinfo) && using_transactions)
- error=1;
+ log_delayed);
+ if (mysql_bin_log.write(&qinfo) && transactional_table)
+ error=1; // Rollback update
}
- if (!using_transactions)
+ if (!log_delayed)
thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
}
- if (using_transactions && ha_autocommit_or_rollback(thd, error >= 0))
- error=1;
- if (updated)
+ if (transactional_table)
+ {
+ if (ha_autocommit_or_rollback(thd, error >= 0))
+ error=1;
+ }
+ /*
+ Only invalidate the query cache if something changed or if we
+ didn't commit the transacion (query cache is automaticly
+ invalidated on commit)
+ */
+ if (updated &&
+ (!transactional_table ||
+ thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))
{
query_cache_invalidate3(thd, table_list, 1);
}
@@ -349,10 +357,12 @@ int mysql_update(THD *thd,
Update multiple tables from join
***************************************************************************/
-multi_update::multi_update(THD *thd_arg, TABLE_LIST *ut, List<Item> &fs,
- enum enum_duplicates handle_duplicates, thr_lock_type lock_option_arg, uint num)
- : update_tables (ut), thd(thd_arg), updated(0), found(0), fields(fs), lock_option(lock_option_arg),
- dupl(handle_duplicates), num_of_tables(num), num_fields(0), num_updated(0) , error(0), do_update(false)
+multi_update::multi_update(THD *thd_arg, TABLE_LIST *ut, List<Item> &fs,
+ enum enum_duplicates handle_duplicates,
+ uint num)
+ : update_tables (ut), thd(thd_arg), updated(0), found(0), fields(fs),
+ dupl(handle_duplicates), num_of_tables(num), num_fields(0), num_updated(0),
+ error(0), do_update(false)
{
save_time_stamps = (uint *) sql_calloc (sizeof(uint) * num_of_tables);
tmp_tables = (TABLE **)NULL;
@@ -695,7 +705,7 @@ void multi_update::send_error(uint errcode,const char *err)
int multi_update::do_updates (bool from_send_error)
{
- int error = 0, counter = 0;
+ int local_error= 0, counter= 0;
if (from_send_error)
{
@@ -720,7 +730,7 @@ int multi_update::do_updates (bool from_send_error)
TABLE *tmp_table=tmp_tables[counter];
if (tmp_table->file->extra(HA_EXTRA_NO_CACHE))
{
- error=1;
+ local_error=1;
break;
}
List<Item> list;
@@ -736,35 +746,36 @@ int multi_update::do_updates (bool from_send_error)
tmp_table->used_keys&=field->part_of_key;
}
tmp_table->used_fields=tmp_table->fields;
- error=0; list.pop(); // we get position some other way ...
- error = tmp_table->file->rnd_init(1);
- if (error)
- return error;
- while (!(error=tmp_table->file->rnd_next(tmp_table->record[0])) &&
+ local_error=0;
+ list.pop(); // we get position some other way ...
+ local_error = tmp_table->file->rnd_init(1);
+ if (local_error)
+ return local_error;
+ while (!(local_error=tmp_table->file->rnd_next(tmp_table->record[0])) &&
(!thd->killed || from_send_error || not_trans_safe))
{
found++;
- error= table->file->rnd_pos(table->record[0],
- (byte*) (*(tmp_table->field))->ptr);
- if (error)
- return error;
+ local_error= table->file->rnd_pos(table->record[0],
+ (byte*) (*(tmp_table->field))->ptr);
+ if (local_error)
+ return local_error;
table->status|= STATUS_UPDATED;
store_record(table,1);
- error= fill_record(*fields_by_tables[counter + 1],list) ||
- /* compare_record(table, query_id) || */
- table->file->update_row(table->record[1],table->record[0]);
- if (error)
+ local_error= (fill_record(*fields_by_tables[counter + 1],list) ||
+ /* compare_record(table, query_id) || */
+ table->file->update_row(table->record[1],table->record[0]));
+ if (local_error)
{
- table->file->print_error(error,MYF(0));
+ table->file->print_error(local_error,MYF(0));
break;
}
else
updated++;
}
- if (error == HA_ERR_END_OF_FILE)
- error = 0;
+ if (local_error == HA_ERR_END_OF_FILE)
+ local_error = 0;
}
- return error;
+ return local_error;
}
@@ -775,18 +786,18 @@ bool multi_update::send_eof()
thd->proc_info="updating the reference tables";
/* Does updates for the last n - 1 tables, returns 0 if ok */
- int error = (num_updated) ? do_updates(false) : 0; /* do_updates returns 0 if success */
+ int local_error = (num_updated) ? do_updates(false) : 0;
/* reset used flags */
#ifndef NOT_USED
update_tables->table->no_keyread=0;
#endif
- if (error == -1)
- error = 0;
- thd->proc_info="end";
- //TODO error should be sent at the query processing end
- if (error)
- send_error(error,"An error occured in multi-table update");
+ if (local_error == -1)
+ local_error= 0;
+ thd->proc_info= "end";
+ // TODO: Error should be sent at the query processing end
+ if (local_error)
+ send_error(local_error, "An error occured in multi-table update");
/*
Write the SQL statement to the binlog if we updated
@@ -798,7 +809,7 @@ bool multi_update::send_eof()
if (updated || not_trans_safe)
{
mysql_update_log.write(thd,thd->query,thd->query_length);
- Query_log_event qinfo(thd, thd->query, thd->query_length);
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
/*
mysql_bin_log is not open if binlogging or replication
@@ -807,14 +818,14 @@ bool multi_update::send_eof()
if (mysql_bin_log.is_open() && mysql_bin_log.write(&qinfo) &&
!not_trans_safe)
- error=1; /* Log write failed: roll back the SQL statement */
+ local_error=1; /* Log write failed: roll back the SQL statement */
/* Commit or rollback the current SQL statement */
- VOID(ha_autocommit_or_rollback(thd,error > 0));
+ VOID(ha_autocommit_or_rollback(thd, local_error > 0));
}
else
- error=0; // this can happen only if it is end of file error
- if (!error) // if the above log write did not fail ...
+ local_error= 0; // this can happen only if it is end of file error
+ if (!local_error) // if the above log write did not fail ...
{
char buff[80];
sprintf(buff,ER(ER_UPDATE_INFO), (long) found, (long) updated,
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 04aeddfc384..a994a2539f7 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -69,6 +69,7 @@ inline Item *or_or_concat(Item* A, Item* B)
enum Item_cast cast_type;
enum Item_udftype udf_type;
CHARSET_INFO *charset;
+ thr_lock_type lock_type;
interval_type interval;
}
@@ -177,7 +178,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token CHARSET
%token CHECKSUM_SYM
%token CHECK_SYM
-%token CIPHER
%token COMMITTED_SYM
%token COLLATE_SYM
%token COLUMNS
@@ -234,7 +234,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token IN_SYM
%token ISOLATION
%token ISAM_SYM
-%token ISSUER
%token JOIN_SYM
%token KEYS
%token KEY_SYM
@@ -254,7 +253,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token MASTER_USER_SYM
%token MASTER_LOG_FILE_SYM
%token MASTER_LOG_POS_SYM
-%token MASTER_LOG_SEQ_SYM
%token MASTER_PASSWORD_SYM
%token MASTER_PORT_SYM
%token MASTER_CONNECT_RETRY_SYM
@@ -275,10 +273,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token NEW_SYM
%token NCHAR_SYM
%token NOT
-%token NO_FOREIGN_KEY_CHECKS
%token NO_SYM
%token NULL_SYM
%token NUM
+%token OFFSET_SYM
%token ON
%token OPEN_SYM
%token OPTION
@@ -305,7 +303,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token REAL_NUM
%token REFERENCES
%token REGEXP
-%token RELAXED_UNIQUE_CHECKS
%token RELOAD
%token RENAME
%token REPEATABLE_SYM
@@ -557,7 +554,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
type int_type real_type order_dir opt_field_spec lock_option
udf_type if_exists opt_local opt_table_options table_options
table_option opt_if_not_exists opt_var_type opt_var_ident_type
- delete_option opt_with_if_not_exists
+ delete_option opt_temporary
%type <ulong_num>
ULONG_NUM raid_types merge_insert_types
@@ -565,6 +562,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%type <ulonglong_number>
ulonglong_num
+%type <lock_type>
+ replace_lock_option opt_low_priority insert_lock_option load_data_lock
+
%type <item>
literal text_literal insert_ident order_ident
simple_ident select_item2 expr opt_expr opt_else sum_expr in_sum_expr
@@ -636,17 +636,18 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
field_opt_list opt_binary table_lock_list table_lock varchar
ref_list opt_on_delete opt_on_delete_list opt_on_delete_item use
opt_delete_options opt_delete_option
- opt_outer table_list table_name opt_option opt_place opt_low_priority
+ opt_outer table_list table_name opt_option opt_place
opt_attribute opt_attribute_list attribute column_list column_list_id
opt_column_list grant_privileges opt_table user_list grant_option
grant_privilege grant_privilege_list
- flush_options flush_option insert_lock_option replace_lock_option
+ flush_options flush_option
equal optional_braces opt_key_definition key_usage_list2
opt_mi_check_type opt_to mi_check_types normal_join
table_to_table_list table_to_table opt_table_list opt_as
handler_rkey_function handler_read_or_scan
- single_multi table_wild_list table_wild_one opt_wild union union_list
- precision union_option opt_on_delete_item subselect_start opt_and
+ single_multi table_wild_list table_wild_one opt_wild
+ union opt_union union_list union_option
+ precision opt_on_delete_item subselect_start opt_and
subselect_end select_var_list select_var_list_init help opt_len
END_OF_INPUT
@@ -730,7 +731,7 @@ change:
{
LEX *lex = Lex;
lex->sql_command = SQLCOM_CHANGE_MASTER;
- memset(&lex->mi, 0, sizeof(lex->mi));
+ bzero((char*) &lex->mi, sizeof(lex->mi));
} master_defs;
master_defs:
@@ -887,10 +888,6 @@ opt_if_not_exists:
/* empty */ { $$= 0; }
| IF NOT EXISTS { $$=HA_LEX_CREATE_IF_NOT_EXISTS; };
-opt_with_if_not_exists:
- /* empty */ { $$= 0; }
- | WITH IF NOT EXISTS { $$=HA_LEX_CREATE_IF_NOT_EXISTS; };
-
opt_create_table_options:
/* empty */
| create_table_options;
@@ -1461,20 +1458,24 @@ opt_to:
| EQ {}
| AS {};
+/*
+ The first two deprecate the last two--delete the last two for 4.1 release
+*/
+
slave:
START_SYM SLAVE slave_thread_opts
- {
- LEX *lex=Lex;
- lex->sql_command = SQLCOM_SLAVE_START;
- lex->type = 0;
- }
- |
- STOP_SYM SLAVE slave_thread_opts
- {
- LEX *lex=Lex;
- lex->sql_command = SQLCOM_SLAVE_STOP;
- lex->type = 0;
- };
+ {
+ LEX *lex=Lex;
+ lex->sql_command = SQLCOM_SLAVE_START;
+ lex->type = 0;
+ }
+ | STOP_SYM SLAVE slave_thread_opts
+ {
+ LEX *lex=Lex;
+ lex->sql_command = SQLCOM_SLAVE_STOP;
+ lex->type = 0;
+ }
+ ;
slave_thread_opts:
slave_thread_opt
@@ -2490,15 +2491,24 @@ opt_table_alias:
where_clause:
/* empty */ { Select->select_lex()->where= 0; }
- | WHERE expr { Select->select_lex()->where= $2; };
+ | WHERE expr
+ {
+ Select->select_lex()->where= $2;
+ if ($2)
+ $2->top_level_item();
+ }
+ ;
having_clause:
/* empty */
| HAVING { Select->select_lex()->create_refs= 1; } expr
- {
- SELECT_LEX *sel= Select->select_lex();
- sel->having= $3; sel->create_refs=0;
- };
+ {
+ SELECT_LEX *sel= Select->select_lex();
+ sel->having= $3; sel->create_refs=0;
+ if ($3)
+ $3->top_level_item();
+ }
+ ;
opt_escape:
ESCAPE_SYM TEXT_STRING { $$= $2.str; }
@@ -2563,11 +2573,6 @@ order_clause:
ORDER_SYM BY
{
LEX *lex=Lex;
- if (lex->sql_command == SQLCOM_MULTI_UPDATE)
- {
- net_printf(lex->thd, ER_WRONG_USAGE, "UPDATE", "ORDER BY");
- YYABORT;
- }
if (lex->current_select->linkage != GLOBAL_OPTIONS_TYPE &&
lex->current_select->select_lex()->olap !=
UNSPECIFIED_OLAP_TYPE)
@@ -2593,7 +2598,7 @@ order_dir:
limit_clause:
/* empty */ {}
- | LIMIT ULONG_NUM
+ | LIMIT
{
LEX *lex= Lex;
if (lex->current_select->linkage != GLOBAL_OPTIONS_TYPE &&
@@ -2604,35 +2609,36 @@ limit_clause:
"LIMIT");
YYABORT;
}
+ }
+ limit_options
+ ;
+
+limit_options:
+ ULONG_NUM
+ {
+ SELECT_LEX_NODE *sel= Select;
+ sel->select_limit= $1;
+ sel->offset_limit= 0L;
+ }
+ | ULONG_NUM ',' ULONG_NUM
+ {
SELECT_LEX_NODE *sel= Select;
- sel->select_limit= $2;
- sel->offset_limit= 0L;
+ sel->select_limit= $3;
+ sel->offset_limit= $1;
}
- | LIMIT ULONG_NUM ',' ULONG_NUM
+ | ULONG_NUM OFFSET_SYM ULONG_NUM
{
- LEX *lex=Lex;
- if (lex->current_select->linkage != GLOBAL_OPTIONS_TYPE &&
- lex->current_select->select_lex()->olap !=
- UNSPECIFIED_OLAP_TYPE)
- {
- net_printf(lex->thd, ER_WRONG_USAGE, "CUBE/ROLLUP",
- "LIMIT");
- YYABORT;
- }
- SELECT_LEX_NODE *sel= lex->current_select;
- sel->select_limit= $4;
- sel->offset_limit= $2;
- };
+ SELECT_LEX_NODE *sel= Select;
+ sel->select_limit= $1;
+ sel->offset_limit= $3;
+ }
+ ;
+
delete_limit_clause:
/* empty */
{
LEX *lex=Lex;
- if (lex->sql_command == SQLCOM_MULTI_UPDATE)
- {
- net_printf(lex->thd, ER_WRONG_USAGE, "DELETE", "LIMIT");
- YYABORT;
- }
lex->current_select->select_limit= HA_POS_ERROR;
}
| LIMIT ulonglong_num
@@ -2754,11 +2760,12 @@ do: DO_SYM
*/
drop:
- DROP TABLE_SYM if_exists table_list opt_restrict
+ DROP opt_temporary TABLE_SYM if_exists table_list opt_restrict
{
LEX *lex=Lex;
lex->sql_command = SQLCOM_DROP_TABLE;
- lex->drop_if_exists = $3;
+ lex->drop_temporary= $2;
+ lex->drop_if_exists= $4;
}
| DROP INDEX ident ON table_ident {}
{
@@ -2795,14 +2802,25 @@ table_name:
if_exists:
/* empty */ { $$=0; }
- | IF EXISTS { $$= 1; };
+ | IF EXISTS { $$= 1; }
+ ;
+opt_temporary:
+ /* empty */ { $$= 0; }
+ | TEMPORARY { $$= 1; }
+ ;
/*
** Insert : add new data to table
*/
insert:
- INSERT { Lex->sql_command = SQLCOM_INSERT; } insert_lock_option opt_ignore insert2 insert_field_spec;
+ INSERT { Lex->sql_command = SQLCOM_INSERT; } insert_lock_option
+ opt_ignore insert2
+ {
+ set_lock_for_tables($3);
+ }
+ insert_field_spec
+ ;
replace:
REPLACE
@@ -2811,17 +2829,23 @@ replace:
lex->sql_command = SQLCOM_REPLACE;
lex->duplicates= DUP_REPLACE;
}
- replace_lock_option insert2 insert_field_spec;
+ replace_lock_option insert2
+ {
+ set_lock_for_tables($3);
+ }
+ insert_field_spec
+ ;
insert_lock_option:
- /* empty */ { Lex->lock_option= TL_WRITE_CONCURRENT_INSERT; }
- | LOW_PRIORITY { Lex->lock_option= TL_WRITE_LOW_PRIORITY; }
- | DELAYED_SYM { Lex->lock_option= TL_WRITE_DELAYED; }
- | HIGH_PRIORITY { Lex->lock_option= TL_WRITE; };
+ /* empty */ { $$= TL_WRITE_CONCURRENT_INSERT; }
+ | LOW_PRIORITY { $$= TL_WRITE_LOW_PRIORITY; }
+ | DELAYED_SYM { $$= TL_WRITE_DELAYED; }
+ | HIGH_PRIORITY { $$= TL_WRITE; }
+ ;
replace_lock_option:
- opt_low_priority {}
- | DELAYED_SYM { Lex->lock_option= TL_WRITE_DELAYED; };
+ opt_low_priority { $$= $1; }
+ | DELAYED_SYM { $$= TL_WRITE_DELAYED; };
insert2:
INTO insert_table {}
@@ -2867,7 +2891,7 @@ insert_values:
mysql_init_select(lex);
}
select_options select_item_list select_from select_lock_type
- union {};
+ opt_union {};
values_list:
values_list ',' no_braces
@@ -2940,7 +2964,12 @@ update:
lex->sql_command= SQLCOM_UPDATE;
lex->select_lex.init_order();
}
- opt_low_priority opt_ignore join_table_list SET update_list where_clause opt_order_clause delete_limit_clause;
+ opt_low_priority opt_ignore join_table_list
+ SET update_list where_clause opt_order_clause delete_limit_clause
+ {
+ set_lock_for_tables($3);
+ }
+ ;
update_list:
update_list ',' simple_ident equal expr
@@ -2955,8 +2984,8 @@ update_list:
};
opt_low_priority:
- /* empty */ { Lex->lock_option= current_thd->update_lock_default; }
- | LOW_PRIORITY { Lex->lock_option= TL_WRITE_LOW_PRIORITY; };
+ /* empty */ { $$= current_thd->update_lock_default; }
+ | LOW_PRIORITY { $$= TL_WRITE_LOW_PRIORITY; };
/* Delete rows from a table */
@@ -2969,13 +2998,20 @@ delete:
lex->lock_option= lex->thd->update_lock_default;
lex->select_lex.init_order();
}
- opt_delete_options single_multi {};
+ opt_delete_options single_multi {}
+ ;
single_multi:
- FROM table_name where_clause opt_order_clause delete_limit_clause {}
+ FROM table_ident
+ {
+ if (!add_table_to_list($2, NULL, 1, Lex->lock_option))
+ YYABORT;
+ }
+ where_clause opt_order_clause
+ delete_limit_clause
| table_wild_list
{ mysql_init_multi_delete(Lex); }
- FROM join_table_list where_clause
+ FROM join_table_list where_clause
| FROM table_wild_list
{ mysql_init_multi_delete(Lex); }
USING join_table_list where_clause;
@@ -2985,18 +3021,19 @@ table_wild_list:
| table_wild_list ',' table_wild_one {};
table_wild_one:
- ident opt_wild
- {
- if (!Select->add_table_to_list(new Table_ident($1), NULL, 1,
- TL_WRITE))
- YYABORT;
- }
- | ident '.' ident opt_wild
- {
- if (!Select->add_table_to_list(new Table_ident($1, $3, 0), NULL,
- 1, TL_WRITE))
+ ident opt_wild
+ {
+ if (!Select->add_table_to_list(new Table_ident($1), NULL, 1,
+ Lex->lock_option))
+ YYABORT;
+ }
+ | ident '.' ident opt_wild
+ {
+ if (!Select->add_table_to_list(new Table_ident($1, $3, 0), NULL, 1,
+ Lex->lock_option))
YYABORT;
- };
+ }
+ ;
opt_wild:
/* empty */ {}
@@ -3018,7 +3055,8 @@ truncate:
lex->sql_command= SQLCOM_TRUNCATE;
lex->select_lex.options= 0;
lex->select_lex.init_order();
- lex->lock_option= lex->thd->update_lock_default; };
+ }
+ ;
opt_table_sym:
/* empty */
@@ -3145,7 +3183,7 @@ show_param:
lex->grant_user=$3;
lex->grant_user->password.str=NullS;
}
- | CREATE DATABASE opt_with_if_not_exists ident
+ | CREATE DATABASE opt_if_not_exists ident
{
Lex->sql_command=SQLCOM_SHOW_CREATE_DB;
Lex->create_info.options=$3;
@@ -3310,7 +3348,8 @@ load: LOAD DATA_SYM load_data_lock opt_local INFILE TEXT_STRING
{
LEX *lex=Lex;
lex->sql_command= SQLCOM_LOAD;
- lex->local_file= $4;
+ lex->lock_option= $3;
+ lex->local_file= $4;
if (!(lex->exchange= new sql_exchange($6.str,0)))
YYABORT;
lex->field_list.empty();
@@ -3340,9 +3379,9 @@ opt_local:
| LOCAL_SYM { $$=1;};
load_data_lock:
- /* empty */ { Lex->lock_option= current_thd->update_lock_default; }
- | CONCURRENT { Lex->lock_option= TL_WRITE_CONCURRENT_INSERT ; }
- | LOW_PRIORITY { Lex->lock_option= TL_WRITE_LOW_PRIORITY; };
+ /* empty */ { $$= current_thd->update_lock_default; }
+ | CONCURRENT { $$= TL_WRITE_CONCURRENT_INSERT ; }
+ | LOW_PRIORITY { $$= TL_WRITE_LOW_PRIORITY; };
opt_duplicate:
@@ -3485,12 +3524,13 @@ ident:
IDENT { $$=$1; }
| keyword
{
- LEX *lex;
- $$.str=sql_strmake($1.str,$1.length);
+ LEX *lex= Lex;
+ $$.str= lex->thd->strmake($1.str,$1.length);
$$.length=$1.length;
- if ((lex=Lex)->next_state != STATE_END)
+ if (lex->next_state != STATE_END)
lex->next_state=STATE_OPERATOR_OR_IDENT;
- };
+ }
+ ;
ident_or_text:
ident { $$=$1;}
@@ -3613,6 +3653,7 @@ keyword:
| NEW_SYM {}
| NO_SYM {}
| NONE_SYM {}
+ | OFFSET_SYM {}
| OPEN_SYM {}
| PACK_KEYS_SYM {}
| PARTIAL {}
@@ -4198,7 +4239,7 @@ rollback:
*/
-union:
+opt_union:
/* empty */ {}
| union_list;
@@ -4225,11 +4266,14 @@ union_list:
;
union_opt:
- union {}
+ union_list {}
| optional_order_or_limit {};
optional_order_or_limit:
- /* empty */ {}
+ /* empty
+ intentional reduce/reduce conflict here !!!
+ { code } below should not be executed
+ when neither ORDER BY nor LIMIT are used */ {}
|
{
LEX *lex=Lex;
diff --git a/sql/stacktrace.c b/sql/stacktrace.c
index 1aba73dda33..f5c0a59b572 100644
--- a/sql/stacktrace.c
+++ b/sql/stacktrace.c
@@ -206,7 +206,7 @@ resolve it\n");
/* Produce a core for the thread */
-#ifdef HAVE_LINUXTHREADS
+#ifdef NOT_USED /* HAVE_LINUXTHREADS */
void write_core(int sig)
{
signal(sig, SIG_DFL);
diff --git a/sql/table.cc b/sql/table.cc
index bad453f2cad..84a072c886d 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -95,15 +95,15 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
if (my_read(file,(byte*) head,64,MYF(MY_NABP))) goto err_not_open;
if (head[0] != (uchar) 254 || head[1] != 1 ||
- (head[2] < FRM_VER && head[2] > FRM_VER+2))
- goto err_not_open; /* purecov: inspected */
+ (head[2] != FRM_VER && head[2] > FRM_VER+2))
+ goto err_not_open; /* purecov: inspected */
new_field_pack_flag=head[27];
new_frm_ver= (head[2] - FRM_VER);
field_pack_length= new_frm_ver < 2 ? 11 : 15;
error=3;
if (!(pos=get_form_pos(file,head,(TYPELIB*) 0)))
- goto err_not_open; /* purecov: inspected */
+ goto err_not_open; /* purecov: inspected */
*fn_ext(index_file)='\0'; // Remove .frm extension
outparam->db_type=ha_checktype((enum db_type) (uint) *(head+3));
@@ -145,7 +145,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
goto err_not_open; /* purecov: inspected */
bzero((char*) keyinfo,n_length);
outparam->key_info=keyinfo;
- outparam->max_key_length=0;
+ outparam->max_key_length= outparam->total_key_length= 0;
key_part= (KEY_PART_INFO*) (keyinfo+keys);
strpos=disk_buff+6;
@@ -203,11 +203,13 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
}
set_if_bigger(outparam->max_key_length,keyinfo->key_length+
keyinfo->key_parts);
+ outparam->total_key_length+= keyinfo->key_length;
if (keyinfo->flags & HA_NOSAME)
set_if_bigger(outparam->max_unique_length,keyinfo->key_length);
}
keynames=(char*) key_part;
strpos+= (strmov(keynames, (char *) strpos) - keynames)+1;
+
outparam->reclength = uint2korr((head+16));
if (*(head+26) == 1)
outparam->system=1; /* one-record-database */
@@ -391,6 +393,11 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
(TYPELIB*) 0),
outparam->fieldnames.type_names[i],
outparam);
+ if (!reg_field) // Not supported field type
+ {
+ error= 4;
+ goto err_not_open; /* purecov: inspected */
+ }
reg_field->comment=comment;
reg_field->set_charset(charset);
if (!(reg_field->flags & NOT_NULL_FLAG))
diff --git a/sql/table.h b/sql/table.h
index d09194442c8..18079e183ce 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -58,6 +58,7 @@ struct st_table {
uint reclength; /* Recordlength */
uint rec_buff_length;
uint keys,key_parts,primary_key,max_key_length,max_unique_length;
+ uint total_key_length;
uint uniques;
uint null_fields; /* number of null fields */
uint blob_fields; /* number of blob fields */