summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/Makefile.am9
-rw-r--r--sql/convert.cc2
-rw-r--r--sql/field.cc884
-rw-r--r--sql/field.h62
-rw-r--r--sql/filesort.cc15
-rw-r--r--sql/gen_lex_hash.cc17
-rw-r--r--sql/ha_berkeley.cc18
-rw-r--r--sql/ha_berkeley.h4
-rw-r--r--sql/ha_heap.cc19
-rw-r--r--sql/ha_innodb.cc752
-rw-r--r--sql/ha_innodb.h11
-rw-r--r--sql/ha_isam.h13
-rw-r--r--sql/ha_myisam.cc56
-rw-r--r--sql/ha_myisam.h18
-rw-r--r--sql/ha_myisammrg.cc26
-rw-r--r--sql/ha_myisammrg.h12
-rw-r--r--sql/handler.cc53
-rw-r--r--sql/handler.h18
-rw-r--r--sql/hostname.cc4
-rw-r--r--sql/item.cc4
-rw-r--r--sql/item.h54
-rw-r--r--sql/item_cmpfunc.cc90
-rw-r--r--sql/item_cmpfunc.h71
-rw-r--r--sql/item_create.cc35
-rw-r--r--sql/item_create.h9
-rw-r--r--sql/item_func.cc299
-rw-r--r--sql/item_func.h86
-rw-r--r--sql/item_strfunc.cc242
-rw-r--r--sql/item_strfunc.h48
-rw-r--r--sql/item_sum.cc9
-rw-r--r--sql/item_sum.h17
-rw-r--r--sql/item_timefunc.cc14
-rw-r--r--sql/item_timefunc.h43
-rw-r--r--sql/item_uniq.h1
-rw-r--r--sql/key.cc2
-rw-r--r--sql/lex.h48
-rw-r--r--sql/lock.cc7
-rw-r--r--sql/log.cc1169
-rw-r--r--sql/log_event.cc865
-rw-r--r--sql/log_event.h494
-rw-r--r--sql/mini_client.cc195
-rw-r--r--sql/mini_client.h19
-rw-r--r--sql/mysql_priv.h219
-rw-r--r--sql/mysqld.cc1618
-rw-r--r--sql/net_pkg.cc29
-rw-r--r--sql/net_serv.cc173
-rw-r--r--sql/nt_servc.cc10
-rw-r--r--sql/opt_range.cc34
-rw-r--r--sql/opt_range.h10
-rw-r--r--sql/opt_sum.cc6
-rw-r--r--sql/procedure.h4
-rw-r--r--sql/records.cc9
-rw-r--r--sql/repl_failsafe.cc250
-rw-r--r--sql/repl_failsafe.h1
-rw-r--r--sql/set_var.cc1357
-rw-r--r--sql/set_var.h440
-rw-r--r--sql/share/czech/errmsg.txt10
-rw-r--r--sql/share/danish/errmsg.txt10
-rw-r--r--sql/share/dutch/errmsg.txt13
-rw-r--r--sql/share/english/errmsg.txt10
-rw-r--r--sql/share/estonian/errmsg.txt10
-rw-r--r--sql/share/french/errmsg.txt12
-rw-r--r--sql/share/german/errmsg.txt10
-rw-r--r--sql/share/greek/errmsg.txt10
-rw-r--r--sql/share/hungarian/errmsg.txt10
-rw-r--r--sql/share/italian/errmsg.txt10
-rw-r--r--sql/share/japanese/errmsg.txt10
-rw-r--r--sql/share/korean/errmsg.txt10
-rw-r--r--sql/share/norwegian-ny/errmsg.txt10
-rw-r--r--sql/share/norwegian/errmsg.txt10
-rw-r--r--sql/share/polish/errmsg.txt10
-rw-r--r--sql/share/portuguese/errmsg.txt154
-rw-r--r--sql/share/romanian/errmsg.txt10
-rw-r--r--sql/share/russian/errmsg.txt10
-rw-r--r--sql/share/slovak/errmsg.txt10
-rw-r--r--sql/share/spanish/errmsg.txt10
-rw-r--r--sql/share/swedish/errmsg.txt10
-rw-r--r--sql/share/ukrainian/errmsg.txt10
-rw-r--r--sql/slave.cc1723
-rw-r--r--sql/slave.h210
-rw-r--r--sql/sql_acl.cc610
-rw-r--r--sql/sql_acl.h96
-rw-r--r--sql/sql_base.cc226
-rw-r--r--sql/sql_cache.cc231
-rw-r--r--sql/sql_cache.h20
-rw-r--r--sql/sql_class.cc97
-rw-r--r--sql/sql_class.h230
-rw-r--r--sql/sql_db.cc11
-rw-r--r--sql/sql_delete.cc68
-rw-r--r--sql/sql_handler.cc7
-rw-r--r--sql/sql_insert.cc66
-rw-r--r--sql/sql_lex.cc40
-rw-r--r--sql/sql_lex.h105
-rw-r--r--sql/sql_load.cc47
-rw-r--r--sql/sql_olap.cc194
-rw-r--r--sql/sql_parse.cc541
-rw-r--r--sql/sql_rename.cc2
-rw-r--r--sql/sql_repl.cc412
-rw-r--r--sql/sql_repl.h17
-rw-r--r--sql/sql_select.cc578
-rw-r--r--sql/sql_show.cc93
-rw-r--r--sql/sql_string.cc4
-rw-r--r--sql/sql_table.cc104
-rw-r--r--sql/sql_test.cc13
-rw-r--r--sql/sql_union.cc7
-rw-r--r--sql/sql_update.cc93
-rw-r--r--sql/sql_yacc.yy977
-rw-r--r--sql/stacktrace.c6
-rw-r--r--sql/structs.h46
-rw-r--r--sql/table.cc48
-rw-r--r--sql/table.h27
-rw-r--r--sql/time.cc2
-rw-r--r--sql/udf_example.cc8
-rw-r--r--sql/uniques.cc2
-rw-r--r--sql/unireg.cc2
-rw-r--r--sql/unireg.h5
116 files changed, 11055 insertions, 6256 deletions
diff --git a/sql/Makefile.am b/sql/Makefile.am
index 9cfdf4c4d9b..5527c345078 100644
--- a/sql/Makefile.am
+++ b/sql/Makefile.am
@@ -55,8 +55,9 @@ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \
opt_range.h opt_ft.h \
sql_select.h structs.h table.h sql_udf.h hash_filo.h\
lex.h lex_symbol.h sql_acl.h sql_crypt.h \
- log_event.h mini_client.h sql_repl.h slave.h \
- stacktrace.h sql_sort.h sql_cache.h spatial.h gstream.h
+ log_event.h mini_client.h sql_repl.h slave.h \
+ stacktrace.h sql_sort.h sql_cache.h set_var.h \
+ spatial.h gstream.h
mysqld_SOURCES = sql_lex.cc sql_handler.cc \
item.cc item_sum.cc item_buff.cc item_func.cc \
item_cmpfunc.cc item_strfunc.cc item_timefunc.cc \
@@ -65,7 +66,7 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc \
net_serv.cc net_pkg.cc lock.cc my_lock.c \
sql_string.cc sql_manager.cc sql_map.cc \
mysqld.cc password.c hash_filo.cc hostname.cc \
- convert.cc sql_parse.cc sql_yacc.yy \
+ convert.cc set_var.cc sql_parse.cc sql_yacc.yy \
sql_base.cc table.cc sql_select.cc sql_insert.cc \
sql_prepare.cc sql_error.cc \
sql_update.cc sql_delete.cc uniques.cc sql_do.cc \
@@ -82,7 +83,7 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc \
sql_udf.cc sql_analyse.cc sql_analyse.h sql_cache.cc \
slave.cc sql_repl.cc sql_union.cc sql_derived.cc \
mini_client.cc mini_client_errors.c \
- stacktrace.c repl_failsafe.h repl_failsafe.cc \
+ stacktrace.c repl_failsafe.h repl_failsafe.cc sql_olap.cc\
gstream.cc spatial.cc
gen_lex_hash_SOURCES = gen_lex_hash.cc
gen_lex_hash_LDADD = $(LDADD) $(CXXLDFLAGS)
diff --git a/sql/convert.cc b/sql/convert.cc
index c2868cac848..13a6dfe0392 100644
--- a/sql/convert.cc
+++ b/sql/convert.cc
@@ -27,7 +27,7 @@
#include "mysql_priv.h"
/****************************************************************************
-** Convert tables
+ Convert tables
****************************************************************************/
/* Windows cp1251->koi8 and reverse conversion by Timur I. Bakeyev <translate@bat.ru> */
diff --git a/sql/field.cc b/sql/field.cc
index 462088d26a6..c9669c93c04 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -42,7 +42,7 @@
#endif
/*****************************************************************************
-** Instansiate templates and static variables
+ Instansiate templates and static variables
*****************************************************************************/
#ifdef __GNUC__
@@ -50,70 +50,13 @@ template class List<create_field>;
template class List_iterator<create_field>;
#endif
-struct st_decstr {
- uint nr_length,nr_dec,sign,extra;
- char sign_char;
-};
-
uchar Field_null::null[1]={1};
const char field_separator=',';
/*****************************************************************************
-** Static help functions
+ Static help functions
*****************************************************************************/
- /*
- Calculate length of number and its parts
- Increment cuted_fields if wrong number
- */
-
-static bool
-number_dec(CHARSET_INFO *cs, struct st_decstr *sdec,
- const char *str, const char *end)
-{
- sdec->sign=sdec->extra=0;
- if (str == end)
- {
- current_thd->cuted_fields++;
- sdec->nr_length=sdec->nr_dec=sdec->sign=0;
- sdec->extra=1; // We must put one 0 before .
- return 1;
- }
-
- if (*str == '-' || *str == '+') /* sign */
- {
- sdec->sign_char= *str;
- sdec->sign=1;
- str++;
- }
- const char *start=str;
- while (str != end && my_isdigit(cs,*str))
- str++;
- if (!(sdec->nr_length=(uint) (str-start)))
- sdec->extra=1; // We must put one 0 before .
- start=str;
- if (str != end && *str == '.')
- {
- str++;
- start=str;
- while (str != end && my_isdigit(cs,*str))
- str++;
- }
- sdec->nr_dec=(uint) (str-start);
- if (current_thd->count_cuted_fields)
- {
- while (str != end && my_isspace(cs,*str))
- str++; /* purecov: inspected */
- if (str != end)
- {
- current_thd->cuted_fields++;
- return 1;
- }
- }
- return 0;
-}
-
-
void Field_num::prepend_zeros(String *value)
{
int diff;
@@ -128,8 +71,8 @@ void Field_num::prepend_zeros(String *value)
}
/*
-** Test if given number is a int (or a fixed format float with .000)
-** This is only used to give warnings in ALTER TABLE or LOAD DATA...
+ Test if given number is a int (or a fixed format float with .000)
+ This is only used to give warnings in ALTER TABLE or LOAD DATA...
*/
bool test_if_int(const char *str,int length)
@@ -143,7 +86,7 @@ bool test_if_int(const char *str,int length)
str++;
if (str == end)
return 0; // Error: Empty string
- for ( ; str != end ; str++)
+ for (; str != end ; str++)
{
if (!my_isdigit(system_charset_info,*str))
{
@@ -207,7 +150,7 @@ static bool test_if_real(const char *str,int length)
length--; str++;
}
}
- for ( ; length ; length--, str++)
+ for (; length ; length--, str++)
{ // Allow end space
if (!my_isspace(system_charset_info,*str))
return 0;
@@ -262,7 +205,7 @@ bool Field::send(THD *thd, String *packet)
String tmp(buff,sizeof(buff),default_charset_info);
val_str(&tmp,&tmp);
CONVERT *convert;
- if ((convert=thd->convert_set))
+ if ((convert=thd->variables.convert_set))
return convert->store(packet,tmp.ptr(),tmp.length());
return net_store_data(packet,tmp.ptr(),tmp.length());
}
@@ -279,6 +222,7 @@ void Field_num::add_zerofill_and_unsigned(String &res) const
void Field_num::make_field(Send_field *field)
{
+ /* table_cache_key is not set for temp tables */
field->db_name=table->table_cache_key ? table->table_cache_key : "";
field->org_table_name=table->real_name;
field->table_name=table_name;
@@ -292,6 +236,7 @@ void Field_num::make_field(Send_field *field)
void Field_str::make_field(Send_field *field)
{
+ /* table_cache_key is not set for temp tables */
field->db_name=table->table_cache_key ? table->table_cache_key : "";
field->org_table_name=table->real_name;
field->table_name=table_name;
@@ -363,9 +308,10 @@ void Field::store_time(TIME *ltime,timestamp_type type)
store(buff,19,default_charset_info);
break;
case TIMESTAMP_TIME:
- sprintf(buff, "%02d:%02d:%02d",
- ltime->hour,ltime->minute,ltime->second);
- store(buff,(uint) strlen(buff),default_charset_info);
+ {
+ ulong length= my_sprintf(buff, (buff, "%02d:%02d:%02d",
+ ltime->hour,ltime->minute,ltime->second));
+ store(buff,(uint) length, default_charset_info);
break;
}
}
@@ -377,8 +323,8 @@ bool Field::optimize_range(uint idx)
}
/****************************************************************************
-** Functions for the Field_decimal class
-** This is an unpacked number.
+ Functions for the Field_decimal class
+ This is an number stored as a pre-space (or pre-zero) string
****************************************************************************/
void
@@ -391,6 +337,8 @@ void Field_decimal::overflow(bool negative)
{
uint len=field_length;
char *to=ptr, filler= '9';
+
+ current_thd->cuted_fields++;
if (negative)
{
if (!unsigned_flag)
@@ -424,114 +372,362 @@ void Field_decimal::overflow(bool negative)
}
-int Field_decimal::store(const char *from,uint len,CHARSET_INFO *cs)
+int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs)
{
- reg3 int i;
- uint tmp_dec;
- char fyllchar;
- const char *end=from+len;
- struct st_decstr decstr;
- bool error;
+ const char *end= from+len;
+ /* The pointer where the field value starts (i.e., "where to write") */
+ char *to=ptr;
+ uint tmp_dec, tmp_uint;
+ /*
+ The sign of the number : will be 0 (means positive but sign not
+ specified), '+' or '-'
+ */
+ char sign_char=0;
+ /* The pointers where prezeros start and stop */
+ const char *pre_zeros_from, *pre_zeros_end;
+ /* The pointers where digits at the left of '.' start and stop */
+ const char *int_digits_from, *int_digits_end;
+ /* The pointers where digits at the right of '.' start and stop */
+ 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
+ /*
+ Pointers used when digits move from the left of the '.' to the
+ right of the '.' (explained below)
+ */
+ const char *int_digits_tail_from;
+ /* Number of 0 that need to be added at the left of the '.' (1E3: 3 zeros) */
+ uint int_digits_added_zeros;
+ /*
+ Pointer used when digits move from the right of the '.' to the left
+ of the '.'
+ */
+ const char *frac_digits_head_end;
+ /* Number of 0 that need to be added at the right of the '.' (for 1E-3) */
+ uint frac_digits_added_zeros;
+ char *pos,*tmp_left_pos,*tmp_right_pos;
+ /* Pointers that are used as limits (begin and end of the field buffer) */
+ char *left_wall,*right_wall;
+ char tmp_char;
+ /*
+ To remember if current_thd->cuted_fields has already been incremented,
+ to do that only once
+ */
+ bool is_cuted_fields_incr=0;
+
+ LINT_INIT(int_digits_tail_from);
+ LINT_INIT(int_digits_added_zeros);
+ LINT_INIT(frac_digits_head_end);
+ LINT_INIT(frac_digits_added_zeros);
+
+ /*
+ There are three steps in this function :
+ - parse the input string
+ - modify the position of digits around the decimal dot '.'
+ according to the exponent value (if specified)
+ - write the formatted number
+ */
+
+ if ((tmp_dec=dec))
+ tmp_dec++;
- if ((tmp_dec= dec))
- tmp_dec++; // Calculate pos of '.'
+ /* skip pre-space */
while (from != end && my_isspace(system_charset_info,*from))
from++;
- if (zerofill)
- {
- fyllchar = '0';
- if (from != end)
- while (*from == '0' && from != end-1) // Skip prezero
- from++;
- }
- else
- fyllchar=' ';
- error=number_dec(system_charset_info,&decstr,from,end);
- if (decstr.sign)
+ if (from == end)
{
- from++;
- if (unsigned_flag) // No sign with zerofill
- {
- if (decstr.sign_char == '+') // just remove "+"
- decstr.sign= 0;
- else
+ current_thd->cuted_fields++;
+ is_cuted_fields_incr=1;
+ }
+ else if (*from == '+' || *from == '-') // Found some sign ?
+ {
+ sign_char= *from++;
+ /*
+ We allow "+" for unsigned decimal unless defined different
+ Both options allowed as one may wish not to have "+" for unsigned numbers
+ because of data processing issues
+ */
+ if (unsigned_flag)
+ {
+ if (sign_char=='-')
{
- if (!error)
- current_thd->cuted_fields++;
- Field_decimal::overflow(1);
- return 1;
+ Field_decimal::overflow(1);
+ return 1;
}
+ /*
+ Defining this will not store "+" for unsigned decimal type even if
+ it is passed in numeric string. This will make some tests to fail
+ */
+#ifdef DONT_ALLOW_UNSIGNED_PLUS
+ else
+ sign_char=0;
+#endif
}
}
+
+ pre_zeros_from= from;
+ for (; from!=end && *from == '0'; from++) ; // Read prezeros
+ pre_zeros_end=int_digits_from=from;
+ /* Read non zero digits at the left of '.'*/
+ for (; from != end && my_isdigit(system_charset_info, *from) ; from++) ;
+ int_digits_end=from;
+ if (from!=end && *from == '.') // Some '.' ?
+ from++;
+ frac_digits_from= from;
+ /* Read digits at the right of '.' */
+ for (;from!=end && my_isdigit(system_charset_info, (*from); from++) ;
+ frac_digits_end=from;
+ // Some exponentiation symbol ?
+ if (from != end && (*from == 'e' || *from == 'E'))
+ {
+ from++;
+ if (from != end && (*from == '+' || *from == '-')) // Some exponent sign ?
+ expo_sign_char= *from++;
+ 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
+ */
+ for (;from!=end && my_isdigit(system_charset_info, (*from)); from++)
+ exponent=10*exponent+(*from-'0');
+ }
+
/*
- ** Remove pre-zeros if too big number
+ We only have to generate warnings if count_cuted_fields is set.
+ This is to avoid extra checks of the number when they are not needed.
+ Even if this flag is not set, it's ok to increment warnings, if
+ it makes the code easer to read.
*/
- for (i= (int) (decstr.nr_length+decstr.extra -(field_length-tmp_dec)+
- decstr.sign) ;
- i > 0 ;
- i--)
+
+ if (current_thd->count_cuted_fields)
{
- if (*from == '0')
+ for (;from != end && isspace(*from); from++) ; // Read end spaces
+ if (from != end) // If still something left, warn
{
- from++;
- decstr.nr_length--;
- continue;
+ current_thd->cuted_fields++;
+ is_cuted_fields_incr=1;
}
- if (decstr.sign && decstr.sign_char == '+' && i == 1)
- { // Remove pre '+'
- decstr.sign=0;
- break;
+ }
+
+ /*
+ Now "move" digits around the decimal dot according to the exponent value,
+ and add necessary zeros.
+ Examples :
+ - 1E+3 : needs 3 more zeros at the left of '.' (int_digits_added_zeros=3)
+ - 1E-3 : '1' moves at the right of '.', and 2 more zeros are needed
+ between '.' and '1'
+ - 1234.5E-3 : '234' moves at the right of '.'
+ These moves are implemented with pointers which point at the begin
+ and end of each moved segment. Examples :
+ - 1234.5E-3 : before the code below is executed, the int_digits part is
+ from '1' to '4' and the frac_digits part from '5' to '5'. After the code
+ below, the int_digits part is from '1' to '1', the frac_digits_head
+ part is from '2' to '4', and the frac_digits part from '5' to '5'.
+ - 1234.5E3 : before the code below is executed, the int_digits part is
+ from '1' to '4' and the frac_digits part from '5' to '5'. After the code
+ below, the int_digits part is from '1' to '4', the int_digits_tail
+ part is from '5' to '5', the frac_digits part is empty, and
+ int_digits_added_zeros=2 (to make 1234500).
+ */
+
+ if (!expo_sign_char)
+ tmp_uint=tmp_dec+(uint)(int_digits_end-int_digits_from);
+ else if (expo_sign_char == '-')
+ {
+ tmp_uint=min(exponent,(uint)(int_digits_end-int_digits_from));
+ 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);
+ }
+ else // (expo_sign_char=='+')
+ {
+ tmp_uint=min(exponent,(uint)(frac_digits_end-frac_digits_from));
+ int_digits_added_zeros=exponent-tmp_uint;
+ int_digits_tail_from=frac_digits_from;
+ frac_digits_from=frac_digits_from+tmp_uint;
+ /*
+ We "eat" the heading zeros of the
+ int_digits.int_digits_tail.int_digits_added_zeros concatenation
+ (for example 0.003e3 must become 3 and not 0003)
+ */
+ if (int_digits_from == int_digits_end)
+ {
+ /*
+ There was nothing in the int_digits part, so continue
+ eating int_digits_tail zeros
+ */
+ for (; int_digits_tail_from != frac_digits_from &&
+ *int_digits_tail_from == '0'; int_digits_tail_from++) ;
+ if (int_digits_tail_from == frac_digits_from)
+ {
+ // there were only zeros in int_digits_tail too
+ int_digits_added_zeros=0;
+ }
}
- current_thd->cuted_fields++;
+ tmp_uint=(tmp_dec+(uint)(int_digits_end-int_digits_from)
+ +(uint)(frac_digits_from-int_digits_tail_from)+
+ int_digits_added_zeros);
+ }
+
+ /*
+ Now write the formated number
+
+ First the digits of the int_% parts.
+ Do we have enough room to write these digits ?
+ If the sign is defined and '-', we need one position for it
+ */
+
+ if (field_length < tmp_uint + (int) (sign_char == '-'))
+ {
// too big number, change to max or min number
- Field_decimal::overflow(decstr.sign && decstr.sign_char == '-');
+ Field_decimal::overflow(sign_char == '-');
return 1;
}
- char *to=ptr;
- for (i=(int) (field_length-tmp_dec-decstr.nr_length-decstr.extra - decstr.sign) ;
- i-- > 0 ;)
- *to++ = fyllchar;
- if (decstr.sign)
- *to++= decstr.sign_char;
- if (decstr.extra)
- *to++ = '0';
- for (i=(int) decstr.nr_length ; i-- > 0 ; )
- *to++ = *from++;
- if (tmp_dec--)
- {
- *to++ ='.';
- if (decstr.nr_dec) from++; // Skip '.'
- for (i=(int) min(decstr.nr_dec,tmp_dec) ; i-- > 0 ; ) *to++ = *from++;
- for (i=(int) (tmp_dec-min(decstr.nr_dec,tmp_dec)) ; i-- > 0 ; ) *to++ = '0';
+
+ /*
+ Tmp_left_pos is the position where the leftmost digit of
+ the int_% parts will be written
+ */
+ tmp_left_pos=pos=to+(uint)(field_length-tmp_uint);
+
+ // Write all digits of the int_% parts
+ while (int_digits_from != int_digits_end)
+ *pos++ = *int_digits_from++ ;
+
+ if (expo_sign_char == '+')
+ {
+ while (int_digits_tail_from != frac_digits_from)
+ *pos++= *int_digits_tail_from++;
+ while (int_digits_added_zeros-- >0)
+ *pos++= '0';
}
+ /*
+ Note the position where the rightmost digit of the int_% parts has been
+ written (this is to later check if the int_% parts contained nothing,
+ meaning an extra 0 is needed).
+ */
+ tmp_right_pos=pos;
/*
- ** Check for incorrect string if in batch mode (ALTER TABLE/LOAD DATA...)
+ Step back to the position of the leftmost digit of the int_% parts,
+ to write sign and fill with zeros or blanks or prezeros.
*/
- if (!error && current_thd->count_cuted_fields && from != end)
- { // Check if number was cuted
- for (; from != end ; from++)
+ pos=tmp_left_pos-1;
+ if (zerofill)
+ {
+ left_wall=to-1;
+ while (pos != left_wall) // Fill with zeros
+ *pos--='0';
+ }
+ else
+ {
+ left_wall=to+(sign_char != 0)-1;
+ if (!expo_sign_char) // If exponent was specified, ignore prezeros
+ {
+ for (;pos != left_wall && pre_zeros_from !=pre_zeros_end;
+ pre_zeros_from++)
+ *pos--= '0';
+ }
+ if (pos == tmp_right_pos-1)
+ *pos--= '0'; // no 0 has ever been written, so write one
+ left_wall= to-1;
+ if (sign_char && pos != left_wall)
+ {
+ /* Write sign if possible (it is if sign is '-') */
+ *pos--= sign_char;
+ }
+ while (pos != left_wall)
+ *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)
+ */
+
+ pos=to+(uint)(field_length-tmp_dec); // Calculate post to '.'
+ *pos++='.';
+ right_wall=to+field_length;
+
+ if (expo_sign_char == '-')
{
- if (*from != '0')
+ while (frac_digits_added_zeros-- > 0)
{
- if (!my_isspace(system_charset_info,*from)) // Space is ok
- current_thd->cuted_fields++;
- break;
+ 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';
+ }
+ while (int_digits_end != frac_digits_head_end)
+ {
+ 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;
+ }
+ }
+
+ for (;frac_digits_from!=frac_digits_end;)
+ {
+ tmp_char= *frac_digits_from++;
+ 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;
}
+
+ while (pos != right_wall)
+ *pos++='0'; // Fill with zeros at right of '.'
}
- return (error) ? 1 : 0;
+ return 0;
}
-int Field_decimal::store(double nr)
+int Field_decimal::store(double nr)
{
if (unsigned_flag && nr < 0)
{
overflow(1);
- current_thd->cuted_fields++;
return 1;
}
+
+#ifdef HAVE_FINITE
+ if (!finite(nr)) // Handle infinity as special case
+ {
+ overflow(nr < 0.0);
+ return 1;
+ }
+#endif
+
reg4 uint i,length;
char fyllchar,*to;
char buff[320];
@@ -548,7 +744,6 @@ int Field_decimal::store(double nr)
if (length > field_length)
{
overflow(nr < 0.0);
- current_thd->cuted_fields++;
return 1;
}
else
@@ -562,12 +757,11 @@ int Field_decimal::store(double nr)
}
-int Field_decimal::store(longlong nr)
+int Field_decimal::store(longlong nr)
{
if (unsigned_flag && nr < 0)
{
overflow(1);
- current_thd->cuted_fields++;
return 1;
}
char buff[22];
@@ -577,7 +771,6 @@ int Field_decimal::store(longlong nr)
if (length > int_part)
{
overflow(test(nr < 0L)); /* purecov: inspected */
- current_thd->cuted_fields++; /* purecov: inspected */
return 1;
}
else
@@ -673,8 +866,8 @@ void Field_decimal::sort_string(char *to,uint length)
char *str,*end;
for (str=ptr,end=ptr+length;
str != end &&
- ((my_isspace(system_charset_info,*str) || *str == '+' || *str == '0')) ;
-
+ ((my_isspace(system_charset_info,*str) || *str == '+' ||
+ *str == '0')) ;
str++)
*to++=' ';
if (str == end)
@@ -693,6 +886,7 @@ void Field_decimal::sort_string(char *to,uint length)
else memcpy(to,str,(uint) (end-str));
}
+
void Field_decimal::sql_type(String &res) const
{
uint tmp=field_length;
@@ -709,11 +903,11 @@ void Field_decimal::sql_type(String &res) const
** tiny int
****************************************************************************/
-int Field_tiny::store(const char *from,uint len,CHARSET_INFO *cs)
+int Field_tiny::store(const char *from,uint len,CHARSET_INFO *cs)
{
String tmp_str(from,len,default_charset_info);
long tmp= strtol(tmp_str.c_ptr(),NULL,10);
- int error=0;
+ int error= 0;
if (unsigned_flag)
{
@@ -721,18 +915,18 @@ int Field_tiny::store(const char *from,uint len,CHARSET_INFO *cs)
{
tmp=0; /* purecov: inspected */
current_thd->cuted_fields++; /* purecov: inspected */
- error = 1;
+ error= 1;
}
else if (tmp > 255)
{
tmp= 255;
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
else if (current_thd->count_cuted_fields && !test_if_int(from,len))
{
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
}
else
@@ -741,18 +935,18 @@ int Field_tiny::store(const char *from,uint len,CHARSET_INFO *cs)
{
tmp= -128;
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
else if (tmp >= 128)
{
tmp= 127;
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
else if (current_thd->count_cuted_fields && !test_if_int(from,len))
{
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
}
ptr[0]= (char) tmp;
@@ -760,9 +954,9 @@ int Field_tiny::store(const char *from,uint len,CHARSET_INFO *cs)
}
-int Field_tiny::store(double nr)
+int Field_tiny::store(double nr)
{
- int error=0;
+ int error= 0;
nr=rint(nr);
if (unsigned_flag)
{
@@ -770,13 +964,13 @@ int Field_tiny::store(double nr)
{
*ptr=0;
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
else if (nr > 255.0)
{
*ptr=(char) 255;
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
else
*ptr=(char) nr;
@@ -787,13 +981,13 @@ int Field_tiny::store(double nr)
{
*ptr= (char) -128;
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
else if (nr > 127.0)
{
*ptr=127;
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
else
*ptr=(char) nr;
@@ -801,22 +995,22 @@ int Field_tiny::store(double nr)
return error;
}
-int Field_tiny::store(longlong nr)
+int Field_tiny::store(longlong nr)
{
- int error=0;
+ int error= 0;
if (unsigned_flag)
{
if (nr < 0L)
{
*ptr=0;
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
else if (nr > 255L)
{
*ptr= (char) 255;
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
else
*ptr=(char) nr;
@@ -827,13 +1021,13 @@ int Field_tiny::store(longlong nr)
{
*ptr= (char) -128;
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
else if (nr > 127L)
{
*ptr=127;
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
else
*ptr=(char) nr;
@@ -904,29 +1098,29 @@ void Field_tiny::sql_type(String &res) const
// Note: Sometimes this should be fixed to use one strtol() to use
// len and check for garbage after number.
-int Field_short::store(const char *from,uint len,CHARSET_INFO *cs)
+int Field_short::store(const char *from,uint len,CHARSET_INFO *cs)
{
String tmp_str(from,len,default_charset_info);
long tmp= strtol(tmp_str.c_ptr(),NULL,10);
- int error=0;
+ int error= 0;
if (unsigned_flag)
{
if (tmp < 0)
{
tmp=0;
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
else if (tmp > (uint16) ~0)
{
tmp=(uint16) ~0;
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
else if (current_thd->count_cuted_fields && !test_if_int(from,len))
{
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
}
else
@@ -935,18 +1129,18 @@ int Field_short::store(const char *from,uint len,CHARSET_INFO *cs)
{
tmp= INT_MIN16;
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
else if (tmp > INT_MAX16)
{
tmp=INT_MAX16;
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
else if (current_thd->count_cuted_fields && !test_if_int(from,len))
{
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
}
#ifdef WORDS_BIGENDIAN
@@ -961,9 +1155,9 @@ int Field_short::store(const char *from,uint len,CHARSET_INFO *cs)
}
-int Field_short::store(double nr)
+int Field_short::store(double nr)
{
- int error=0;
+ int error= 0;
int16 res;
nr=rint(nr);
if (unsigned_flag)
@@ -972,13 +1166,13 @@ int Field_short::store(double nr)
{
res=0;
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
else if (nr > (double) (uint16) ~0)
{
res=(int16) (uint16) ~0;
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
else
res=(int16) (uint16) nr;
@@ -989,13 +1183,13 @@ int Field_short::store(double nr)
{
res=INT_MIN16;
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
else if (nr > (double) INT_MAX16)
{
res=INT_MAX16;
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
else
res=(int16) nr;
@@ -1011,9 +1205,9 @@ int Field_short::store(double nr)
return error;
}
-int Field_short::store(longlong nr)
+int Field_short::store(longlong nr)
{
- int error=0;
+ int error= 0;
int16 res;
if (unsigned_flag)
{
@@ -1021,13 +1215,13 @@ int Field_short::store(longlong nr)
{
res=0;
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
else if (nr > (longlong) (uint16) ~0)
{
res=(int16) (uint16) ~0;
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
else
res=(int16) (uint16) nr;
@@ -1038,13 +1232,13 @@ int Field_short::store(longlong nr)
{
res=INT_MIN16;
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
else if (nr > INT_MAX16)
{
res=INT_MAX16;
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
else
res=(int16) nr;
@@ -1168,11 +1362,11 @@ void Field_short::sql_type(String &res) const
// Note: Sometimes this should be fixed to use one strtol() to use
// len and check for garbage after number.
-int Field_medium::store(const char *from,uint len,CHARSET_INFO *cs)
+int Field_medium::store(const char *from,uint len,CHARSET_INFO *cs)
{
String tmp_str(from,len,default_charset_info);
long tmp= strtol(tmp_str.c_ptr(),NULL,10);
- int error=0;
+ int error= 0;
if (unsigned_flag)
{
@@ -1180,18 +1374,18 @@ int Field_medium::store(const char *from,uint len,CHARSET_INFO *cs)
{
tmp=0;
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
else if (tmp >= (long) (1L << 24))
{
tmp=(long) (1L << 24)-1L;
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
else if (current_thd->count_cuted_fields && !test_if_int(from,len))
{
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
}
else
@@ -1200,18 +1394,18 @@ int Field_medium::store(const char *from,uint len,CHARSET_INFO *cs)
{
tmp= INT_MIN24;
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
else if (tmp > INT_MAX24)
{
tmp=INT_MAX24;
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
else if (current_thd->count_cuted_fields && !test_if_int(from,len))
{
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
}
@@ -1220,9 +1414,9 @@ int Field_medium::store(const char *from,uint len,CHARSET_INFO *cs)
}
-int Field_medium::store(double nr)
+int Field_medium::store(double nr)
{
- int error=0;
+ int error= 0;
nr=rint(nr);
if (unsigned_flag)
{
@@ -1230,14 +1424,14 @@ int Field_medium::store(double nr)
{
int3store(ptr,0);
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
else if (nr >= (double) (long) (1L << 24))
{
uint32 tmp=(uint32) (1L << 24)-1L;
int3store(ptr,tmp);
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
else
int3store(ptr,(uint32) nr);
@@ -1249,14 +1443,14 @@ int Field_medium::store(double nr)
long tmp=(long) INT_MIN24;
int3store(ptr,tmp);
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
else if (nr > (double) INT_MAX24)
{
long tmp=(long) INT_MAX24;
int3store(ptr,tmp);
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
else
int3store(ptr,(long) nr);
@@ -1264,23 +1458,23 @@ int Field_medium::store(double nr)
return error;
}
-int Field_medium::store(longlong nr)
+int Field_medium::store(longlong nr)
{
- int error=0;
+ int error= 0;
if (unsigned_flag)
{
if (nr < 0L)
{
int3store(ptr,0);
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
else if (nr >= (longlong) (long) (1L << 24))
{
long tmp=(long) (1L << 24)-1L;;
int3store(ptr,tmp);
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
else
int3store(ptr,(uint32) nr);
@@ -1292,14 +1486,14 @@ int Field_medium::store(longlong nr)
long tmp=(long) INT_MIN24;
int3store(ptr,tmp);
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
else if (nr > (longlong) INT_MAX24)
{
long tmp=(long) INT_MAX24;
int3store(ptr,tmp);
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
else
int3store(ptr,(long) nr);
@@ -1377,14 +1571,14 @@ void Field_medium::sql_type(String &res) const
// Note: Sometimes this should be fixed to use one strtol() to use
// len and check for garbage after number.
-int Field_long::store(const char *from,uint len,CHARSET_INFO *cs)
+int Field_long::store(const char *from,uint len,CHARSET_INFO *cs)
{
while (len && my_isspace(system_charset_info,*from))
{
len--; from++;
}
long tmp;
- int error=0;
+ int error= 0;
String tmp_str(from,len,default_charset_info);
errno=0;
if (unsigned_flag)
@@ -1393,7 +1587,7 @@ int Field_long::store(const char *from,uint len,CHARSET_INFO *cs)
{
tmp=0; // Set negative to 0
errno=ERANGE;
- error = 1;
+ error= 1;
}
else
tmp=(long) strtoul(tmp_str.c_ptr(),NULL,10);
@@ -1403,7 +1597,7 @@ int Field_long::store(const char *from,uint len,CHARSET_INFO *cs)
if (errno || current_thd->count_cuted_fields && !test_if_int(from,len))
{
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
#ifdef WORDS_BIGENDIAN
if (table->db_low_byte_first)
@@ -1417,9 +1611,9 @@ int Field_long::store(const char *from,uint len,CHARSET_INFO *cs)
}
-int Field_long::store(double nr)
+int Field_long::store(double nr)
{
- int error=0;
+ int error= 0;
int32 res;
nr=rint(nr);
if (unsigned_flag)
@@ -1428,13 +1622,13 @@ int Field_long::store(double nr)
{
res=0;
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
else if (nr > (double) (ulong) ~0L)
{
res=(int32) (uint32) ~0L;
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
else
res=(int32) (ulong) nr;
@@ -1445,13 +1639,13 @@ int Field_long::store(double nr)
{
res=(int32) INT_MIN32;
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
else if (nr > (double) INT_MAX32)
{
res=(int32) INT_MAX32;
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
else
res=(int32) nr;
@@ -1468,9 +1662,9 @@ int Field_long::store(double nr)
}
-int Field_long::store(longlong nr)
+int Field_long::store(longlong nr)
{
- int error=0;
+ int error= 0;
int32 res;
if (unsigned_flag)
{
@@ -1478,13 +1672,13 @@ int Field_long::store(longlong nr)
{
res=0;
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
else if (nr >= (LL(1) << 32))
{
res=(int32) (uint32) ~0L;
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
else
res=(int32) (uint32) nr;
@@ -1495,13 +1689,13 @@ int Field_long::store(longlong nr)
{
res=(int32) INT_MIN32;
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
else if (nr > (longlong) INT_MAX32)
{
res=(int32) INT_MAX32;
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
else
res=(int32) nr;
@@ -1623,7 +1817,7 @@ void Field_long::sql_type(String &res) const
** longlong int
****************************************************************************/
-int Field_longlong::store(const char *from,uint len,CHARSET_INFO *cs)
+int Field_longlong::store(const char *from,uint len,CHARSET_INFO *cs)
{
while (len && my_isspace(system_charset_info,*from))
{ // For easy error check
@@ -1631,7 +1825,7 @@ int Field_longlong::store(const char *from,uint len,CHARSET_INFO *cs)
}
longlong tmp;
String tmp_str(from,len,default_charset_info);
- int error=0;
+ int error= 0;
errno=0;
if (unsigned_flag)
{
@@ -1639,7 +1833,7 @@ int Field_longlong::store(const char *from,uint len,CHARSET_INFO *cs)
{
tmp=0; // Set negative to 0
errno=ERANGE;
- error = 1;
+ error= 1;
}
else
tmp=(longlong) strtoull(tmp_str.c_ptr(),NULL,10);
@@ -1649,7 +1843,7 @@ int Field_longlong::store(const char *from,uint len,CHARSET_INFO *cs)
if (errno || current_thd->count_cuted_fields && !test_if_int(from,len))
{
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
#ifdef WORDS_BIGENDIAN
if (table->db_low_byte_first)
@@ -1663,9 +1857,9 @@ int Field_longlong::store(const char *from,uint len,CHARSET_INFO *cs)
}
-int Field_longlong::store(double nr)
+int Field_longlong::store(double nr)
{
- int error=0;
+ int error= 0;
longlong res;
nr=rint(nr);
if (unsigned_flag)
@@ -1674,13 +1868,13 @@ int Field_longlong::store(double nr)
{
res=0;
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
else if (nr >= (double) ~ (ulonglong) 0)
{
res= ~(longlong) 0;
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
else
res=(longlong) (ulonglong) nr;
@@ -1691,13 +1885,13 @@ int Field_longlong::store(double nr)
{
res=(longlong) LONGLONG_MIN;
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
else if (nr >= (double) LONGLONG_MAX)
{
res=(longlong) LONGLONG_MAX;
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
else
res=(longlong) nr;
@@ -1714,7 +1908,7 @@ int Field_longlong::store(double nr)
}
-int Field_longlong::store(longlong nr)
+int Field_longlong::store(longlong nr)
{
#ifdef WORDS_BIGENDIAN
if (table->db_low_byte_first)
@@ -1843,7 +2037,7 @@ void Field_longlong::sql_type(String &res) const
** single precision float
****************************************************************************/
-int Field_float::store(const char *from,uint len,CHARSET_INFO *cs)
+int Field_float::store(const char *from,uint len,CHARSET_INFO *cs)
{
String tmp_str(from,len,default_charset_info);
errno=0;
@@ -1857,29 +2051,29 @@ int Field_float::store(const char *from,uint len,CHARSET_INFO *cs)
}
-int Field_float::store(double nr)
+int Field_float::store(double nr)
{
float j;
- int error=0;
+ int error= 0;
if (dec < NOT_FIXED_DEC)
nr=floor(nr*log_10[dec]+0.5)/log_10[dec]; // To fixed point
if (unsigned_flag && nr < 0)
{
current_thd->cuted_fields++;
nr=0;
- error = 1;
+ error= 1;
}
if (nr < -FLT_MAX)
{
j= -FLT_MAX;
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
else if (nr > FLT_MAX)
{
j=FLT_MAX;
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
else
j= (float) nr;
@@ -1895,15 +2089,15 @@ int Field_float::store(double nr)
}
-int Field_float::store(longlong nr)
+int Field_float::store(longlong nr)
{
- int error=0;
+ int error= 0;
float j= (float) nr;
if (unsigned_flag && j < 0)
{
current_thd->cuted_fields++;
j=0;
- error = 1;
+ error= 1;
}
#ifdef WORDS_BIGENDIAN
if (table->db_low_byte_first)
@@ -2105,22 +2299,22 @@ void Field_float::sql_type(String &res) const
** double precision floating point numbers
****************************************************************************/
-int Field_double::store(const char *from,uint len,CHARSET_INFO *cs)
+int Field_double::store(const char *from,uint len,CHARSET_INFO *cs)
{
String tmp_str(from,len,default_charset_info);
errno=0;
- int error=0;
+ int error= 0;
double j= atof(tmp_str.c_ptr());
if (errno || current_thd->count_cuted_fields && !test_if_real(from,len))
{
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
if (unsigned_flag && j < 0)
{
current_thd->cuted_fields++;
j=0;
- error = 1;
+ error= 1;
}
#ifdef WORDS_BIGENDIAN
if (table->db_low_byte_first)
@@ -2134,16 +2328,16 @@ int Field_double::store(const char *from,uint len,CHARSET_INFO *cs)
}
-int Field_double::store(double nr)
+int Field_double::store(double nr)
{
- int error=0;
+ int error= 0;
if (dec < NOT_FIXED_DEC)
nr=floor(nr*log_10[dec]+0.5)/log_10[dec]; // To fixed point
if (unsigned_flag && nr < 0)
{
current_thd->cuted_fields++;
nr=0;
- error = 1;
+ error= 1;
}
#ifdef WORDS_BIGENDIAN
if (table->db_low_byte_first)
@@ -2157,14 +2351,14 @@ int Field_double::store(double nr)
}
-int Field_double::store(longlong nr)
+int Field_double::store(longlong nr)
{
double j= (double) nr;
- int error=0;
+ int error= 0;
if (unsigned_flag && j < 0)
{
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
j=0;
}
#ifdef WORDS_BIGENDIAN
@@ -2373,7 +2567,7 @@ Field_timestamp::Field_timestamp(char *ptr_arg, uint32 len_arg,
}
-int Field_timestamp::store(const char *from,uint len,CHARSET_INFO *cs)
+int Field_timestamp::store(const char *from,uint len,CHARSET_INFO *cs)
{
long tmp=(long) str_to_timestamp(from,len);
#ifdef WORDS_BIGENDIAN
@@ -2387,7 +2581,7 @@ int Field_timestamp::store(const char *from,uint len,CHARSET_INFO *cs)
return 0;
}
-void Field_timestamp::fill_and_store(char *from,uint len)
+void Field_timestamp::fill_and_store(char *from,uint len)
{
uint res_length;
if (len <= field_length)
@@ -2416,16 +2610,16 @@ void Field_timestamp::fill_and_store(char *from,uint len)
}
-int Field_timestamp::store(double nr)
+int Field_timestamp::store(double nr)
{
- int error=0;
+ int error= 0;
if (nr < 0 || nr > 99991231235959.0)
{
- nr=0; // Avoid overflow on buff
+ nr= 0; // Avoid overflow on buff
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
- error |= Field_timestamp::store((longlong) rint(nr));
+ error|= Field_timestamp::store((longlong) rint(nr));
return error;
}
@@ -2467,7 +2661,7 @@ static longlong fix_datetime(longlong nr)
}
-int Field_timestamp::store(longlong nr)
+int Field_timestamp::store(longlong nr)
{
TIME l_time;
time_t timestamp;
@@ -2717,15 +2911,15 @@ void Field_timestamp::set_time()
** Stored as a 3 byte unsigned int
****************************************************************************/
-int Field_time::store(const char *from,uint len,CHARSET_INFO *cs)
+int Field_time::store(const char *from,uint len,CHARSET_INFO *cs)
{
TIME ltime;
long tmp;
- int error=0;
+ int error= 0;
if (str_to_time(from,len,&ltime))
{
tmp=0L;
- error = 1;
+ error= 1;
}
else
{
@@ -2736,7 +2930,7 @@ int Field_time::store(const char *from,uint len,CHARSET_INFO *cs)
{
tmp=8385959;
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
}
if (ltime.neg)
@@ -2746,21 +2940,21 @@ int Field_time::store(const char *from,uint len,CHARSET_INFO *cs)
}
-int Field_time::store(double nr)
+int Field_time::store(double nr)
{
long tmp;
- int error=0;
+ int error= 0;
if (nr > 8385959.0)
{
tmp=8385959L;
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
else if (nr < -8385959.0)
{
tmp= -8385959L;
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
else
{
@@ -2771,7 +2965,7 @@ int Field_time::store(double nr)
{
tmp=0;
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
}
int3store(ptr,tmp);
@@ -2779,21 +2973,21 @@ int Field_time::store(double nr)
}
-int Field_time::store(longlong nr)
+int Field_time::store(longlong nr)
{
long tmp;
- int error=0;
+ int error= 0;
if (nr > (longlong) 8385959L)
{
tmp=8385959L;
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
else if (nr < (longlong) -8385959L)
{
tmp= -8385959L;
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
else
{
@@ -2802,7 +2996,7 @@ int Field_time::store(longlong nr)
{
tmp=0;
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
}
int3store(ptr,tmp);
@@ -2882,7 +3076,7 @@ void Field_time::sql_type(String &res) const
** Can handle 2 byte or 4 byte years!
****************************************************************************/
-int Field_year::store(const char *from, uint len,CHARSET_INFO *cs)
+int Field_year::store(const char *from, uint len,CHARSET_INFO *cs)
{
String tmp_str(from,len,default_charset_info);
long nr= strtol(tmp_str.c_ptr(),NULL,10);
@@ -2906,7 +3100,7 @@ int Field_year::store(const char *from, uint len,CHARSET_INFO *cs)
return 0;
}
-int Field_year::store(double nr)
+int Field_year::store(double nr)
{
if (nr < 0.0 || nr >= 2155.0)
{
@@ -2917,7 +3111,7 @@ int Field_year::store(double nr)
return Field_year::store((longlong) nr);
}
-int Field_year::store(longlong nr)
+int Field_year::store(longlong nr)
{
if (nr < 0 || nr >= 100 && nr <= 1900 || nr > 2155)
{
@@ -2976,15 +3170,15 @@ void Field_year::sql_type(String &res) const
** Stored as a 4 byte unsigned int
****************************************************************************/
-int Field_date::store(const char *from, uint len,CHARSET_INFO *cs)
+int Field_date::store(const char *from, uint len,CHARSET_INFO *cs)
{
TIME l_time;
uint32 tmp;
- int error=0;
+ int error= 0;
if (str_to_TIME(from,len,&l_time,1) == TIMESTAMP_NONE)
{
tmp=0;
- error = 1;
+ error= 1;
}
else
tmp=(uint32) l_time.year*10000L + (uint32) (l_time.month*100+l_time.day);
@@ -3000,17 +3194,17 @@ int Field_date::store(const char *from, uint len,CHARSET_INFO *cs)
}
-int Field_date::store(double nr)
+int Field_date::store(double nr)
{
long tmp;
- int error=0;
+ int error= 0;
if (nr >= 19000000000000.0 && nr <= 99991231235959.0)
nr=floor(nr/1000000.0); // Timestamp to date
if (nr < 0.0 || nr > 99991231.0)
{
tmp=0L;
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
else
tmp=(long) rint(nr);
@@ -3026,17 +3220,17 @@ int Field_date::store(double nr)
}
-int Field_date::store(longlong nr)
+int Field_date::store(longlong nr)
{
long tmp;
- int error=0;
+ int error= 0;
if (nr >= LL(19000000000000) && nr < LL(99991231235959))
nr=nr/LL(1000000); // Timestamp to date
if (nr < 0 || nr > LL(99991231))
{
tmp=0L;
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
else
tmp=(long) nr;
@@ -3144,15 +3338,15 @@ void Field_date::sql_type(String &res) const
** In number context: YYYYMMDD
****************************************************************************/
-int Field_newdate::store(const char *from,uint len,CHARSET_INFO *cs)
+int Field_newdate::store(const char *from,uint len,CHARSET_INFO *cs)
{
TIME l_time;
long tmp;
- int error=0;
+ int error= 0;
if (str_to_TIME(from,len,&l_time,1) == TIMESTAMP_NONE)
{
tmp=0L;
- error = 1;
+ error= 1;
}
else
tmp= l_time.day + l_time.month*32 + l_time.year*16*32;
@@ -3160,7 +3354,7 @@ int Field_newdate::store(const char *from,uint len,CHARSET_INFO *cs)
return error;
}
-int Field_newdate::store(double nr)
+int Field_newdate::store(double nr)
{
if (nr < 0.0 || nr > 99991231235959.0)
{
@@ -3172,17 +3366,17 @@ int Field_newdate::store(double nr)
}
-int Field_newdate::store(longlong nr)
+int Field_newdate::store(longlong nr)
{
int32 tmp;
- int error=0;
+ int error= 0;
if (nr >= LL(100000000) && nr <= LL(99991231235959))
nr=nr/LL(1000000); // Timestamp to date
if (nr < 0L || nr > 99991231L)
{
tmp=0;
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
else
{
@@ -3200,7 +3394,7 @@ int Field_newdate::store(longlong nr)
{
tmp=0L; // Don't allow date to change
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
else
tmp= day + month*32 + (tmp/10000)*16*32;
@@ -3309,7 +3503,7 @@ void Field_newdate::sql_type(String &res) const
** Stored as a 8 byte unsigned int. Should sometimes be change to a 6 byte int.
****************************************************************************/
-int Field_datetime::store(const char *from,uint len,CHARSET_INFO *cs)
+int Field_datetime::store(const char *from,uint len,CHARSET_INFO *cs)
{
longlong tmp=str_to_datetime(from,len,1);
#ifdef WORDS_BIGENDIAN
@@ -3324,28 +3518,28 @@ int Field_datetime::store(const char *from,uint len,CHARSET_INFO *cs)
}
-int Field_datetime::store(double nr)
+int Field_datetime::store(double nr)
{
- int error=0;
+ int error= 0;
if (nr < 0.0 || nr > 99991231235959.0)
{
nr=0.0;
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
error |= Field_datetime::store((longlong) rint(nr));
return error;
}
-int Field_datetime::store(longlong nr)
+int Field_datetime::store(longlong nr)
{
- int error=0;
+ int error= 0;
if (nr < 0 || nr > LL(99991231235959))
{
nr=0;
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
else
nr=fix_datetime(nr);
@@ -3532,14 +3726,14 @@ void Field_datetime::sql_type(String &res) const
/* Copy a string and fill with space */
-int Field_string::store(const char *from,uint length,CHARSET_INFO *cs)
+int Field_string::store(const char *from,uint length,CHARSET_INFO *cs)
{
field_charset=cs;
- int error=0;
+ int error= 0;
#ifdef USE_TIS620
- if(!binary_flag) {
+ if (!binary_flag) {
ThNormalize((uchar *)ptr, field_length, (uchar *)from, length);
- if(length < field_length) {
+ if (length < field_length) {
bfill(ptr + length, field_length - length, ' ');
}
}
@@ -3572,7 +3766,7 @@ int Field_string::store(const char *from,uint length,CHARSET_INFO *cs)
}
-int Field_string::store(double nr)
+int Field_string::store(double nr)
{
char buff[MAX_FIELD_WIDTH],*end;
int width=min(field_length,DBL_DIG+5);
@@ -3582,7 +3776,7 @@ int Field_string::store(double nr)
}
-int Field_string::store(longlong nr)
+int Field_string::store(longlong nr)
{
char buff[22];
char *end=longlong10_to_str(nr,buff,-10);
@@ -3745,12 +3939,12 @@ uint Field_string::max_packed_col_length(uint max_length)
****************************************************************************/
-int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs)
+int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs)
{
- int error=0;
+ int error= 0;
field_charset=cs;
#ifdef USE_TIS620
- if(!binary_flag)
+ if (!binary_flag)
{
ThNormalize((uchar *) ptr+2, field_length, (uchar *) from, length);
}
@@ -3764,7 +3958,7 @@ int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs)
length=field_length;
memcpy(ptr+2,from,field_length);
current_thd->cuted_fields++;
- error = 1;
+ error= 1;
}
#endif /* USE_TIS620 */
int2store(ptr,length);
@@ -3772,7 +3966,7 @@ int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs)
}
-int Field_varstring::store(double nr)
+int Field_varstring::store(double nr)
{
char buff[MAX_FIELD_WIDTH],*end;
int width=min(field_length,DBL_DIG+5);
@@ -3782,7 +3976,7 @@ int Field_varstring::store(double nr)
}
-int Field_varstring::store(longlong nr)
+int Field_varstring::store(longlong nr)
{
char buff[22];
char *end=longlong10_to_str(nr,buff,-10);
@@ -4071,7 +4265,7 @@ uint32 Field_blob::get_length(const char *pos)
}
-int Field_blob::store(const char *from,uint len,CHARSET_INFO *cs)
+int Field_blob::store(const char *from,uint len,CHARSET_INFO *cs)
{
field_charset=cs;
if (!len)
@@ -4087,7 +4281,7 @@ int Field_blob::store(const char *from,uint len,CHARSET_INFO *cs)
if (table->copy_blobs || len <= MAX_FIELD_WIDTH)
{ // Must make a copy
#ifdef USE_TIS620
- if(!binary_flag)
+ if (!binary_flag)
{
/* If there isn't enough memory, use original string */
if ((th_ptr=(char * ) my_malloc(sizeof(char) * len,MYF(0))))
@@ -4109,17 +4303,19 @@ int Field_blob::store(const char *from,uint len,CHARSET_INFO *cs)
}
-int Field_blob::store(double nr)
+int Field_blob::store(double nr)
{
value.set(nr);
- return Field_blob::store(value.ptr(),(uint) value.length(), default_charset_info);
+ return Field_blob::store(value.ptr(),(uint) value.length(),
+ default_charset_info);
}
-int Field_blob::store(longlong nr)
+int Field_blob::store(longlong nr)
{
value.set(nr);
- return Field_blob::store(value.ptr(), (uint) value.length(), default_charset_info);
+ return Field_blob::store(value.ptr(), (uint) value.length(),
+ default_charset_info);
}
@@ -4226,16 +4422,15 @@ int Field_blob::cmp_binary(const char *a_ptr, const char *b_ptr,
void Field_blob::get_key_image(char *buff,uint length, imagetype type)
{
- if(type == itMBR)
+ length-= HA_KEY_BLOB_LENGTH;
+ uint32 blob_length= get_length(ptr);
+ char *blob;
+
+ if (type == itMBR)
{
- length-=HA_KEY_BLOB_LENGTH;
- ulong blob_length=get_length(ptr);
- char *blob;
- get_ptr(&blob);
- if(!blob_length)
- {
+ if (!blob_length)
return;
- }
+ get_ptr(&blob);
MBR mbr;
Geometry gobj;
@@ -4249,8 +4444,6 @@ void Field_blob::get_key_image(char *buff,uint length, imagetype type)
}
length-=HA_KEY_BLOB_LENGTH;
- uint32 blob_length=get_length(ptr);
- char *blob;
if ((uint32) length > blob_length)
{
#ifdef HAVE_purify
@@ -4269,6 +4462,7 @@ void Field_blob::set_key_image(char *buff,uint length)
(void) Field_blob::store(buff+2,length, default_charset_info);
}
+
void Field_geom::get_key_image(char *buff,uint length, imagetype type)
{
length-=HA_KEY_BLOB_LENGTH;
@@ -4293,7 +4487,6 @@ void Field_geom::set_key_image(char *buff,uint length)
}
-
int Field_blob::key_cmp(const byte *key_ptr, uint max_key_length)
{
char *blob1;
@@ -4587,9 +4780,9 @@ uint find_enum(TYPELIB *lib,const char *x, uint length)
** (if there isn't a empty value in the enum)
*/
-int Field_enum::store(const char *from,uint length,CHARSET_INFO *cs)
+int Field_enum::store(const char *from,uint length,CHARSET_INFO *cs)
{
- int error=0;
+ int error= 0;
uint tmp=find_enum(typelib,from,length);
if (!tmp)
{
@@ -4620,15 +4813,15 @@ int Field_enum::store(const char *from,uint length,CHARSET_INFO *cs)
}
-int Field_enum::store(double nr)
+int Field_enum::store(double nr)
{
return Field_enum::store((longlong) nr);
}
-int Field_enum::store(longlong nr)
+int Field_enum::store(longlong nr)
{
- int error=0;
+ int error= 0;
if ((uint) nr > typelib->count || nr == 0)
{
current_thd->cuted_fields++;
@@ -4763,11 +4956,11 @@ ulonglong find_set(TYPELIB *lib,const char *x,uint length)
if (x != end)
{
const char *start=x;
- bool error=0;
+ bool error= 0;
for (;;)
{
const char *pos=start;
- for ( ; pos != end && *pos != field_separator ; pos++) ;
+ for (; pos != end && *pos != field_separator ; pos++) ;
uint find=find_enum(lib,start,(uint) (pos-start));
if (!find)
error=1;
@@ -4784,9 +4977,9 @@ ulonglong find_set(TYPELIB *lib,const char *x,uint length)
}
-int Field_set::store(const char *from,uint length,CHARSET_INFO *cs)
+int Field_set::store(const char *from,uint length,CHARSET_INFO *cs)
{
- int error=0;
+ int error= 0;
ulonglong tmp=find_set(typelib,from,length);
if (!tmp && length && length < 22)
{
@@ -4814,9 +5007,9 @@ int Field_set::store(const char *from,uint length,CHARSET_INFO *cs)
}
-int Field_set::store(longlong nr)
+int Field_set::store(longlong nr)
{
- int error=0;
+ int error= 0;
if ((ulonglong) nr > (ulonglong) (((longlong) 1 << typelib->count) -
(longlong) 1))
{
@@ -4914,7 +5107,7 @@ bool Field_num::eq_def(Field *field)
*****************************************************************************/
/*
-** Make a field from the .frm file info
+ Make a field from the .frm file info
*/
uint32 calc_pack_length(enum_field_types type,uint32 length)
@@ -5116,7 +5309,8 @@ create_field::create_field(Field *old_field,Field *orig_field)
orig_field)
{
char buff[MAX_FIELD_WIDTH],*pos;
- String tmp(buff,sizeof(buff),default_charset_info);
+ CHARSET_INFO *field_charset= charset ? charset : default_charset_info;
+ String tmp(buff,sizeof(buff),field_charset);
/* Get the value from record[2] (the default value row) */
my_ptrdiff_t diff= (my_ptrdiff_t) (orig_field->table->rec_buff_length*2);
@@ -5128,7 +5322,7 @@ create_field::create_field(Field *old_field,Field *orig_field)
{
pos= (char*) sql_memdup(tmp.ptr(),tmp.length()+1);
pos[tmp.length()]=0;
- def=new Item_string(pos,tmp.length(),default_charset_info);
+ def=new Item_string(pos,tmp.length(),field_charset);
}
}
}
diff --git a/sql/field.h b/sql/field.h
index 88187b2b7aa..551619abc6f 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -43,7 +43,7 @@ public:
const char *table_name,*field_name;
LEX_STRING comment;
ulong query_id; // For quick test of used fields
- // Field is part of the following keys
+ /* Field is part of the following keys */
key_map key_start,part_of_key,part_of_sortkey;
enum utype { NONE,DATE,SHIELD,NOEMPTY,CASEUP,PNR,BGNR,PGNR,YES,NO,REL,
CHECK,EMPTY,UNKNOWN_FIELD,CASEDN,NEXT_NUMBER,INTERVAL_FIELD,
@@ -74,6 +74,13 @@ public:
virtual uint32 pack_length() const { return (uint32) field_length; }
virtual void reset(void) { bzero(ptr,pack_length()); }
virtual void reset_fields() {}
+ virtual void set_default()
+ {
+ memcpy(ptr, ptr + table->rec_buff_length, pack_length());
+ if (null_ptr)
+ *null_ptr= ((*null_ptr & (uchar) ~null_bit) |
+ null_ptr[table->rec_buff_length] & null_bit);
+ }
virtual bool binary() const { return 1; }
virtual bool zero_pack() const { return 1; }
virtual enum ha_base_keytype key_type() const { return HA_KEYTYPE_BINARY; }
@@ -93,12 +100,13 @@ public:
virtual int key_cmp(const byte *str, uint length)
{ return cmp(ptr,(char*) str); }
virtual uint decimals() const { return 0; }
+ /*
+ Caller beware: sql_type can change str.Ptr, so check
+ ptr() to see if it changed if you are using your own buffer
+ in str and restore it with set() if needed
+ */
virtual void sql_type(String &str) const =0;
- // Caller beware: sql_type can change str.Ptr, so check
- // ptr() to see if it changed if you are using your own buffer
- // in str and restore it with set() if needed
-
- virtual uint size_of() const =0; // For new field
+ virtual uint size_of() const =0; // For new field
inline bool is_null(uint row_offset=0)
{ return null_ptr ? (null_ptr[row_offset] & null_bit ? 1 : 0) : table->null_row; }
inline bool is_real_null(uint row_offset=0)
@@ -185,7 +193,7 @@ public:
{ return cmp(a,b); }
virtual int pack_cmp(const char *b, uint key_length_arg)
{ return cmp(ptr,b); }
- uint offset(); // Should be inline ...
+ uint offset(); // Should be inline ...
void copy_from_tmp(int offset);
uint fill_cache_field(struct st_cache_field *copy);
virtual bool get_date(TIME *ltime,bool fuzzydate);
@@ -211,7 +219,7 @@ public:
class Field_num :public Field {
public:
const uint8 dec;
- bool zerofill,unsigned_flag; // Purify cannot handle bit fields
+ bool zerofill,unsigned_flag; // Purify cannot handle bit fields
Field_num(char *ptr_arg,uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg, utype unireg_check_arg,
const char *field_name_arg,
@@ -449,6 +457,7 @@ public:
void sort_string(char *buff,uint length);
uint32 pack_length() const { return 8; }
void sql_type(String &str) const;
+ bool store_for_compare() { return 1; }
};
#endif
@@ -561,6 +570,10 @@ public:
bool store_for_compare() { return 1; }
bool zero_pack() const { return 0; }
void set_time();
+ virtual void set_default()
+ {
+ set_time();
+ }
inline long get_timestamp()
{
#ifdef WORDS_BIGENDIAN
@@ -835,7 +848,7 @@ public:
class Field_blob :public Field_str {
uint packlength;
- String value; // For temporaries
+ String value; // For temporaries
bool binary_flag;
bool geom_flag;
public:
@@ -956,9 +969,9 @@ public:
:Field_str(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg, table_arg, default_charset_info),
packlength(packlength_arg),typelib(typelib_arg)
- {
+ {
flags|=ENUM_FLAG;
- }
+ }
enum_field_types type() const { return FIELD_TYPE_STRING; }
enum Item_result cmp_type () const { return INT_RESULT; }
enum ha_base_keytype key_type() const;
@@ -1008,25 +1021,24 @@ public:
/*
-** Create field class for CREATE TABLE
+ Create field class for CREATE TABLE
*/
class create_field :public Sql_alloc {
public:
const char *field_name;
- const char *change; // If done with alter table
- const char *after; // Put column after this one
- LEX_STRING comment; // Comment for field
- Item *def; // Default value
+ const char *change; // If done with alter table
+ const char *after; // Put column after this one
+ LEX_STRING comment; // Comment for field
+ Item *def; // Default value
enum enum_field_types sql_type;
uint32 length;
uint decimals,flags,pack_length;
Field::utype unireg_check;
- TYPELIB *interval; // Which interval to use
- Field *field; // For alter table
- CHARSET_INFO *charset;
+ TYPELIB *interval; // Which interval to use
+ Field *field; // For alter table
- uint8 row,col,sc_length,interval_id; // For rea_create_table
+ uint8 row,col,sc_length,interval_id; // For rea_create_table
uint offset,pack_flag;
create_field() :after(0) {}
create_field(Field *field, Field *orig_field);
@@ -1034,7 +1046,7 @@ public:
/*
-** A class for sending info to the client
+ A class for sending info to the client
*/
class Send_field {
@@ -1049,7 +1061,7 @@ class Send_field {
/*
-** A class for quick copying data to fields
+ A class for quick copying data to fields
*/
class Copy_field :public Sql_alloc {
@@ -1065,7 +1077,7 @@ public:
Copy_field() {}
~Copy_field() {}
- void set(Field *to,Field *from,bool save); // Field to field
+ void set(Field *to,Field *from,bool save); // Field to field
void set(char *to,Field *from); // Field to string
void (*do_copy)(Copy_field *);
void (*do_copy2)(Copy_field *); // Used to handle null values
@@ -1086,11 +1098,11 @@ ulonglong find_set(TYPELIB *typelib,const char *x, uint length);
bool test_if_int(const char *str,int length);
/*
-** The following are for the interface with the .frm file
+ The following are for the interface with the .frm file
*/
#define FIELDFLAG_DECIMAL 1
-#define FIELDFLAG_BINARY 1 // Shares same flag
+#define FIELDFLAG_BINARY 1 // Shares same flag
#define FIELDFLAG_NUMBER 2
#define FIELDFLAG_ZEROFILL 4
#define FIELDFLAG_PACK 120 // Bits used for packing
diff --git a/sql/filesort.cc b/sql/filesort.cc
index b7745ccb8ca..398ba4875d3 100644
--- a/sql/filesort.cc
+++ b/sql/filesort.cc
@@ -75,6 +75,8 @@ ha_rows filesort(TABLE *table, SORT_FIELD *sortorder, uint s_length,
uchar **sort_keys;
IO_CACHE tempfile, buffpek_pointers, *selected_records_file, *outfile;
SORTPARAM param;
+ THD *thd= current_thd;
+
DBUG_ENTER("filesort");
DBUG_EXECUTE("info",TEST_filesort(sortorder,s_length,special););
CHARSET_INFO *charset=table->table_charset;
@@ -143,7 +145,7 @@ ha_rows filesort(TABLE *table, SORT_FIELD *sortorder, uint s_length,
goto err;
#endif
- memavl=sortbuff_size;
+ memavl= thd->variables.sortbuff_size;
while (memavl >= MIN_SORT_MEMORY)
{
ulong old_memavl;
@@ -158,7 +160,8 @@ ha_rows filesort(TABLE *table, SORT_FIELD *sortorder, uint s_length,
}
if (memavl < MIN_SORT_MEMORY)
{
- my_error(ER_OUTOFMEMORY,MYF(ME_ERROR+ME_WAITTANG),sortbuff_size);
+ my_error(ER_OUTOFMEMORY,MYF(ME_ERROR+ME_WAITTANG),
+ thd->variables.sortbuff_size);
goto err;
}
if (open_cached_file(&buffpek_pointers,mysql_tmpdir,TEMP_PREFIX,
@@ -324,7 +327,8 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
file->extra(HA_EXTRA_KEYREAD); // QQ is removed
next_pos=(byte*) 0; /* Find records in sequence */
file->rnd_init();
- file->extra(HA_EXTRA_CACHE); /* Quicker reads */
+ file->extra_opt(HA_EXTRA_CACHE,
+ current_thd->variables.read_buff_size);
}
for (;;)
@@ -917,6 +921,7 @@ static uint
sortlength(SORT_FIELD *sortorder, uint s_length)
{
reg2 uint length;
+ THD *thd= current_thd;
length=0;
for (; s_length-- ; sortorder++)
@@ -924,7 +929,7 @@ sortlength(SORT_FIELD *sortorder, uint s_length)
if (sortorder->field)
{
if (sortorder->field->type() == FIELD_TYPE_BLOB)
- sortorder->length=max_item_sort_length;
+ sortorder->length= thd->variables.max_sort_length;
else
{
sortorder->length=sortorder->field->pack_length();
@@ -971,7 +976,7 @@ sortlength(SORT_FIELD *sortorder, uint s_length)
if (sortorder->item->maybe_null)
length++; // Place for NULL marker
}
- set_if_smaller(sortorder->length,max_item_sort_length);
+ set_if_smaller(sortorder->length, thd->variables.max_sort_length);
length+=sortorder->length;
}
sortorder->field= (Field*) 0; // end marker
diff --git a/sql/gen_lex_hash.cc b/sql/gen_lex_hash.cc
index 6cec0b160b7..4da5496c201 100644
--- a/sql/gen_lex_hash.cc
+++ b/sql/gen_lex_hash.cc
@@ -73,15 +73,6 @@ static struct my_option my_long_options[] =
0, 0, 0},
{"version", 'V', "Output version information and exit",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"rnd1", 'r', "Set 1 part of rnd value for hash generator",
- (gptr*) &best_t1, (gptr*) &best_t1, 0, GET_ULONG, REQUIRED_ARG, 6657025L,
- 0, 0, 0, 0, 0},
- {"rnd2", 'R', "Set 2 part of rnd value for hash generator",
- (gptr*) &best_t2, (gptr*) &best_t2, 0, GET_ULONG, REQUIRED_ARG, 6114496L,
- 0, 0, 0, 0, 0},
- {"type", 't', "Set type of char table to generate",
- (gptr*) &best_type, (gptr*) &best_type, 0, GET_UINT, REQUIRED_ARG, 1, 0, 0,
- 0, 0, 0},
{ 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};
@@ -373,7 +364,7 @@ static my_bool
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
char *argument __attribute__((unused)))
{
- switch(optid) {
+ switch (optid) {
case 'v':
opt_verbose++;
break;
@@ -398,8 +389,9 @@ static int get_options(int argc, char **argv)
if (argc >= 1)
{
+ fprintf(stderr,"%s: Too many arguments\n", my_progname);
usage(0);
- exit(1);
+ exit(1);
}
return(0);
}
@@ -477,8 +469,7 @@ int main(int argc,char **argv)
int error;
MY_INIT(argv[0]);
-
- start_value=1109118L; /* mode=4903 add=3 type: 0 */
+ start_value=2925024L; best_t1=654916L; best_t2=1723390L; best_type=3; /* mode=4943 add=1 type: 0 */
if (get_options(argc,(char **) argv))
exit(1);
diff --git a/sql/ha_berkeley.cc b/sql/ha_berkeley.cc
index 58a090a8aed..131e38a6bc3 100644
--- a/sql/ha_berkeley.cc
+++ b/sql/ha_berkeley.cc
@@ -358,7 +358,7 @@ berkeley_cmp_packed_key(DB *file, const DBT *new_key, const DBT *saved_key)
KEY_PART_INFO *key_part= key->key_part, *end=key_part+key->key_parts;
uint key_length=new_key->size;
- for ( ; key_part != end && (int) key_length > 0; key_part++)
+ for (; key_part != end && (int) key_length > 0; key_part++)
{
int cmp;
if (key_part->null_bit)
@@ -396,7 +396,7 @@ berkeley_cmp_fix_length_key(DB *file, const DBT *new_key, const DBT *saved_key)
KEY_PART_INFO *key_part= key->key_part, *end=key_part+key->key_parts;
uint key_length=new_key->size;
- for ( ; key_part != end && (int) key_length > 0 ; key_part++)
+ for (; key_part != end && (int) key_length > 0 ; key_part++)
{
int cmp;
if ((cmp=key_part->field->pack_cmp(new_key_ptr,saved_key_ptr,0)))
@@ -417,7 +417,7 @@ berkeley_key_cmp(TABLE *table, KEY *key_info, const char *key, uint key_length)
KEY_PART_INFO *key_part= key_info->key_part,
*end=key_part+key_info->key_parts;
- for ( ; key_part != end && (int) key_length > 0; key_part++)
+ for (; key_part != end && (int) key_length > 0; key_part++)
{
int cmp;
if (key_part->null_bit)
@@ -561,7 +561,7 @@ int ha_berkeley::open(const char *name, int mode, uint test_if_locked)
ref_length=0;
KEY_PART_INFO *key_part= table->key_info[primary_key].key_part;
KEY_PART_INFO *end=key_part+table->key_info[primary_key].key_parts;
- for ( ; key_part != end ; key_part++)
+ for (; key_part != end ; key_part++)
ref_length+= key_part->field->max_packed_col_length(key_part->length);
share->fixed_length_primary_key=
(ref_length == table->key_info[primary_key].key_length);
@@ -701,7 +701,7 @@ void ha_berkeley::unpack_key(char *record, DBT *key, uint index)
*end=key_part+key_info->key_parts;
char *pos=(char*) key->data;
- for ( ; key_part != end; key_part++)
+ for (; key_part != end; key_part++)
{
if (key_part->null_bit)
{
@@ -747,7 +747,7 @@ DBT *ha_berkeley::create_key(DBT *key, uint keynr, char *buff,
key->data=buff;
key->app_private= key_info;
- for ( ; key_part != end && key_length > 0; key_part++)
+ for (; key_part != end && key_length > 0; key_part++)
{
if (key_part->null_bit)
{
@@ -925,7 +925,7 @@ int ha_berkeley::key_cmp(uint keynr, const byte * old_row,
KEY_PART_INFO *key_part=table->key_info[keynr].key_part;
KEY_PART_INFO *end=key_part+table->key_info[keynr].key_parts;
- for ( ; key_part != end ; key_part++)
+ for (; key_part != end ; key_part++)
{
if (key_part->null_bit)
{
@@ -1584,7 +1584,7 @@ DBT *ha_berkeley::get_pos(DBT *to, byte *pos)
KEY_PART_INFO *key_part=table->key_info[primary_key].key_part;
KEY_PART_INFO *end=key_part+table->key_info[primary_key].key_parts;
- for ( ; key_part != end ; key_part++)
+ for (; key_part != end ; key_part++)
pos+=key_part->field->packed_col_length((char*) pos,key_part->length);
to->size= (uint) (pos- (byte*) to->data);
}
@@ -1701,7 +1701,7 @@ int ha_berkeley::external_lock(THD *thd, int lock_type)
DBUG_ASSERT(thd->transaction.stmt.bdb_tid == 0);
transaction=0; // Safety
/* First table lock, start transaction */
- if ((thd->options & (OPTION_NOT_AUTO_COMMIT | OPTION_BEGIN |
+ if ((thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN |
OPTION_TABLE_LOCK)) &&
!thd->transaction.all.bdb_tid)
{
diff --git a/sql/ha_berkeley.h b/sql/ha_berkeley.h
index f56ee5ef1a9..198664d0c06 100644
--- a/sql/ha_berkeley.h
+++ b/sql/ha_berkeley.h
@@ -88,8 +88,7 @@ class ha_berkeley: public handler
ha_berkeley(TABLE *table): handler(table), alloc_ptr(0),rec_buff(0), file(0),
int_table_flags(HA_REC_NOT_IN_SEQ |
HA_KEYPOS_TO_RNDPOS | HA_LASTKEY_ORDER |
- HA_NULL_KEY | HA_HAVE_KEY_READ_ONLY |
- HA_BLOB_KEY | HA_NOT_EXACT_COUNT |
+ HA_NULL_KEY | HA_BLOB_KEY | HA_NOT_EXACT_COUNT |
HA_PRIMARY_KEY_IN_READ_INDEX | HA_DROP_BEFORE_CREATE |
HA_AUTO_PART_KEY | HA_TABLE_SCAN_ON_INDEX),
changed_rows(0),last_dup_key((uint) -1),version(0),using_ignore(0)
@@ -168,7 +167,6 @@ class ha_berkeley: public handler
};
extern bool berkeley_skip, berkeley_shared_data;
-extern SHOW_COMP_OPTION have_berkeley_db;
extern u_int32_t berkeley_init_flags,berkeley_env_flags, berkeley_lock_type,
berkeley_lock_types[];
extern ulong berkeley_cache_size, berkeley_max_lock, berkeley_log_buffer_size;
diff --git a/sql/ha_heap.cc b/sql/ha_heap.cc
index f56bfe74265..271f00428a5 100644
--- a/sql/ha_heap.cc
+++ b/sql/ha_heap.cc
@@ -220,7 +220,8 @@ ha_rows ha_heap::records_in_range(int inx,
if (pos->algorithm == HA_KEY_ALG_BTREE)
{
return hp_rb_records_in_range(file, inx, start_key, start_key_len,
- start_search_flag, end_key, end_key_len, end_search_flag);
+ start_search_flag, end_key, end_key_len,
+ end_search_flag);
}
else
{
@@ -233,7 +234,9 @@ ha_rows ha_heap::records_in_range(int inx,
}
}
-int ha_heap::create(const char *name, TABLE *table, HA_CREATE_INFO *create_info)
+
+int ha_heap::create(const char *name, TABLE *table,
+ HA_CREATE_INFO *create_info)
{
uint key, parts, mem_per_row= 0;
ulong max_rows;
@@ -250,7 +253,8 @@ int ha_heap::create(const char *name, TABLE *table, HA_CREATE_INFO *create_info)
}
if (!(keydef= (HP_KEYDEF*) my_malloc(table->keys * sizeof(HP_KEYDEF) +
- parts * sizeof(HA_KEYSEG), MYF(MY_WME))))
+ parts * sizeof(HA_KEYSEG),
+ MYF(MY_WME))))
return my_errno;
seg= my_reinterpret_cast(HA_KEYSEG*) (keydef + table->keys);
for (key= 0; key < table->keys; key++)
@@ -264,17 +268,15 @@ int ha_heap::create(const char *name, TABLE *table, HA_CREATE_INFO *create_info)
keydef[key].keysegs= (uint) pos->key_parts;
keydef[key].flag= (pos->flags & (HA_NOSAME | HA_NULL_ARE_EQUAL));
keydef[key].seg= seg;
- keydef[key].algorithm= pos->algorithm == HA_KEY_ALG_UNDEF ?
- HA_KEY_ALG_HASH : pos->algorithm;
+ keydef[key].algorithm= ((pos->algorithm == HA_KEY_ALG_UNDEF) ?
+ HA_KEY_ALG_HASH : pos->algorithm);
for (; key_part != key_part_end; key_part++, seg++)
{
uint flag= key_part->key_type;
Field *field= key_part->field;
if (pos->algorithm == HA_KEY_ALG_BTREE)
- {
seg->type= field->key_type();
- }
else
{
if (!f_is_packed(flag) &&
@@ -310,7 +312,8 @@ int ha_heap::create(const char *name, TABLE *table, HA_CREATE_INFO *create_info)
}
}
mem_per_row+= MY_ALIGN(table->reclength + 1, sizeof(char*));
- max_rows= (ulong) (max_heap_table_size / mem_per_row);
+ max_rows = (ulong) (current_thd->variables.max_heap_table_size /
+ mem_per_row);
error= heap_create(fn_format(buff,name,"","",4+2),
table->keys,keydef, table->reclength,
((table->max_rows < max_rows && table->max_rows) ?
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index 455d890758f..d42311b43b6 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 MySQL AB & InnoDB Oy
+/* Copyright (C) 2000 MySQL AB & Innobase Oy
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -19,7 +19,7 @@
/* TODO list for the InnoDB handler:
- Ask Monty if strings of different languages can exist in the same
- database. Answer: in near future yes, but not yet.
+ database. Answer: in 4.1 yes.
*/
#ifdef __GNUC__
@@ -27,6 +27,7 @@
#endif
#include "mysql_priv.h"
+#include "slave.h"
#ifdef HAVE_INNOBASE_DB
#include <m_ctype.h>
#include <assert.h>
@@ -53,10 +54,13 @@ typedef byte mysql_byte;
/* Include necessary InnoDB headers */
extern "C" {
#include "../innobase/include/univ.i"
+#include "../innobase/include/os0file.h"
+#include "../innobase/include/os0thread.h"
#include "../innobase/include/srv0start.h"
#include "../innobase/include/srv0srv.h"
#include "../innobase/include/trx0roll.h"
#include "../innobase/include/trx0trx.h"
+#include "../innobase/include/trx0sys.h"
#include "../innobase/include/row0ins.h"
#include "../innobase/include/row0mysql.h"
#include "../innobase/include/row0sel.h"
@@ -107,8 +111,6 @@ my_bool innobase_fast_shutdown = TRUE;
specify any startup options.
*/
-/* innobase_data_file_path=ibdata:15,idata2:1,... */
-
char *innobase_data_file_path= (char*) "ibdata1:10M:autoextend";
static char *internal_innobase_data_file_path=0;
@@ -135,8 +137,9 @@ static void innobase_print_error(const char* db_errpfx, char* buffer);
/* General functions */
/**********************************************************************
-Releases possible search latch, auto inc lock, and InnoDB thread FIFO ticket.
-These should be released at each SQL statement end. */
+Releases possible search latch and InnoDB thread FIFO ticket. These should
+be released at each SQL statement end. It does no harm to release these
+also in the middle of an SQL statement. */
static
void
innobase_release_stat_resources(
@@ -147,16 +150,6 @@ innobase_release_stat_resources(
trx_search_latch_release_if_reserved(trx);
}
- if (trx->auto_inc_lock) {
-
- /* If we had reserved the auto-inc lock for
- some table in this SQL statement, we release it now */
-
- srv_conc_enter_innodb(trx);
- row_unlock_table_autoinc_for_mysql(trx);
- srv_conc_exit_innodb(trx);
- }
-
if (trx->declared_to_be_inside_innodb) {
/* Release our possible ticket in the FIFO */
@@ -188,7 +181,8 @@ int
convert_error_code_to_mysql(
/*========================*/
/* out: MySQL error code */
- int error) /* in: InnoDB error code */
+ int error, /* in: InnoDB error code */
+ THD* thd) /* in: user thread handle or NULL */
{
if (error == DB_SUCCESS) {
@@ -207,11 +201,27 @@ convert_error_code_to_mysql(
return(HA_ERR_NO_ACTIVE_RECORD);
} else if (error == (int) DB_DEADLOCK) {
+ /* Since we roll back the whole transaction, we must
+ tell it also to MySQL so that MySQL knows to empty the
+ cached binlog for this transaction */
+
+ if (thd) {
+ ha_rollback(thd);
+ }
return(HA_ERR_LOCK_DEADLOCK);
} else if (error == (int) DB_LOCK_WAIT_TIMEOUT) {
+ /* Since we roll back the whole transaction, we must
+ tell it also to MySQL so that MySQL knows to empty the
+ cached binlog for this transaction */
+
+
+ if (thd) {
+ ha_rollback(thd);
+ }
+
return(HA_ERR_LOCK_WAIT_TIMEOUT);
} else if (error == (int) DB_NO_REFERENCED_ROW) {
@@ -242,8 +252,6 @@ convert_error_code_to_mysql(
return(HA_ERR_TO_BIG_ROW);
} else {
- DBUG_ASSERT(0);
-
return(-1); // Unknown error
}
}
@@ -251,41 +259,66 @@ convert_error_code_to_mysql(
extern "C" {
/*****************************************************************
Prints info of a THD object (== user session thread) to the
-standard output. NOTE that mysql/innobase/trx/trx0trx.c must contain
+standard output. NOTE that /mysql/innobase/trx/trx0trx.c must contain
the prototype for this function! */
void
innobase_mysql_print_thd(
/*=====================*/
- void* input_thd)/* in: pointer to a MySQL THD object */
+ char* buf, /* in/out: buffer where to print, must be at least
+ 400 bytes */
+ void* input_thd)/* in: pointer to a MySQL THD object */
{
- THD* thd;
+ THD* thd;
+ char* old_buf = buf;
+
+ thd = (THD*) input_thd;
- thd = (THD*) input_thd;
+ /* We cannot use the return value of normal sprintf() as this is
+ not portable to some old non-Posix Unixes, e.g., some old SCO
+ Unixes */
- printf("MySQL thread id %lu, query id %lu",
- thd->thread_id, thd->query_id);
+ buf += my_sprintf(buf,
+ (buf, "MySQL thread id %lu, query id %lu",
+ thd->thread_id, thd->query_id));
if (thd->host) {
- printf(" %s", thd->host);
+ *buf = ' ';
+ buf++;
+ buf = strnmov(buf, thd->host, 30);
}
if (thd->ip) {
- printf(" %s", thd->ip);
+ *buf = ' ';
+ buf++;
+ buf=strnmov(buf, thd->ip, 20);
}
if (thd->user) {
- printf(" %s", thd->user);
+ *buf = ' ';
+ buf++;
+ buf=strnmov(buf, thd->user, 20);
}
if (thd->proc_info) {
- printf(" %s", thd->proc_info);
+ *buf = ' ';
+ buf++;
+ buf=strnmov(buf, thd->proc_info, 50);
}
if (thd->query) {
- printf("\n%-.100s", thd->query);
+ *buf = '\n';
+ buf++;
+ buf=strnmov(buf, thd->query, 150);
}
- printf("\n");
+ buf[0] = '\n';
+ buf[1] = '\0'; /* Note that we must put a null character here to end
+ the printed string */
+
+ /* We test the printed length did not overrun the buffer length of
+ 400 bytes */
+
+ ut_a(strlen(old_buf) < 400);
}
}
@@ -302,6 +335,8 @@ check_trx_exists(
{
trx_t* trx;
+ ut_a(thd == current_thd);
+
trx = (trx_t*) thd->transaction.all.innobase_tid;
if (trx == NULL) {
@@ -321,7 +356,23 @@ check_trx_exists(
thd->transaction.stmt.innobase_tid =
(void*)&innodb_dummy_stmt_trx_handle;
} else {
- ut_a(trx->magic_n == TRX_MAGIC_N);
+ if (trx->magic_n != TRX_MAGIC_N) {
+ mem_analyze_corruption((byte*)trx);
+
+ ut_a(0);
+ }
+ }
+
+ if (thd->options & OPTION_NO_FOREIGN_KEY_CHECKS) {
+ trx->check_foreigns = FALSE;
+ } else {
+ trx->check_foreigns = TRUE;
+ }
+
+ if (thd->options & OPTION_RELAXED_UNIQUE_CHECKS) {
+ trx->check_unique_secondary = FALSE;
+ } else {
+ trx->check_unique_secondary = TRUE;
}
return(trx);
@@ -340,7 +391,7 @@ ha_innobase::update_thd(
{
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
trx_t* trx;
-
+
trx = check_trx_exists(thd);
if (prebuilt->trx != trx) {
@@ -353,6 +404,61 @@ ha_innobase::update_thd(
return(0);
}
+/* The code here appears for documentational purposes only. Not used
+or tested yet. Will be used in 4.1. */
+/*********************************************************************
+Call this when you have opened a new table handle in HANDLER, before you
+call index_read_idx() etc. Actually, we can let the cursor stay open even
+over a transaction commit! Then you should call this before every operation,
+fecth next etc. This function inits the necessary things even after a
+transaction commit. */
+
+void
+ha_innobase::init_table_handle_for_HANDLER(void)
+/*============================================*/
+{
+ row_prebuilt_t* prebuilt;
+
+ /* If current thd does not yet have a trx struct, create one.
+ If the current handle does not yet have a prebuilt struct, create
+ one. Update the trx pointers in the prebuilt struct. Normally
+ this operation is done in external_lock. */
+
+ update_thd(current_thd);
+
+ /* Initialize the prebuilt struct much like it would be inited in
+ external_lock */
+
+ prebuilt = (row_prebuilt_t*)innobase_prebuilt;
+
+ /* If the transaction is not started yet, start it */
+
+ trx_start_if_not_started_noninline(prebuilt->trx);
+
+ /* Assign a read view if the transaction does not have it yet */
+
+ trx_assign_read_view(prebuilt->trx);
+
+ /* We did the necessary inits in this function, no need to repeat them
+ in row_search_for_mysql */
+
+ prebuilt->sql_stat_start = FALSE;
+
+ /* We let HANDLER always to do the reads as consistent reads, even
+ if the trx isolation level would have been specified as SERIALIZABLE */
+
+ prebuilt->select_lock_type = LOCK_NONE;
+
+ /* Always fetch all columns in the index record */
+
+ prebuilt->hint_no_need_to_fetch_extra_cols = FALSE;
+
+ /* We want always to fetch all columns in the whole row? Or do
+ we???? */
+
+ prebuilt->read_just_key = FALSE;
+}
+
/*************************************************************************
Opens an InnoDB database. */
@@ -361,12 +467,15 @@ innobase_init(void)
/*===============*/
/* out: TRUE if error */
{
+ static char current_dir[3]; // Set if using current lib
int err;
bool ret;
- char current_lib[3], *default_path;
+ char *default_path;
DBUG_ENTER("innobase_init");
+ os_innodb_umask = (ulint)my_umask;
+
/*
When using the embedded server, the datadirectory is not
in the current directory.
@@ -376,10 +485,10 @@ innobase_init(void)
else
{
/* It's better to use current lib, to keep path's short */
- current_lib[0] = FN_CURLIB;
- current_lib[1] = FN_LIBCHAR;
- current_lib[2] = 0;
- default_path=current_lib;
+ current_dir[0] = FN_CURLIB;
+ current_dir[1] = FN_LIBCHAR;
+ current_dir[2] = 0;
+ default_path=current_dir;
}
if (specialflag & SPECIAL_NO_PRIOR) {
@@ -440,11 +549,12 @@ innobase_init(void)
srv_log_archive_on = (ulint) innobase_log_archive;
srv_log_buffer_size = (ulint) innobase_log_buffer_size;
- srv_flush_log_at_trx_commit = (ibool) innobase_flush_log_at_trx_commit;
+ 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;
srv_n_file_io_threads = (ulint) innobase_file_io_threads;
@@ -475,6 +585,22 @@ innobase_init(void)
(void) hash_init(&innobase_open_tables,system_charset_info,32,0,0,
(hash_get_key) innobase_get_key,0,0);
pthread_mutex_init(&innobase_mutex,MY_MUTEX_INIT_FAST);
+
+ /* If this is a replication slave and we needed to do a crash recovery,
+ set the master binlog position to what InnoDB internally knew about
+ how far we got transactions durable inside InnoDB. There is a
+ problem here: if the user used also MyISAM tables, InnoDB might not
+ know the right position for them.
+
+ THIS DOES NOT WORK CURRENTLY because replication seems to initialize
+ glob_mi also after innobase_init. */
+
+/* if (trx_sys_mysql_master_log_pos != -1) {
+ ut_memcpy(glob_mi.log_file_name, trx_sys_mysql_master_log_name,
+ 1 + ut_strlen(trx_sys_mysql_master_log_name));
+ glob_mi.pos = trx_sys_mysql_master_log_pos;
+ }
+*/
DBUG_RETURN(0);
}
@@ -534,6 +660,30 @@ innobase_get_free_space(void)
/*********************************************************************
Commits a transaction in an InnoDB database. */
+void
+innobase_commit_low(
+/*================*/
+ trx_t* trx) /* in: transaction handle */
+{
+ if (current_thd->slave_thread)
+ {
+ /* Update the replication position info inside InnoDB */
+#ifdef NEED_TO_BE_FIXED
+ trx->mysql_relay_log_file_name= active_mi->rli.log_file_name;
+ trx->mysql_relay_log_pos= active_mi->rli.relay_log_pos;
+#endif
+ trx->mysql_master_log_file_name= active_mi->rli.master_log_name;
+ trx->mysql_master_log_pos= ((ib_longlong)
+ (active_mi->rli.master_log_pos +
+ active_mi->rli.event_len +
+ active_mi->rli.pending));
+ }
+ trx_commit_for_mysql(trx);
+}
+
+/*********************************************************************
+Commits a transaction in an InnoDB database. */
+
int
innobase_commit(
/*============*/
@@ -552,9 +702,18 @@ innobase_commit(
trx = check_trx_exists(thd);
- if (trx_handle != (void*)&innodb_dummy_stmt_trx_handle) {
+ if (trx->auto_inc_lock) {
+
+ /* If we had reserved the auto-inc lock for
+ some table in this SQL statement, we release it now */
+
+ srv_conc_enter_innodb(trx);
+ row_unlock_table_autoinc_for_mysql(trx);
+ srv_conc_exit_innodb(trx);
+ }
- trx_commit_for_mysql(trx);
+ if (trx_handle != (void*)&innodb_dummy_stmt_trx_handle) {
+ innobase_commit_low(trx);
}
/* Release possible statement level resources */
@@ -594,6 +753,8 @@ innobase_report_binlog_offset_and_commit(
trx = (trx_t*)trx_handle;
+ ut_a(trx != NULL);
+
trx->mysql_log_file_name = log_file_name;
trx->mysql_log_offset = (ib_longlong)end_offset;
@@ -619,6 +780,16 @@ innobase_rollback(
trx = check_trx_exists(thd);
+ if (trx->auto_inc_lock) {
+
+ /* If we had reserved the auto-inc lock for
+ some table in this SQL statement, we release it now */
+
+ srv_conc_enter_innodb(trx);
+ row_unlock_table_autoinc_for_mysql(trx);
+ srv_conc_exit_innodb(trx);
+ }
+
srv_conc_enter_innodb(trx);
if (trx_handle != (void*)&innodb_dummy_stmt_trx_handle) {
@@ -634,7 +805,7 @@ innobase_rollback(
trx_mark_sql_stat_end(trx);
- DBUG_RETURN(convert_error_code_to_mysql(error));
+ DBUG_RETURN(convert_error_code_to_mysql(error, NULL));
}
/*********************************************************************
@@ -747,7 +918,7 @@ normalize_table_name(
}
/*********************************************************************
-Creates and opens a handle to a table which already exists in an Innobase
+Creates and opens a handle to a table which already exists in an InnoDB
database. */
int
@@ -796,7 +967,6 @@ 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\
@@ -819,13 +989,13 @@ have moved .frm files to another database?",
primary_key = MAX_KEY;
- if (!row_table_got_default_clust_index(ib_table)) {
+ /* Allocate a buffer for a 'row reference'. A row reference is
+ a string of bytes of length ref_length which uniquely specifies
+ a row in our table. Note that MySQL may also compare two row
+ references for equality by doing a simple memcmp on the strings
+ of length ref_length! */
- /* If we automatically created the clustered index,
- then MySQL does not know about it and it must not be aware
- of the index used on scan, to avoid checking if we update
- the column of the index. The column is the row id in
- the automatical case, and it will not be updated. */
+ if (!row_table_got_default_clust_index(ib_table)) {
((row_prebuilt_t*)innobase_prebuilt)
->clust_index_was_generated = FALSE;
@@ -834,13 +1004,13 @@ have moved .frm files to another database?",
key_used_on_scan = 0;
/*
- MySQL allocates the buffer for ref.
- This includes all keys + one byte for each column
- that may be NULL.
- The ref_length must be exact as possible as
- all reference buffers are allocated based on this.
+ MySQL allocates the buffer for ref. key_info->key_length
+ includes space for all key columns + one byte for each column
+ that may be NULL. ref_length must be as exact as possible to
+ save space, because all row reference buffers are allocated
+ based on ref_length.
*/
-
+
ref_length = table->key_info->key_length;
} else {
((row_prebuilt_t*)innobase_prebuilt)
@@ -848,11 +1018,23 @@ have moved .frm files to another database?",
ref_length = DATA_ROW_ID_LEN;
+ /*
+ If we automatically created the clustered index, then
+ MySQL does not know about it, and MySQL must NOT be aware
+ of the index used on scan, to make it avoid checking if we
+ update the column of the index. That is why we assert below
+ that key_used_on_scan is the undefined value MAX_KEY.
+ The column is the row id in the automatical generation case,
+ and it will never be updated anyway.
+ */
DBUG_ASSERT(key_used_on_scan == MAX_KEY);
}
auto_inc_counter_for_this_stat = 0;
+ block_size = 16 * 1024; /* Index block size in InnoDB: used by MySQL
+ in query optimization */
+
/* Init table lock structure */
thr_lock_data_init(&share->lock,&lock,(void*) 0);
@@ -1094,7 +1276,8 @@ get_innobase_type_from_mysql_type(
}
/***********************************************************************
-Stores a key value for a row to a buffer. */
+Stores a key value for a row to a buffer. This must currently only be used
+to store a row reference to the 'ref' buffer of this table handle! */
uint
ha_innobase::store_key_val_for_row(
@@ -1102,7 +1285,8 @@ ha_innobase::store_key_val_for_row(
/* out: key value length as stored in buff */
uint keynr, /* in: key number */
char* buff, /* in/out: buffer for the key value (in MySQL
- format) */
+ format); currently this MUST be the 'ref'
+ buffer! */
const mysql_byte* record)/* in: row in MySQL format */
{
KEY* key_info = table->key_info + keynr;
@@ -1131,11 +1315,12 @@ ha_innobase::store_key_val_for_row(
}
/*
- We have to zero-fill the buffer to be able to compare two
- keys to see if they are equal
+ We have to zero-fill the 'ref' buffer so that MySQL is able to
+ use a simple memcmp to compare two key values to determine if they
+ are equal
*/
bzero(buff, (ref_length- (uint) (buff - buff_start)));
- return ref_length;
+ DBUG_RETURN(ref_length);
}
/******************************************************************
@@ -1310,9 +1495,13 @@ ha_innobase::write_row(
row_prebuilt_t* prebuilt = (row_prebuilt_t*)innobase_prebuilt;
int error;
longlong auto_inc;
+ longlong dummy;
DBUG_ENTER("ha_innobase::write_row");
+ ut_a(prebuilt->trx ==
+ (trx_t*) current_thd->transaction.all.innobase_tid);
+
statistic_increment(ha_write_count, &LOCK_status);
if (table->time_stamp) {
@@ -1329,7 +1518,31 @@ ha_innobase::write_row(
if (table->next_number_field && record == table->record[0]) {
/* This is the case where the table has an
auto-increment column */
-
+
+ /* Initialize the auto-inc counter if it has not been
+ initialized yet */
+
+ if (0 == dict_table_autoinc_peek(prebuilt->table)) {
+
+ /* This call initializes the counter */
+ error = innobase_read_and_init_auto_inc(&dummy);
+
+ if (error) {
+ /* Deadlock or lock wait timeout */
+
+ goto func_exit;
+ }
+
+ /* We have to set sql_stat_start to TRUE because
+ the above call probably has called a select, and
+ has reset that flag; row_insert_for_mysql has to
+ know to set the IX intention lock on the table,
+ something it only does at the start of each
+ statement */
+
+ prebuilt->sql_stat_start = TRUE;
+ }
+
/* Fetch the value the user possibly has set in the
autoincrement field */
@@ -1362,10 +1575,9 @@ ha_innobase::write_row(
}
if (auto_inc != 0) {
- /* This call will calculate the max of the
- current value and the value supplied by the user, if
- the auto_inc counter is already initialized
- for the table */
+ /* This call will calculate the max of the current
+ value and the value supplied by the user and
+ update the counter accordingly */
/* We have to use the transactional lock mechanism
on the auto-inc counter of the table to ensure
@@ -1380,7 +1592,8 @@ ha_innobase::write_row(
if (error != DB_SUCCESS) {
- error = convert_error_code_to_mysql(error);
+ error = convert_error_code_to_mysql(error,
+ user_thd);
goto func_exit;
}
@@ -1396,7 +1609,7 @@ ha_innobase::write_row(
srv_conc_exit_innodb(prebuilt->trx);
error = convert_error_code_to_mysql(
- error);
+ error, user_thd);
goto func_exit;
}
}
@@ -1404,45 +1617,18 @@ ha_innobase::write_row(
auto_inc = dict_table_autoinc_get(prebuilt->table);
srv_conc_exit_innodb(prebuilt->trx);
- /* If auto_inc is now != 0 the autoinc counter
- was already initialized for the table: we can give
- the new value for MySQL to place in the field */
+ /* We can give the new value for MySQL to place in
+ the field */
- if (auto_inc != 0) {
- user_thd->next_insert_id = auto_inc;
- }
- }
-
- update_auto_increment();
-
- if (auto_inc == 0) {
- /* The autoinc counter for our table was not yet
- initialized, initialize it now */
-
- auto_inc = table->next_number_field->val_int();
-
- srv_conc_enter_innodb(prebuilt->trx);
- error = row_lock_table_autoinc_for_mysql(prebuilt);
- srv_conc_exit_innodb(prebuilt->trx);
-
- if (error != DB_SUCCESS) {
-
- error = convert_error_code_to_mysql(error);
- goto func_exit;
- }
-
- dict_table_autoinc_initialize(prebuilt->table,
- auto_inc);
+ user_thd->next_insert_id = auto_inc;
}
- /* We have to set sql_stat_start to TRUE because
- update_auto_increment may have called a select, and
- has reset that flag; row_insert_for_mysql has to
- know to set the IX intention lock on the table, something
- it only does at the start of each statement */
+ /* This call of a handler.cc function places
+ user_thd->next_insert_id to the column value, if the column
+ value was not set by the user */
- prebuilt->sql_stat_start = TRUE;
- }
+ update_auto_increment();
+ }
if (prebuilt->mysql_template == NULL
|| prebuilt->template_type != ROW_MYSQL_WHOLE_ROW) {
@@ -1467,7 +1653,7 @@ ha_innobase::write_row(
prebuilt->trx->ignore_duplicates_in_insert = FALSE;
- error = convert_error_code_to_mysql(error);
+ error = convert_error_code_to_mysql(error, user_thd);
/* Tell InnoDB server that there might be work for
utility threads: */
@@ -1651,6 +1837,9 @@ ha_innobase::update_row(
DBUG_ENTER("ha_innobase::update_row");
+ ut_a(prebuilt->trx ==
+ (trx_t*) current_thd->transaction.all.innobase_tid);
+
if (table->time_stamp) {
update_timestamp(new_row + table->time_stamp - 1);
}
@@ -1684,7 +1873,7 @@ ha_innobase::update_row(
srv_conc_exit_innodb(prebuilt->trx);
- error = convert_error_code_to_mysql(error);
+ error = convert_error_code_to_mysql(error, user_thd);
/* Tell InnoDB server that there might be work for
utility threads: */
@@ -1708,6 +1897,9 @@ ha_innobase::delete_row(
DBUG_ENTER("ha_innobase::delete_row");
+ ut_a(prebuilt->trx ==
+ (trx_t*) current_thd->transaction.all.innobase_tid);
+
if (last_query_id != user_thd->query_id) {
prebuilt->sql_stat_start = TRUE;
last_query_id = user_thd->query_id;
@@ -1729,7 +1921,7 @@ ha_innobase::delete_row(
srv_conc_exit_innodb(prebuilt->trx);
- error = convert_error_code_to_mysql(error);
+ error = convert_error_code_to_mysql(error, user_thd);
/* Tell the InnoDB server that there might be work for
utility threads: */
@@ -1796,6 +1988,55 @@ convert_search_mode_to_innobase(
return(0);
}
+/*
+ BACKGROUND INFO: HOW A SELECT SQL QUERY IS EXECUTED
+ ---------------------------------------------------
+The following does not cover all the details, but explains how we determine
+the start of a new SQL statement, and what is associated with it.
+
+For each table in the database the MySQL interpreter may have several
+table handle instances in use, also in a single SQL query. For each table
+handle instance there is an InnoDB 'prebuilt' struct which contains most
+of the InnoDB data associated with this table handle instance.
+
+ A) if the user has not explicitly set any MySQL table level locks:
+
+ 1) MySQL calls ::external_lock to set an 'intention' table level lock on
+the table of the handle instance. There we set
+prebuilt->sql_stat_start = TRUE. The flag sql_stat_start should be set
+true if we are taking this table handle instance to use in a new SQL
+statement issued by the user. We also increment trx->n_mysql_tables_in_use.
+
+ 2) If prebuilt->sql_stat_start == TRUE we 'pre-compile' the MySQL search
+instructions to prebuilt->template of the table handle instance in
+::index_read. The template is used to save CPU time in large joins.
+
+ 3) In row_search_for_mysql, if prebuilt->sql_stat_start is true, we
+allocate a new consistent read view for the trx if it does not yet have one,
+or in the case of a locking read, set an InnoDB 'intention' table level
+lock on the table.
+
+ 4) We do the SELECT. MySQL may repeatedly call ::index_read for the
+same table handle instance, if it is a join.
+
+ 5) When the SELECT ends, MySQL removes its intention table level locks
+in ::external_lock. When trx->n_mysql_tables_in_use drops to zero,
+ (a) we execute a COMMIT there if the autocommit is on,
+ (b) we also release possible 'SQL statement level resources' InnoDB may
+have for this SQL statement. The MySQL interpreter does NOT execute
+autocommit for pure read transactions, though it should. That is why the
+table handler in that case has to execute the COMMIT in ::external_lock.
+
+ B) If the user has explicitly set MySQL table level locks, then MySQL
+does NOT call ::external_lock at the start of the statement. To determine
+when we are at the start of a new SQL statement we at the start of
+::index_read also compare the query id to the latest query id where the
+table handle instance was used. If it has changed, we know we are at the
+start of a new SQL statement. Since the query id can theoretically
+overwrap, we use this test only as a secondary way of determining the
+start of a new SQL statement. */
+
+
/**************************************************************************
Positions an index cursor to the index specified in the handle. Fetches the
row if any. */
@@ -1809,7 +2050,10 @@ ha_innobase::index_read(
row */
const mysql_byte* key_ptr,/* in: key value; if this is NULL
we position the cursor at the
- start or end of index */
+ start or end of index; this can
+ also contain an InnoDB row id, in
+ which case key_len is the InnoDB
+ row id length */
uint key_len,/* in: key value length */
enum ha_rkey_function find_flag)/* in: search flags from my_base.h */
{
@@ -1821,6 +2065,10 @@ ha_innobase::index_read(
ulint ret;
DBUG_ENTER("index_read");
+
+ ut_a(prebuilt->trx ==
+ (trx_t*) current_thd->transaction.all.innobase_tid);
+
statistic_increment(ha_read_key_count, &LOCK_status);
if (last_query_id != user_thd->query_id) {
@@ -1832,10 +2080,8 @@ ha_innobase::index_read(
index = prebuilt->index;
- /* Note that if the select is used for an update, we always
- fetch the clustered index record: therefore the index for which the
- template is built is not necessarily prebuilt->index, but can also
- be the clustered index */
+ /* Note that if the index for which the search template is built is not
+ necessarily prebuilt->index, but can also be the clustered index */
if (prebuilt->sql_stat_start) {
build_template(prebuilt, user_thd, table,
@@ -1843,6 +2089,9 @@ ha_innobase::index_read(
}
if (key_ptr) {
+ /* Convert the search key value to InnoDB format into
+ prebuilt->search_tuple */
+
row_sel_convert_mysql_key_to_innobase(prebuilt->search_tuple,
(byte*) key_val_buff,
index,
@@ -1887,7 +2136,7 @@ ha_innobase::index_read(
error = HA_ERR_KEY_NOT_FOUND;
table->status = STATUS_NOT_FOUND;
} else {
- error = convert_error_code_to_mysql(ret);
+ error = convert_error_code_to_mysql(ret, user_thd);
table->status = STATUS_NOT_FOUND;
}
@@ -1925,7 +2174,6 @@ ha_innobase::change_active_index(
{
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
KEY* key=0;
-
statistic_increment(ha_read_key_count, &LOCK_status);
DBUG_ENTER("change_active_index");
@@ -2010,6 +2258,9 @@ ha_innobase::general_fetch(
DBUG_ENTER("general_fetch");
+ ut_a(prebuilt->trx ==
+ (trx_t*) current_thd->transaction.all.innobase_tid);
+
srv_conc_enter_innodb(prebuilt->trx);
ret = row_search_for_mysql((byte*)buf, 0, prebuilt, match_mode,
@@ -2028,7 +2279,7 @@ ha_innobase::general_fetch(
error = HA_ERR_END_OF_FILE;
table->status = STATUS_NOT_FOUND;
} else {
- error = convert_error_code_to_mysql(ret);
+ error = convert_error_code_to_mysql(ret, user_thd);
table->status = STATUS_NOT_FOUND;
}
@@ -2202,8 +2453,7 @@ ha_innobase::rnd_next(
}
/**************************************************************************
-Fetches a row from the table based on a reference. TODO: currently we use
-'ref_stored_len' of the handle as the key length. This may change. */
+Fetches a row from the table based on a row reference. */
int
ha_innobase::rnd_pos(
@@ -2211,21 +2461,28 @@ ha_innobase::rnd_pos(
/* out: 0, HA_ERR_KEY_NOT_FOUND,
or error code */
mysql_byte* buf, /* in/out: buffer for the row */
- mysql_byte* pos) /* in: primary key value in MySQL format */
+ mysql_byte* pos) /* in: primary key value of the row in the
+ MySQL format, or the row id if the clustered
+ index was internally generated by InnoDB;
+ the length of data in pos has to be
+ ref_length */
{
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
int error;
uint keynr = active_index;
DBUG_ENTER("rnd_pos");
- DBUG_DUMP("key", (char*) pos, ref_stored_len);
+ DBUG_DUMP("key", (char*) pos, ref_length);
statistic_increment(ha_read_rnd_count, &LOCK_status);
+ ut_a(prebuilt->trx ==
+ (trx_t*) current_thd->transaction.all.innobase_tid);
+
if (prebuilt->clust_index_was_generated) {
/* No primary key was defined for the table and we
generated the clustered index from the row id: the
row reference is the row id, not any key value
- that MySQL knows */
+ that MySQL knows of */
error = change_active_index(MAX_KEY);
} else {
@@ -2237,7 +2494,10 @@ ha_innobase::rnd_pos(
DBUG_RETURN(error);
}
- error = index_read(buf, pos, ref_stored_len, HA_READ_KEY_EXACT);
+ /* Note that we assume the length of the row reference is fixed
+ for the table, and it is == ref_length */
+
+ error = index_read(buf, pos, ref_length, HA_READ_KEY_EXACT);
if (error)
{
DBUG_PRINT("error",("Got error: %ld",error));
@@ -2249,7 +2509,8 @@ ha_innobase::rnd_pos(
/*************************************************************************
Stores a reference to the current row to 'ref' field of the handle. Note
-that the function parameter is illogical: we must assume that 'record'
+that in the case where we have generated the clustered index for the
+table, the function parameter is illogical: we MUST ASSUME that 'record'
is the current 'position' of the handle, because if row ref is actually
the row id internally generated in InnoDB, then 'record' does not contain
it. We just guess that the row id must be for the record where the handle
@@ -2263,11 +2524,14 @@ ha_innobase::position(
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
uint len;
+ ut_a(prebuilt->trx ==
+ (trx_t*) current_thd->transaction.all.innobase_tid);
+
if (prebuilt->clust_index_was_generated) {
/* No primary key was defined for the table and we
generated the clustered index from row id: the
row reference will be the row id, not any key value
- that MySQL knows */
+ that MySQL knows of */
len = DATA_ROW_ID_LEN;
@@ -2276,8 +2540,11 @@ ha_innobase::position(
len = store_key_val_for_row(primary_key, (char*) ref, record);
}
- DBUG_ASSERT(len == ref_length);
- ref_stored_len = len;
+ /* Since we do not store len to the buffer 'ref', we must assume
+ that len is always fixed for this table. The following assertion
+ checks this. */
+
+ ut_a(len == ref_length);
}
@@ -2335,7 +2602,7 @@ create_table_def(
error = row_create_table_for_mysql(table, trx);
- error = convert_error_code_to_mysql(error);
+ error = convert_error_code_to_mysql(error, NULL);
DBUG_RETURN(error);
}
@@ -2393,7 +2660,7 @@ create_index(
error = row_create_index_for_mysql(index, trx);
- error = convert_error_code_to_mysql(error);
+ error = convert_error_code_to_mysql(error, NULL);
DBUG_RETURN(error);
}
@@ -2419,7 +2686,7 @@ create_clustered_index_when_no_primary(
0, DICT_CLUSTERED, 0);
error = row_create_index_for_mysql(index, trx);
- error = convert_error_code_to_mysql(error);
+ error = convert_error_code_to_mysql(error, NULL);
return(error);
}
@@ -2445,22 +2712,41 @@ ha_innobase::create(
uint i;
char name2[FN_REFLEN];
char norm_name[FN_REFLEN];
+ THD *thd= current_thd;
DBUG_ENTER("ha_innobase::create");
+ DBUG_ASSERT(thd != NULL);
+
trx = trx_allocate_for_mysql();
+ if (thd->options & OPTION_NO_FOREIGN_KEY_CHECKS) {
+ trx->check_foreigns = FALSE;
+ }
+
+ if (thd->options & OPTION_RELAXED_UNIQUE_CHECKS) {
+ trx->check_unique_secondary = FALSE;
+ }
+
+
fn_format(name2, name, "", "",2); // Remove the .frm extension
normalize_table_name(norm_name, name2);
- /* Create the table definition in InnoDB */
+ /* Latch the InnoDB data dictionary exclusive 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.) */
+
+ row_mysql_lock_data_dictionary();
+
+ /* Create the table definition in InnoDB */
error = create_table_def(trx, form, norm_name);
if (error) {
+ innobase_commit_low(trx);
- trx_commit_for_mysql(trx);
+ row_mysql_unlock_data_dictionary();
trx_free_for_mysql(trx);
@@ -2476,7 +2762,7 @@ ha_innobase::create(
/* Our function row_get_mysql_key_number_for_index assumes
the primary key is always number 0, if it exists */
- assert(primary_key_no == -1 || primary_key_no == 0);
+ DBUG_ASSERT(primary_key_no == -1 || primary_key_no == 0);
/* Create the keys */
@@ -2488,7 +2774,9 @@ ha_innobase::create(
error = create_clustered_index_when_no_primary(trx,
norm_name);
if (error) {
- trx_commit_for_mysql(trx);
+ innobase_commit_low(trx);
+
+ row_mysql_unlock_data_dictionary();
trx_free_for_mysql(trx);
@@ -2501,7 +2789,9 @@ ha_innobase::create(
first */
if ((error = create_index(trx, form, norm_name,
(uint) primary_key_no))) {
- trx_commit_for_mysql(trx);
+ innobase_commit_low(trx);
+
+ row_mysql_unlock_data_dictionary();
trx_free_for_mysql(trx);
@@ -2515,7 +2805,9 @@ ha_innobase::create(
if ((error = create_index(trx, form, norm_name, i))) {
- trx_commit_for_mysql(trx);
+ innobase_commit_low(trx);
+
+ row_mysql_unlock_data_dictionary();
trx_free_for_mysql(trx);
@@ -2527,17 +2819,21 @@ ha_innobase::create(
error = row_table_add_foreign_constraints(trx,
create_info->create_statement, norm_name);
- error = convert_error_code_to_mysql(error);
+ error = convert_error_code_to_mysql(error, NULL);
if (error) {
- trx_commit_for_mysql(trx);
+ innobase_commit_low(trx);
+
+ row_mysql_unlock_data_dictionary();
trx_free_for_mysql(trx);
DBUG_RETURN(error);
}
- trx_commit_for_mysql(trx);
+ innobase_commit_low(trx);
+
+ row_mysql_unlock_data_dictionary();
/* Flush the log to reduce probability that the .frm files and
the InnoDB data dictionary get out-of-sync if the user runs
@@ -2547,7 +2843,7 @@ ha_innobase::create(
innobase_table = dict_table_get(norm_name, NULL);
- assert(innobase_table != 0);
+ DBUG_ASSERT(innobase_table != 0);
/* Tell the InnoDB server that there might be work for
utility threads: */
@@ -2605,11 +2901,11 @@ ha_innobase::delete_table(
srv_active_wake_master_thread();
- trx_commit_for_mysql(trx);
+ innobase_commit_low(trx);
trx_free_for_mysql(trx);
- error = convert_error_code_to_mysql(error);
+ error = convert_error_code_to_mysql(error, NULL);
DBUG_RETURN(error);
}
@@ -2662,10 +2958,10 @@ innobase_drop_database(
srv_active_wake_master_thread();
- trx_commit_for_mysql(trx);
+ innobase_commit_low(trx);
trx_free_for_mysql(trx);
- error = convert_error_code_to_mysql(error);
+ error = convert_error_code_to_mysql(error, NULL);
return(error);
}
@@ -2715,10 +3011,10 @@ ha_innobase::rename_table(
srv_active_wake_master_thread();
- trx_commit_for_mysql(trx);
+ innobase_commit_low(trx);
trx_free_for_mysql(trx);
- error = convert_error_code_to_mysql(error);
+ error = convert_error_code_to_mysql(error, NULL);
DBUG_RETURN(error);
}
@@ -2981,6 +3277,8 @@ ha_innobase::check(
ulint ret;
ut_a(prebuilt->trx && prebuilt->trx->magic_n == TRX_MAGIC_N);
+ ut_a(prebuilt->trx ==
+ (trx_t*) current_thd->transaction.all.innobase_tid);
if (prebuilt->mysql_template == NULL) {
/* Build the template; we will use a dummy template
@@ -3030,8 +3328,9 @@ ha_innobase::update_table_comment(
*pos++=' ';
}
- pos += sprintf(pos, "InnoDB free: %lu kB",
- (ulong) innobase_get_free_space());
+ pos += my_sprintf(pos,
+ (pos,"InnoDB free: %lu kB",
+ (ulong) innobase_get_free_space()));
/* We assume 450 - length bytes of space to print info */
@@ -3177,7 +3476,7 @@ ha_innobase::external_lock(
thd->transaction.all.innodb_active_trans = 1;
trx->n_mysql_tables_in_use++;
- if (thd->tx_isolation == ISO_SERIALIZABLE
+ if (thd->variables.tx_isolation == ISO_SERIALIZABLE
&& prebuilt->select_lock_type == LOCK_NONE) {
/* To get serializable execution we let InnoDB
@@ -3205,7 +3504,7 @@ ha_innobase::external_lock(
innobase_release_stat_resources(trx);
if (!(thd->options
- & (OPTION_NOT_AUTO_COMMIT | OPTION_BEGIN))) {
+ & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
innobase_commit(thd, trx);
thd->transaction.all.innodb_active_trans=0;
@@ -3217,6 +3516,53 @@ ha_innobase::external_lock(
}
/****************************************************************************
+Implements the SHOW INNODB STATUS command. Send the output of the InnoDB
+Monitor to the client. */
+
+int
+innodb_show_status(
+/*===============*/
+ THD* thd) /* in: the MySQL query thread of the caller */
+{
+ String* packet = &thd->packet;
+ char* buf;
+
+ DBUG_ENTER("innodb_show_status");
+
+ /* We let the InnoDB Monitor to output at most 100 kB of text, add
+ a safety margin of 10 kB for buffer overruns */
+
+ buf = (char*)ut_malloc(110 * 1024);
+
+ srv_sprintf_innodb_monitor(buf, 100 * 1024);
+
+ List<Item> field_list;
+
+ field_list.push_back(new Item_empty_string("Status", strlen(buf)));
+
+ if(send_fields(thd, field_list, 1)) {
+ DBUG_RETURN(-1);
+ }
+
+ packet->length(0);
+
+ net_store_data(packet, buf);
+
+ if (my_net_write(&thd->net, (char*)thd->packet.ptr(),
+ packet->length())) {
+ ut_free(buf);
+
+ DBUG_RETURN(-1);
+ }
+
+ ut_free(buf);
+
+ send_eof(&thd->net);
+
+ DBUG_RETURN(0);
+}
+
+/****************************************************************************
Handling the shared INNOBASE_SHARE structure that is needed to provide table
locking.
****************************************************************************/
@@ -3325,34 +3671,53 @@ ha_innobase::store_lock(
}
/***********************************************************************
-Returns the next auto-increment column value for the table. write_row
-normally fetches the value from the cache in the data dictionary. This
-function in used by SHOW TABLE STATUS and when the first insert to the table
-is done after database startup. */
+This function initializes the auto-inc counter if it has not been
+initialized yet. This function does not change the value of the auto-inc
+counter if it already has been initialized. In parameter ret returns
+the value of the auto-inc counter. */
-longlong
-ha_innobase::get_auto_increment()
-/*=============================*/
- /* out: the next auto-increment column value */
+int
+ha_innobase::innobase_read_and_init_auto_inc(
+/*=========================================*/
+ /* out: 0 or error code: deadlock or
+ lock wait timeout */
+ longlong* ret) /* out: auto-inc value */
{
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
- longlong nr;
+ longlong auto_inc;
int error;
- /* Also SHOW TABLE STATUS calls this function. Previously, when we did
- always read the max autoinc key value, setting x-locks, users were
- surprised that SHOW TABLE STATUS could end up in a deadlock with
- ordinary SQL queries. We avoid these deadlocks if the auto-inc
- counter for the table has been initialized by fetching the value
- from the table struct in dictionary cache. */
+ ut_a(prebuilt);
+ ut_a(prebuilt->trx ==
+ (trx_t*) current_thd->transaction.all.innobase_tid);
+ ut_a(prebuilt->table);
+
+ auto_inc = dict_table_autoinc_read(prebuilt->table);
- assert(prebuilt->table);
-
- nr = dict_table_autoinc_read(prebuilt->table);
+ if (auto_inc != 0) {
+ /* Already initialized */
+ *ret = auto_inc;
+
+ return(0);
+ }
+
+ srv_conc_enter_innodb(prebuilt->trx);
+ error = row_lock_table_autoinc_for_mysql(prebuilt);
+ srv_conc_exit_innodb(prebuilt->trx);
+
+ if (error != DB_SUCCESS) {
+ error = convert_error_code_to_mysql(error, user_thd);
- if (nr != 0) {
+ goto func_exit;
+ }
- return(nr + 1);
+ /* Check again if someone has initialized the counter meanwhile */
+ auto_inc = dict_table_autoinc_read(prebuilt->table);
+
+ if (auto_inc != 0) {
+ *ret = auto_inc;
+
+ return(0);
}
(void) extra(HA_EXTRA_KEYREAD);
@@ -3372,22 +3737,63 @@ ha_innobase::get_auto_increment()
prebuilt->hint_no_need_to_fetch_extra_cols = FALSE;
- prebuilt->trx->mysql_n_tables_locked += 1;
+ prebuilt->trx->mysql_n_tables_locked += 1;
- error = index_last(table->record[1]);
+ error = index_last(table->record[1]);
if (error) {
- nr = 1;
+ if (error == HA_ERR_END_OF_FILE) {
+ /* The table was empty, initialize to 1 */
+ auto_inc = 1;
+
+ error = 0;
+ } else {
+ /* Deadlock or a lock wait timeout */
+ auto_inc = -1;
+
+ goto func_exit;
+ }
} else {
- nr = (longlong) table->next_number_field->
+ /* Initialize to max(col) + 1 */
+ auto_inc = (longlong) table->next_number_field->
val_int_offset(table->rec_buff_length) + 1;
}
+ dict_table_autoinc_initialize(prebuilt->table, auto_inc);
+
+func_exit:
(void) extra(HA_EXTRA_NO_KEYREAD);
- index_end();
+ index_end();
+
+ *ret = auto_inc;
+
+ return(error);
+}
+
+/***********************************************************************
+This function initializes the auto-inc counter if it has not been
+initialized yet. This function does not change the value of the auto-inc
+counter if it already has been initialized. Returns the value of the
+auto-inc counter. */
+
+longlong
+ha_innobase::get_auto_increment()
+/*=============================*/
+ /* out: auto-increment column value, -1 if error
+ (deadlock or lock wait timeout) */
+{
+ longlong nr;
+ int error;
+
+ error = innobase_read_and_init_auto_inc(&nr);
+
+ if (error) {
+
+ return(-1);
+ }
- return(nr);
+ return(nr);
}
#endif /* HAVE_INNOBASE_DB */
diff --git a/sql/ha_innodb.h b/sql/ha_innodb.h
index b2aa963f91a..2addd957c8c 100644
--- a/sql/ha_innodb.h
+++ b/sql/ha_innodb.h
@@ -52,8 +52,6 @@ class ha_innobase: public handler
byte* key_val_buff; /* buffer used in converting
search key values from MySQL format
to Innodb format */
- uint ref_stored_len; /* length of the key value stored to
- 'ref' buffer of the handle, if any */
ulong int_table_flags;
uint primary_key;
uint last_dup_key;
@@ -71,14 +69,14 @@ class ha_innobase: public handler
int update_thd(THD* thd);
int change_active_index(uint keynr);
int general_fetch(byte* buf, uint direction, uint match_mode);
+ int innobase_read_and_init_auto_inc(longlong* ret);
/* Init values for the class: */
public:
ha_innobase(TABLE *table): handler(table),
int_table_flags(HA_REC_NOT_IN_SEQ |
HA_KEYPOS_TO_RNDPOS | HA_LASTKEY_ORDER |
- HA_HAVE_KEY_READ_ONLY |
- HA_NULL_KEY |
+ HA_NULL_KEY | HA_CAN_SQL_HANDLER |
HA_NOT_EXACT_COUNT |
HA_NO_WRITE_DELAYED |
HA_PRIMARY_KEY_IN_READ_INDEX |
@@ -98,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_NOT_READ_PREFIX_LAST);
+ 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; }
@@ -166,11 +164,11 @@ class ha_innobase: public handler
void free_foreign_key_create_info(char* str);
THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
enum thr_lock_type lock_type);
+ void init_table_handle_for_HANDLER();
longlong get_auto_increment();
};
extern bool innodb_skip;
-extern SHOW_COMP_OPTION have_innodb;
extern uint innobase_init_flags, innobase_lock_type;
extern ulong innobase_cache_size;
extern char *innobase_home, *innobase_tmpdir, *innobase_logdir;
@@ -203,4 +201,5 @@ int innobase_report_binlog_offset_and_commit(
int innobase_rollback(THD *thd, void* trx_handle);
int innobase_close_connection(THD *thd);
int innobase_drop_database(char *path);
+int innodb_show_status(THD* thd);
diff --git a/sql/ha_isam.h b/sql/ha_isam.h
index bae9700f149..82a243ef5c0 100644
--- a/sql/ha_isam.h
+++ b/sql/ha_isam.h
@@ -26,16 +26,16 @@
class ha_isam: public handler
{
N_INFO *file;
- uint int_table_flags;
+ /* We need this as table_flags() may change after open() */
+ ulong int_table_flags;
public:
- ha_isam(TABLE *table): handler(table), file(0),
- int_table_flags(HA_READ_RND_SAME |
- HA_KEYPOS_TO_RNDPOS | HA_LASTKEY_ORDER |
- HA_HAVE_KEY_READ_ONLY |
+ ha_isam(TABLE *table)
+ :handler(table), file(0),
+ int_table_flags(HA_READ_RND_SAME | HA_KEYPOS_TO_RNDPOS | HA_LASTKEY_ORDER |
HA_KEY_READ_WRONG_STR | HA_DUPP_POS |
HA_NOT_DELETE_WITH_CACHE)
- {}
+ {}
~ha_isam() {}
const char *table_type() const { return "ISAM"; }
const char *index_type(uint key_number) { return "BTREE"; }
@@ -80,5 +80,4 @@ class ha_isam: public handler
int create(const char *name, TABLE *form, HA_CREATE_INFO *create_info);
THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
enum thr_lock_type lock_type);
-
};
diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc
index e32656b44d3..e9ef5b4ce12 100644
--- a/sql/ha_myisam.cc
+++ b/sql/ha_myisam.cc
@@ -31,7 +31,6 @@
#include "../myisam/rt_index.h"
#endif
-ulong myisam_sort_buffer_size;
ulong myisam_recover_options= HA_RECOVER_NONE;
/* bits in myisam_recover_options */
@@ -46,6 +45,7 @@ TYPELIB myisam_recover_typelib= {array_elements(myisam_recover_names)-1,"",
*****************************************************************************/
// collect errors printed by mi_check routines
+
static void mi_check_print_msg(MI_CHECK *param, const char* msg_type,
const char *fmt, va_list args)
{
@@ -67,8 +67,7 @@ static void mi_check_print_msg(MI_CHECK *param, const char* msg_type,
sql_print_error(msgbuf);
return;
}
- if (param->testflag & (T_CREATE_MISSING_KEYS | T_SAFE_REPAIR |
- T_AUTO_REPAIR))
+ if (param->testflag & (T_CREATE_MISSING_KEYS | T_SAFE_REPAIR | T_AUTO_REPAIR))
{
my_message(ER_NOT_KEYFILE,msgbuf,MYF(MY_WME));
return;
@@ -139,7 +138,7 @@ int ha_myisam::net_read_dump(NET* net)
int error = 0;
my_seek(data_fd, 0L, MY_SEEK_SET, MYF(MY_WME));
- for(;;)
+ for (;;)
{
ulong packet_len = my_net_read(net);
if (!packet_len)
@@ -176,7 +175,7 @@ int ha_myisam::dump(THD* thd, int fd)
int error = 0;
my_seek(data_fd, 0L, MY_SEEK_SET, MYF(MY_WME));
- for(; bytes_to_read > 0;)
+ for (; bytes_to_read > 0;)
{
uint bytes = my_read(data_fd, buf, blocksize, MYF(MY_WME));
if (bytes == MY_FILE_ERROR)
@@ -223,10 +222,10 @@ int ha_myisam::open(const char *name, int mode, uint test_if_locked)
return (my_errno ? my_errno : -1);
if (test_if_locked & (HA_OPEN_IGNORE_IF_LOCKED | HA_OPEN_TMP_TABLE))
- VOID(mi_extra(file,HA_EXTRA_NO_WAIT_LOCK));
+ VOID(mi_extra(file, HA_EXTRA_NO_WAIT_LOCK, 0));
info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
if (!(test_if_locked & HA_OPEN_WAIT_IF_LOCKED))
- VOID(mi_extra(file,HA_EXTRA_WAIT_LOCK));
+ VOID(mi_extra(file, HA_EXTRA_WAIT_LOCK, 0));
if (!table->db_record_offset)
int_table_flags|=HA_REC_NOT_IN_SEQ;
return (0);
@@ -499,8 +498,8 @@ int ha_myisam::repair(THD* thd, HA_CHECK_OPT *check_opt)
while ((error=repair(thd,param,0)) && param.retry_repair)
{
param.retry_repair=0;
- if ((param.testflag & T_RETRY_WITHOUT_QUICK) &&
- (param.testflag & T_QUICK))
+ if (test_all_bits(param.testflag,
+ (uint) (T_RETRY_WITHOUT_QUICK | T_QUICK)))
{
param.testflag&= ~T_RETRY_WITHOUT_QUICK;
sql_print_error("Warning: Retrying repair of: '%s' without quick",
@@ -670,13 +669,16 @@ void ha_myisam::deactivate_non_unique_index(ha_rows rows)
if (share->state.key_map == ((ulonglong) 1L << share->base.keys)-1)
{
if (!(specialflag & SPECIAL_SAFE_MODE))
- if (rows==HA_POS_ERROR)
- mi_extra(file, HA_EXTRA_NO_KEYS);
+ {
+ if (rows == HA_POS_ERROR)
+ mi_extra(file, HA_EXTRA_NO_KEYS, 0);
else
{
mi_disable_non_unique_index(file,rows);
- mi_extra(file, HA_EXTRA_BULK_INSERT_BEGIN);
+ ha_myisam::extra_opt(HA_EXTRA_BULK_INSERT_BEGIN,
+ current_thd->variables.bulk_insert_buff_size);
}
+ }
enable_activate_all_index=1;
}
else
@@ -691,7 +693,7 @@ bool ha_myisam::activate_all_index(THD *thd)
MYISAM_SHARE* share = file->s;
DBUG_ENTER("activate_all_index");
- mi_extra(file, HA_EXTRA_BULK_INSERT_END);
+ mi_extra(file, HA_EXTRA_BULK_INSERT_END, 0);
if (enable_activate_all_index &&
share->state.key_map != set_bits(ulonglong, share->base.keys))
{
@@ -700,9 +702,9 @@ bool ha_myisam::activate_all_index(THD *thd)
myisamchk_init(&param);
param.op_name = (char*) "recreating_index";
param.testflag = (T_SILENT | T_REP_BY_SORT | T_QUICK |
- T_CREATE_MISSING_KEYS | T_TRUST_HEADER);
+ T_CREATE_MISSING_KEYS);
param.myf_rw&= ~MY_WAIT_IF_FULL;
- param.sort_buffer_length= myisam_sort_buffer_size;
+ param.sort_buffer_length= thd->variables.myisam_sort_buff_size;
param.tmpdir=mysql_tmpdir;
error=repair(thd,param,0) != HA_ADMIN_OK;
thd->proc_info=save_proc_info;
@@ -833,8 +835,7 @@ int ha_myisam::rnd_init(bool scan)
{
if (scan)
return mi_scan_init(file);
- else
- return mi_extra(file,HA_EXTRA_RESET);
+ return mi_extra(file, HA_EXTRA_RESET, 0);
}
int ha_myisam::rnd_next(byte *buf)
@@ -889,7 +890,8 @@ void ha_myisam::info(uint flag)
ref_length=info.reflength;
table->db_options_in_use = info.options;
block_size=myisam_block_size;
- table->keys_in_use &= info.key_map;
+ table->keys_in_use&= info.key_map;
+ table->keys_for_keyread&= info.key_map;
table->db_record_offset=info.record_offset;
if (table->key_parts)
memcpy((char*) table->key_info[0].rec_per_key,
@@ -925,17 +927,27 @@ void ha_myisam::info(uint flag)
int ha_myisam::extra(enum ha_extra_function operation)
{
- if (((specialflag & SPECIAL_SAFE_MODE) || (test_flags & TEST_NO_EXTRA)) &&
+ if ((specialflag & SPECIAL_SAFE_MODE) && operation == HA_EXTRA_KEYREAD)
+ return 0;
+ return mi_extra(file, operation, 0);
+}
+
+
+/* To be used with WRITE_CACHE, EXTRA_CACHE and BULK_INSERT_BEGIN */
+
+int ha_myisam::extra_opt(enum ha_extra_function operation, ulong cache_size)
+{
+ if ((specialflag & SPECIAL_SAFE_MODE) &
(operation == HA_EXTRA_WRITE_CACHE ||
- operation == HA_EXTRA_KEYREAD ||
operation == HA_EXTRA_BULK_INSERT_BEGIN))
return 0;
- return mi_extra(file,operation);
+ return mi_extra(file, operation, (void*) &cache_size);
}
+
int ha_myisam::reset(void)
{
- return mi_extra(file,HA_EXTRA_RESET);
+ return mi_extra(file, HA_EXTRA_RESET, 0);
}
int ha_myisam::delete_all_rows()
diff --git a/sql/ha_myisam.h b/sql/ha_myisam.h
index d304085fdd5..215608f8f0a 100644
--- a/sql/ha_myisam.h
+++ b/sql/ha_myisam.h
@@ -24,11 +24,11 @@
#include <myisam.h>
#include <ft_global.h>
-#define HA_RECOVER_NONE 0 // No automatic recover
-#define HA_RECOVER_DEFAULT 1 // Automatic recover active
-#define HA_RECOVER_BACKUP 2 // Make a backupfile on recover
-#define HA_RECOVER_FORCE 4 // Recover even if we loose rows
-#define HA_RECOVER_QUICK 8 // Don't check rows in data file
+#define HA_RECOVER_NONE 0 /* No automatic recover */
+#define HA_RECOVER_DEFAULT 1 /* Automatic recover active */
+#define HA_RECOVER_BACKUP 2 /* Make a backupfile on recover */
+#define HA_RECOVER_FORCE 4 /* Recover even if we loose rows */
+#define HA_RECOVER_QUICK 8 /* Don't check rows in data file */
extern ulong myisam_sort_buffer_size;
extern TYPELIB myisam_recover_typelib;
@@ -45,7 +45,6 @@ class ha_myisam: public handler
public:
ha_myisam(TABLE *table): handler(table), file(0),
int_table_flags(HA_READ_RND_SAME | HA_KEYPOS_TO_RNDPOS | HA_LASTKEY_ORDER |
- HA_HAVE_KEY_READ_ONLY |
HA_NULL_KEY | HA_CAN_FULLTEXT | HA_CAN_SQL_HANDLER |
HA_DUPP_POS | HA_BLOB_KEY | HA_AUTO_PART_KEY),
enable_activate_all_index(1)
@@ -55,6 +54,12 @@ class ha_myisam: public handler
const char *index_type(uint key_number);
const char **bas_ext() const;
ulong table_flags() const { return int_table_flags; }
+ ulong index_flags(uint inx) const
+ {
+ ulong flags=(HA_READ_NEXT | HA_READ_PREV | HA_READ_ORDER);
+ return (flags | ((table->key_info[inx].algorithm == HA_KEY_ALG_FULLTEXT) ?
+ 0 : HA_KEY_READ_ONLY));
+ }
uint max_record_length() const { return HA_MAX_REC_LENGTH; }
uint max_keys() const { return MI_MAX_KEY; }
uint max_key_parts() const { return MAX_REF_PARTS; }
@@ -95,6 +100,7 @@ class ha_myisam: public handler
my_off_t row_position() { return mi_position(file); }
void info(uint);
int extra(enum ha_extra_function operation);
+ int extra_opt(enum ha_extra_function operation, ulong cache_size);
int reset(void);
int external_lock(THD *thd, int lock_type);
int delete_all_rows(void);
diff --git a/sql/ha_myisammrg.cc b/sql/ha_myisammrg.cc
index 4e09c87f341..ee72216baa5 100644
--- a/sql/ha_myisammrg.cc
+++ b/sql/ha_myisammrg.cc
@@ -49,10 +49,10 @@ int ha_myisammrg::open(const char *name, int mode, uint test_if_locked)
myrg_extrafunc(file, query_cache_invalidate_by_MyISAM_filename_ref);
if (!(test_if_locked == HA_OPEN_WAIT_IF_LOCKED ||
test_if_locked == HA_OPEN_ABORT_IF_LOCKED))
- myrg_extra(file,HA_EXTRA_NO_WAIT_LOCK);
+ myrg_extra(file,HA_EXTRA_NO_WAIT_LOCK,0);
info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
if (!(test_if_locked & HA_OPEN_WAIT_IF_LOCKED))
- myrg_extra(file,HA_EXTRA_WAIT_LOCK);
+ myrg_extra(file,HA_EXTRA_WAIT_LOCK,0);
if (table->reclength != mean_rec_length && mean_rec_length)
{
DBUG_PRINT("error",("reclength: %d mean_rec_length: %d",
@@ -75,8 +75,7 @@ int ha_myisammrg::write_row(byte * buf)
if (table->time_stamp)
update_timestamp(buf+table->time_stamp-1);
if (table->next_number_field && buf == table->record[0])
- return (my_errno=HA_ERR_WRONG_COMMAND);
- // update_auto_increment(); - [phi] have to check this before allowing it
+ update_auto_increment();
return myrg_write(file,buf);
}
@@ -155,7 +154,7 @@ int ha_myisammrg::index_last(byte * buf)
int ha_myisammrg::rnd_init(bool scan)
{
- return myrg_extra(file,HA_EXTRA_RESET);
+ return myrg_extra(file,HA_EXTRA_RESET,0);
}
int ha_myisammrg::rnd_next(byte *buf)
@@ -210,12 +209,25 @@ int ha_myisammrg::extra(enum ha_extra_function operation)
if (operation == HA_EXTRA_FORCE_REOPEN ||
operation == HA_EXTRA_PREPARE_FOR_DELETE)
return 0;
- return myrg_extra(file,operation);
+ return myrg_extra(file,operation,0);
}
+
+/* To be used with WRITE_CACHE, EXTRA_CACHE and BULK_INSERT_BEGIN */
+
+int ha_myisammrg::extra_opt(enum ha_extra_function operation, ulong cache_size)
+{
+ if ((specialflag & SPECIAL_SAFE_MODE) &
+ (operation == HA_EXTRA_WRITE_CACHE ||
+ operation == HA_EXTRA_BULK_INSERT_BEGIN))
+ return 0;
+ return myrg_extra(file, operation, (void*) &cache_size);
+}
+
+
int ha_myisammrg::reset(void)
{
- return myrg_extra(file,HA_EXTRA_RESET);
+ return myrg_extra(file,HA_EXTRA_RESET,0);
}
int ha_myisammrg::external_lock(THD *thd, int lock_type)
diff --git a/sql/ha_myisammrg.h b/sql/ha_myisammrg.h
index ed2817f3ca6..b75d5360097 100644
--- a/sql/ha_myisammrg.h
+++ b/sql/ha_myisammrg.h
@@ -34,11 +34,16 @@ class ha_myisammrg: public handler
const char **bas_ext() const;
ulong table_flags() const
{
- return (HA_REC_NOT_IN_SEQ | HA_READ_RND_SAME |
- HA_HAVE_KEY_READ_ONLY | HA_KEYPOS_TO_RNDPOS |
- HA_LASTKEY_ORDER |
+ return (HA_REC_NOT_IN_SEQ | HA_READ_RND_SAME | HA_AUTO_PART_KEY |
+ HA_KEYPOS_TO_RNDPOS | HA_LASTKEY_ORDER |
HA_NULL_KEY | HA_BLOB_KEY);
}
+ ulong index_flags(uint inx) const
+ {
+ ulong flags=(HA_READ_NEXT | HA_READ_PREV | HA_READ_ORDER);
+ return (flags | ((table->key_info[inx].algorithm == HA_KEY_ALG_FULLTEXT) ?
+ 0 : HA_KEY_READ_ONLY));
+ }
uint max_record_length() const { return HA_MAX_REC_LENGTH; }
uint max_keys() const { return MI_MAX_KEY; }
uint max_key_parts() const { return MAX_REF_PARTS; }
@@ -67,6 +72,7 @@ class ha_myisammrg: public handler
my_off_t row_position() { return myrg_position(file); }
void info(uint);
int extra(enum ha_extra_function operation);
+ int extra_opt(enum ha_extra_function operation, ulong cache_size);
int reset(void);
int external_lock(THD *thd, int lock_type);
uint lock_count(void) const;
diff --git a/sql/handler.cc b/sql/handler.cc
index 47c59be0166..f60c3449075 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -53,8 +53,10 @@ const char *ha_table_type[] = {
"MRG_ISAM","MYISAM", "MRG_MYISAM", "BDB", "INNODB", "GEMINI", "?", "?",NullS
};
-TYPELIB ha_table_typelib= {array_elements(ha_table_type)-4,"",
- ha_table_type+1};
+TYPELIB ha_table_typelib=
+{
+ array_elements(ha_table_type)-3, "", ha_table_type
+};
const char *ha_row_type[] = {
"", "FIXED", "DYNAMIC", "COMPRESSED","?","?","?"
@@ -216,7 +218,8 @@ int ha_autocommit_or_rollback(THD *thd, int error)
}
else
(void) ha_rollback_stmt(thd);
- thd->tx_isolation=thd->session_tx_isolation;
+
+ thd->variables.tx_isolation=thd->session_tx_isolation;
}
#endif
DBUG_RETURN(error);
@@ -272,6 +275,7 @@ int ha_commit_trans(THD *thd, THD_TRANS* trans)
{
bool operation_done= 0;
bool transaction_commited= 0;
+
/* Update the binary log if we have cached some queries */
if (trans == &thd->transaction.all && mysql_bin_log.is_open() &&
my_b_tell(&thd->transaction.trans_log))
@@ -314,9 +318,12 @@ int ha_commit_trans(THD *thd, THD_TRANS* trans)
#endif /*HAVE_QUERY_CACHE*/
if (error && trans == &thd->transaction.all && mysql_bin_log.is_open())
sql_print_error("Error: Got error during commit; Binlog is not up to date!");
- thd->tx_isolation=thd->session_tx_isolation;
+ thd->variables.tx_isolation=thd->session_tx_isolation;
if (operation_done)
+ {
statistic_increment(ha_commit_count,&LOCK_status);
+ thd->transaction.cleanup();
+ }
}
#endif // using transactions
DBUG_RETURN(error);
@@ -359,9 +366,12 @@ int ha_rollback_trans(THD *thd, THD_TRANS *trans)
reinit_io_cache(&thd->transaction.trans_log,
WRITE_CACHE, (my_off_t) 0, 0, 1);
thd->transaction.trans_log.end_of_file= max_binlog_cache_size;
- thd->tx_isolation=thd->session_tx_isolation;
+ thd->variables.tx_isolation=thd->session_tx_isolation;
if (operation_done)
+ {
statistic_increment(ha_rollback_count,&LOCK_status);
+ thd->transaction.cleanup();
+ }
}
#endif /* USING_TRANSACTIONS */
DBUG_RETURN(error);
@@ -622,16 +632,29 @@ longlong handler::get_auto_increment()
{
longlong nr;
int error;
+
(void) extra(HA_EXTRA_KEYREAD);
index_init(table->next_number_index);
- error=index_last(table->record[1]);
+ if (!table->next_number_key_offset)
+ { // Autoincrement at key-start
+ error=index_last(table->record[1]);
+ }
+ else
+ {
+ byte key[MAX_KEY_LENGTH];
+ key_copy(key,table,table->next_number_index,
+ table->next_number_key_offset);
+ error=index_read(table->record[1], key, table->next_number_key_offset,
+ HA_READ_PREFIX_LAST);
+ }
+
if (error)
nr=1;
else
nr=(longlong) table->next_number_field->
val_int_offset(table->rec_buff_length)+1;
- (void) extra(HA_EXTRA_NO_KEYREAD);
index_end();
+ (void) extra(HA_EXTRA_NO_KEYREAD);
return nr;
}
@@ -859,8 +882,14 @@ int ha_create_table(const char *name, HA_CREATE_INFO *create_info,
void ha_key_cache(void)
{
if (keybuff_size)
- (void) init_key_cache(keybuff_size,0);
-} /* ha_key_cache */
+ (void) init_key_cache(keybuff_size);
+}
+
+
+void ha_resize_key_cache(void)
+{
+ (void) resize_key_cache(keybuff_size);
+}
static int NEAR_F delete_file(const char *name,const char *ext,int extflag)
@@ -869,3 +898,9 @@ static int NEAR_F delete_file(const char *name,const char *ext,int extflag)
VOID(fn_format(buff,name,"",ext,extflag | 4));
return(my_delete_with_symlink(buff,MYF(MY_WME)));
}
+
+void st_ha_check_opt::init()
+{
+ flags= sql_flags= 0;
+ sort_buffer_size = current_thd->variables.myisam_sort_buff_size;
+}
diff --git a/sql/handler.h b/sql/handler.h
index 7260e8f2f8c..adbfff8c55c 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -48,7 +48,6 @@
#define HA_TABLE_SCAN_ON_INDEX 4 /* No separate data/index file */
#define HA_REC_NOT_IN_SEQ 8 /* ha_info don't return recnumber;
It returns a position to ha_r_rnd */
-#define HA_HAVE_KEY_READ_ONLY 16 /* Can read only keys (no record) */
#define HA_NO_INDEX 32 /* No index needed for next/prev */
#define HA_KEY_READ_WRONG_STR 64 /* keyread returns converted strings */
#define HA_NULL_KEY 128 /* One can have keys with NULL */
@@ -83,6 +82,7 @@
#define HA_READ_ORDER 8 /* Read through record-keys in order */
#define HA_ONLY_WHOLE_INDEX 16 /* Can't use part key searches */
#define HA_NOT_READ_PREFIX_LAST 32
+#define HA_KEY_READ_ONLY 64 /* Support HA_EXTRA_KEYREAD */
/*
Parameters for open() (in register form->filestat)
@@ -174,18 +174,13 @@ typedef struct st_ha_create_information
struct st_table;
typedef struct st_table TABLE;
-extern ulong myisam_sort_buffer_size;
typedef struct st_ha_check_opt
{
ulong sort_buffer_size;
uint flags; /* isam layer flags (e.g. for myisamchk) */
uint sql_flags; /* sql layer flags - for something myisamchk cannot do */
- inline void init()
- {
- flags= sql_flags= 0;
- sort_buffer_size = myisam_sort_buffer_size;
- }
+ void init();
} HA_CHECK_OPT;
class handler :public Sql_alloc
@@ -287,6 +282,10 @@ public:
virtual my_off_t row_position() { return HA_OFFSET_ERROR; }
virtual void info(uint)=0;
virtual int extra(enum ha_extra_function operation)=0;
+ virtual int extra_opt(enum ha_extra_function operation, ulong cache_size)
+ {
+ return extra(operation);
+ }
virtual int reset()=0;
virtual int external_lock(THD *thd, int lock_type)=0;
virtual void unlock_row() {}
@@ -316,6 +315,8 @@ public:
virtual void append_create_info(String *packet) {}
virtual char* get_foreign_key_create_info()
{ return(NULL);} /* gets foreign key create string from InnoDB */
+ virtual void init_table_handle_for_HANDLER()
+ { return; } /* prepare InnoDB for HANDLER */
virtual void free_foreign_key_create_info(char* str) {}
/* The following can be called without an open handler */
virtual const char *table_type() const =0;
@@ -323,7 +324,7 @@ public:
virtual ulong table_flags(void) const =0;
virtual ulong index_flags(uint idx) const
{
- return (HA_READ_NEXT | HA_READ_PREV | HA_READ_ORDER);
+ return (HA_READ_NEXT | HA_READ_PREV | HA_READ_ORDER | HA_KEY_READ_ONLY);
}
virtual uint max_record_length() const =0;
virtual uint max_keys() const =0;
@@ -369,6 +370,7 @@ int ha_create_table(const char *name, HA_CREATE_INFO *create_info,
int ha_delete_table(enum db_type db_type, const char *path);
void ha_drop_database(char* path);
void ha_key_cache(void);
+void ha_resize_key_cache(void);
int ha_start_stmt(THD *thd);
int ha_report_binlog_offset_and_commit(THD *thd, char *log_file_name,
my_off_t end_offset);
diff --git a/sql/hostname.cc b/sql/hostname.cc
index bcc8ea87281..3da752f3b64 100644
--- a/sql/hostname.cc
+++ b/sql/hostname.cc
@@ -57,8 +57,8 @@ void hostname_cache_refresh()
bool hostname_cache_init()
{
- host_entry *tmp;
- uint offset= (uint) ((char*) (&tmp->ip) - (char*) tmp);
+ host_entry tmp;
+ uint offset= (uint) ((char*) (&tmp.ip) - (char*) &tmp);
(void) pthread_mutex_init(&LOCK_hostname,MY_MUTEX_INIT_SLOW);
if (!(hostname_cache=new hash_filo(HOST_CACHE_SIZE, offset,
diff --git a/sql/item.cc b/sql/item.cc
index f717b78f4bf..7693ef428c6 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -568,12 +568,14 @@ void Item_datetime::make_field(Send_field *tmp_field)
init_make_field(tmp_field,FIELD_TYPE_DATETIME);
}
+
void Item_null::make_field(Send_field *tmp_field)
{
init_make_field(tmp_field,FIELD_TYPE_NULL);
tmp_field->length=4;
}
+
void Item_func::make_field(Send_field *tmp_field)
{
init_make_field(tmp_field, ((result_type() == STRING_RESULT) ?
@@ -780,7 +782,7 @@ bool Item::send(THD *thd, String *packet)
String s(buff,sizeof(buff),packet->charset()),*res;
if (!(res=val_str(&s)))
return net_store_null(packet);
- if ((convert=thd->convert_set))
+ if ((convert=thd->variables.convert_set))
return convert->store(packet,res->ptr(),res->length());
return net_store_data(packet,res->ptr(),res->length());
}
diff --git a/sql/item.h b/sql/item.h
index a0b637b6030..206d7b5bd78 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -31,7 +31,7 @@ public:
enum Type {FIELD_ITEM,FUNC_ITEM,SUM_FUNC_ITEM,STRING_ITEM,
INT_ITEM,REAL_ITEM,NULL_ITEM,VARBIN_ITEM,
- COPY_STR_ITEM,FIELD_AVG_ITEM,
+ COPY_STR_ITEM,FIELD_AVG_ITEM, DEFAULT_ITEM,
PROC_ITEM,COND_ITEM,REF_ITEM,FIELD_STD_ITEM, CONST_ITEM,
SUBSELECT_ITEM};
enum cond_result { COND_UNDEF,COND_OK,COND_TRUE,COND_FALSE };
@@ -82,6 +82,7 @@ public:
virtual bool get_date(TIME *ltime,bool fuzzydate);
virtual bool get_time(TIME *ltime);
virtual bool is_null() { return 0; }
+ virtual unsigned int size_of()= 0;
};
@@ -99,8 +100,10 @@ public:
field_name(field_name_par), depended_from(0)
{ name = (char*) field_name_par; }
const char *full_name() const;
+ unsigned int size_of() { return sizeof(*this);}
};
+
class Item_field :public Item_ident
{
void set_field(Field *field);
@@ -121,7 +124,10 @@ public:
double val_result();
longlong val_int_result();
String *str_result(String* tmp);
- bool send(THD *thd, String *str_arg) { return result_field->send(thd,str_arg); }
+ bool send(THD *thd, String *str_arg)
+ {
+ return result_field->send(thd,str_arg);
+ }
void make_field(Send_field *field);
bool fix_fields(THD *, struct st_table_list *, Item **);
int save_in_field(Field *field);
@@ -135,6 +141,7 @@ public:
bool get_date(TIME *ltime,bool fuzzydate);
bool get_time(TIME *ltime);
bool is_null() { return field->is_null(); }
+ unsigned int size_of() { return sizeof(*this);}
};
@@ -156,6 +163,7 @@ public:
bool basic_const_item() const { return 1; }
Item *new_item() { return new Item_null(name); }
bool is_null() { return 1; }
+ unsigned int size_of() { return sizeof(*this);}
};
class Item_param :public Item
@@ -219,6 +227,7 @@ public:
bool basic_const_item() const { return 1; }
Item *new_item() { return new Item_int(name,value,max_length); }
void print(String *str);
+ unsigned int size_of() { return sizeof(*this);}
};
@@ -227,11 +236,13 @@ class Item_uint :public Item_int
public:
Item_uint(const char *str_arg, uint length) :
Item_int(str_arg, (longlong) strtoull(str_arg,(char**) 0,10), length) {}
+ Item_uint(uint32 i) :Item_int((longlong) i, 10) {}
double val() { return ulonglong2double(value); }
String *val_str(String*);
void make_field(Send_field *field);
Item *new_item() { return new Item_uint(name,max_length); }
void print(String *str);
+ unsigned int size_of() { return sizeof(*this);}
};
@@ -262,6 +273,7 @@ public:
void make_field(Send_field *field);
bool basic_const_item() const { return 1; }
Item *new_item() { return new Item_real(name,value,decimals,max_length); }
+ unsigned int size_of() { return sizeof(*this);}
};
@@ -273,6 +285,7 @@ public:
decimals=NOT_FIXED_DEC;
max_length=DBL_DIG+8;
}
+ unsigned int size_of() { return sizeof(*this);}
};
class Item_string :public Item
@@ -306,8 +319,31 @@ public:
String *const_string() { return &str_value; }
inline void append(char *str,uint length) { str_value.append(str,length); }
void print(String *str);
+ unsigned int size_of() { return sizeof(*this);}
+};
+
+
+/* For INSERT ... VALUES (DEFAULT) */
+
+class Item_default :public Item
+{
+public:
+ Item_default() { name= (char*) "DEFAULT"; }
+ enum Type type() const { return DEFAULT_ITEM; }
+ void make_field(Send_field *field) {}
+ bool save_in_field(Field *field)
+ {
+ field->set_default();
+ return 0;
+ }
+ virtual double val() { return 0.0; }
+ virtual longlong val_int() { return 0; }
+ virtual String *val_str(String *str) { return 0; }
+ bool basic_const_item() const { return 1; }
+ unsigned int size_of() { return sizeof(*this);}
};
+
/* for show tables */
class Item_datetime :public Item_string
@@ -316,6 +352,7 @@ public:
Item_datetime(const char *item_name): Item_string(item_name,"",0,default_charset_info)
{ max_length=19;}
void make_field(Send_field *field);
+ unsigned int size_of() { return sizeof(*this);}
};
class Item_empty_string :public Item_string
@@ -323,6 +360,7 @@ class Item_empty_string :public Item_string
public:
Item_empty_string(const char *header,uint length) :Item_string("",0,default_charset_info)
{ name=(char*) header; max_length=length;}
+ unsigned int size_of() { return sizeof(*this);}
};
class Item_varbinary :public Item
@@ -337,6 +375,7 @@ public:
int save_in_field(Field *field);
void make_field(Send_field *field);
enum Item_result result_type () const { return INT_RESULT; }
+ unsigned int size_of() { return sizeof(*this);}
};
@@ -349,6 +388,7 @@ public:
Field *tmp_table_field(TABLE *t_arg=(TABLE *)0) { return result_field; }
table_map used_tables() const { return 1; }
virtual void fix_length_and_dec()=0;
+ unsigned int size_of() { return sizeof(*this);}
};
@@ -398,6 +438,7 @@ public:
void save_org_in_field(Field *field) { (*ref)->save_org_in_field(field); }
enum Item_result result_type () const { return (*ref)->result_type(); }
table_map used_tables() const { return (*ref)->used_tables(); }
+ unsigned int size_of() { return sizeof(*this);}
};
@@ -417,6 +458,7 @@ public:
{
return ref->save_in_field(field);
}
+ unsigned int size_of() { return sizeof(*this);}
};
@@ -453,6 +495,7 @@ public:
table_map used_tables() const { return (table_map) 1L; }
bool const_item() const { return 0; }
bool is_null() { return null_value; }
+ unsigned int size_of() { return sizeof(*this);}
};
@@ -463,6 +506,7 @@ public:
Item_buff() :null_value(0) {}
virtual bool cmp(void)=0;
virtual ~Item_buff(); /*line -e1509 */
+ unsigned int size_of() { return sizeof(*this);}
};
class Item_str_buff :public Item_buff
@@ -473,6 +517,7 @@ public:
Item_str_buff(Item *arg) :item(arg),value(arg->max_length) {}
bool cmp(void);
~Item_str_buff(); // Deallocate String:s
+ unsigned int size_of() { return sizeof(*this);}
};
@@ -483,6 +528,7 @@ class Item_real_buff :public Item_buff
public:
Item_real_buff(Item *item_par) :item(item_par),value(0.0) {}
bool cmp(void);
+ unsigned int size_of() { return sizeof(*this);}
};
class Item_int_buff :public Item_buff
@@ -492,6 +538,7 @@ class Item_int_buff :public Item_buff
public:
Item_int_buff(Item *item_par) :item(item_par),value(0) {}
bool cmp(void);
+ unsigned int size_of() { return sizeof(*this);}
};
@@ -508,11 +555,10 @@ public:
buff= (char*) sql_calloc(length=field->pack_length());
}
bool cmp(void);
+ unsigned int size_of() { return sizeof(*this);}
};
extern Item_buff *new_Item_buff(Item *item);
extern Item_result item_cmp_type(Item_result a,Item_result b);
extern Item *resolve_const_item(Item *item,Item *cmp_item);
extern bool field_is_equal_to_item(Field *field,Item *item);
-Item *get_system_var(LEX_STRING name);
-
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 084688f7d3d..10215f406c3 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -38,19 +38,27 @@ longlong Item_func_not::val_int()
return !null_value && value == 0 ? 1 : 0;
}
+/*
+ Convert a constant expression or string to an integer.
+ This is done when comparing DATE's of different formats and
+ also when comparing bigint to strings (in which case the string
+ is converted once to a bigint).
+
+ RESULT VALUES
+ 0 Can't convert item
+ 1 Item was replaced with an integer version of the item
+*/
static bool convert_constant_item(Field *field, Item **item)
{
- if ((*item)->const_item())
+ if ((*item)->const_item() && (*item)->type() != Item::INT_ITEM)
{
- if ((*item)->save_in_field(field))
- return 0;
- if (!((*item)->null_value))
+ if (!(*item)->save_in_field(field) && !((*item)->null_value))
{
Item *tmp=new Item_int_with_ref(field->val_int(), *item);
if (tmp)
*item=tmp;
- return 1;
+ return 1; // Item was replaced
}
}
return 0;
@@ -59,7 +67,7 @@ static bool convert_constant_item(Field *field, Item **item)
void Item_bool_func2::fix_length_and_dec()
{
- max_length=1;
+ max_length=1; // Function returns 0 or 1
/*
As some compare functions are generated after sql_yacc,
@@ -488,6 +496,7 @@ Item_func_ifnull::val_str(String *str)
return res;
}
+
void
Item_func_if::fix_length_and_dec()
{
@@ -496,16 +505,32 @@ Item_func_if::fix_length_and_dec()
decimals=max(args[1]->decimals,args[2]->decimals);
enum Item_result arg1_type=args[1]->result_type();
enum Item_result arg2_type=args[2]->result_type();
- binary=1;
- if (arg1_type == STRING_RESULT || arg2_type == STRING_RESULT)
+ bool null1=args[1]->null_value;
+ bool null2=args[2]->null_value;
+
+ if (null1)
+ {
+ cached_result_type= arg2_type;
+ binary= args[2]->binary;
+ }
+ else if (null2)
+ {
+ cached_result_type= arg1_type;
+ binary= args[1]->binary;
+ }
+ else if (arg1_type == STRING_RESULT || arg2_type == STRING_RESULT)
{
cached_result_type = STRING_RESULT;
binary=args[1]->binary | args[2]->binary;
}
- else if (arg1_type == REAL_RESULT || arg2_type == REAL_RESULT)
- cached_result_type = REAL_RESULT;
else
- cached_result_type=arg1_type; // Should be INT_RESULT
+ {
+ binary=1; // Number
+ if (arg1_type == REAL_RESULT || arg2_type == REAL_RESULT)
+ cached_result_type = REAL_RESULT;
+ else
+ cached_result_type=arg1_type; // Should be INT_RESULT
+ }
}
@@ -551,7 +576,7 @@ Item_func_nullif::fix_length_and_dec()
}
/*
- nullif() returns NULL if arguments are different, else it returns the
+ nullif () returns NULL if arguments are different, else it returns the
first argument.
Note that we have to evaluate the first argument twice as the compare
may have been done with a different type than return value
@@ -1301,7 +1326,7 @@ bool Item_func_like::fix_fields(THD *thd, TABLE_LIST *tlist, Item ** ref)
*last == wild_many)
{
const char* tmp = first + 1;
- for ( ; *tmp != wild_many && *tmp != wild_one && *tmp != escape; tmp++) ;
+ for (; *tmp != wild_many && *tmp != wild_one && *tmp != escape; tmp++) ;
canDoTurboBM = tmp == last;
}
@@ -1642,6 +1667,45 @@ bool Item_func_like::turboBM_matches(const char* text, int text_len) const
}
}
+
+/*
+ Make a logical XOR of the arguments.
+
+ SYNOPSIS
+ val_int()
+
+ DESCRIPTION
+ If either operator is NULL, return NULL.
+
+ NOTE
+ As we don't do any index optimization on XOR this is not going to be
+ very fast to use.
+
+ TODO (low priority)
+ Change this to be optimized as:
+ A XOR B -> (A) == 1 AND (B) <> 1) OR (A <> 1 AND (B) == 1)
+ To be able to do this, we would however first have to extend the MySQL
+ range optimizer to handle OR better.
+*/
+
+longlong Item_cond_xor::val_int()
+{
+ List_iterator<Item> li(list);
+ Item *item;
+ int result=0;
+ null_value=0;
+ while ((item=li++))
+ {
+ result^= (item->val_int() != 0);
+ if (item->null_value)
+ {
+ null_value=1;
+ return 0;
+ }
+ }
+ return (longlong) result;
+}
+
/****************************************************************
Classes and functions for spatial relations
*****************************************************************/
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 08c5a30c57c..c0dcc2bba8f 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -587,6 +587,17 @@ public:
};
+class Item_cond_xor :public Item_cond
+{
+public:
+ Item_cond_xor() :Item_cond() {}
+ Item_cond_xor(Item *i1,Item *i2) :Item_cond(i1,i2) {}
+ enum Functype functype() const { return COND_XOR_FUNC; }
+ longlong val_int();
+ const char *func_name() const { return "xor"; }
+};
+
+
/* Some usefull inline functions */
inline Item *and_conds(Item *a,Item *b)
@@ -601,7 +612,7 @@ inline Item *and_conds(Item *a,Item *b)
/**************************************************************
-Spatial relations
+ Spatial relations
***************************************************************/
class Item_func_spatial_rel :public Item_bool_func2
@@ -609,45 +620,43 @@ class Item_func_spatial_rel :public Item_bool_func2
enum Functype spatial_rel;
public:
Item_func_spatial_rel(Item *a,Item *b, enum Functype sp_rel) :
- Item_bool_func2(a,b) { spatial_rel = sp_rel; }
+ Item_bool_func2(a,b) { spatial_rel = sp_rel; }
longlong val_int();
enum Functype functype() const
{
- switch (spatial_rel)
- {
- case SP_CONTAINS_FUNC:
- return SP_WITHIN_FUNC;
- case SP_WITHIN_FUNC:
- return SP_CONTAINS_FUNC;
- default:
- return spatial_rel;
+ switch (spatial_rel) {
+ case SP_CONTAINS_FUNC:
+ return SP_WITHIN_FUNC;
+ case SP_WITHIN_FUNC:
+ return SP_CONTAINS_FUNC;
+ default:
+ return spatial_rel;
}
}
enum Functype rev_functype() const { return spatial_rel; }
const char *func_name() const
{
- switch (spatial_rel)
- {
- case SP_CONTAINS_FUNC:
- return "contains";
- case SP_WITHIN_FUNC:
- return "within";
- case SP_EQUALS_FUNC:
- return "equals";
- case SP_DISJOINT_FUNC:
- return "disjoint";
- case SP_INTERSECTS_FUNC:
- return "intersects";
- case SP_TOUCHES_FUNC:
- return "touches";
- case SP_CROSSES_FUNC:
- return "crosses";
- case SP_OVERLAPS_FUNC:
- return "overlaps";
- default:
- return "sp_unknown";
+ switch (spatial_rel) {
+ case SP_CONTAINS_FUNC:
+ return "contains";
+ case SP_WITHIN_FUNC:
+ return "within";
+ case SP_EQUALS_FUNC:
+ return "equals";
+ case SP_DISJOINT_FUNC:
+ return "disjoint";
+ case SP_INTERSECTS_FUNC:
+ return "intersects";
+ case SP_TOUCHES_FUNC:
+ return "touches";
+ case SP_CROSSES_FUNC:
+ return "crosses";
+ case SP_OVERLAPS_FUNC:
+ return "overlaps";
+ default:
+ return "sp_unknown";
+ }
}
- }
};
diff --git a/sql/item_create.cc b/sql/item_create.cc
index a41ba1cc526..e4c9a160686 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -32,6 +32,16 @@ Item *create_func_acos(Item* a)
return new Item_func_acos(a);
}
+Item *create_func_aes_encrypt(Item* a, Item* b)
+{
+ return new Item_func_aes_encrypt(a, b);
+}
+
+Item *create_func_aes_decrypt(Item* a, Item* b)
+{
+ return new Item_func_aes_decrypt(a, b);
+}
+
Item *create_func_ascii(Item* a)
{
return new Item_func_ascii(a);
@@ -215,9 +225,14 @@ Item *create_func_char_length(Item* a)
return new Item_func_char_length(a);
}
-Item *create_func_log(Item* a)
+Item *create_func_ln(Item* a)
{
- return new Item_func_log(a);
+ return new Item_func_ln(a);
+}
+
+Item *create_func_log2(Item* a)
+{
+ return new Item_func_log2(a);
}
Item *create_func_log10(Item* a)
@@ -332,6 +347,11 @@ Item *create_func_sin(Item* a)
return new Item_func_sin(a);
}
+Item *create_func_sha(Item* a)
+{
+ return new Item_func_sha(a);
+}
+
Item *create_func_space(Item *a)
{
return new Item_func_repeat(new Item_string(" ",1,default_charset_info),a);
@@ -421,6 +441,17 @@ Item *create_func_cast(Item *a, Item_cast cast_type)
return res;
}
+Item *create_func_is_free_lock(Item* a)
+{
+ current_thd->safe_to_cache_query=0;
+ return new Item_func_is_free_lock(a);
+}
+
+Item *create_func_quote(Item* a)
+{
+ return new Item_func_quote(a);
+}
+
Item *create_func_geometry_from_text(Item* a)
{
return new Item_func_geometry_from_text(a);
diff --git a/sql/item_create.h b/sql/item_create.h
index fd9a856f283..6d9cef04c13 100644
--- a/sql/item_create.h
+++ b/sql/item_create.h
@@ -18,6 +18,8 @@
Item *create_func_abs(Item* a);
Item *create_func_acos(Item* a);
+Item *create_func_aes_encrypt(Item* a, Item* b);
+Item *create_func_aes_decrypt(Item* a, Item* b);
Item *create_func_ascii(Item* a);
Item *create_func_asin(Item* a);
Item *create_func_bin(Item* a);
@@ -25,6 +27,7 @@ Item *create_func_bit_count(Item* a);
Item *create_func_bit_length(Item* a);
Item *create_func_ceiling(Item* a);
Item *create_func_char_length(Item* a);
+Item *create_func_cast(Item *a, Item_cast cast_type);
Item *create_func_connection_id(void);
Item *create_func_conv(Item* a, Item *b, Item *c);
Item *create_func_cos(Item* a);
@@ -51,8 +54,9 @@ Item *create_func_instr(Item* a, Item *b);
Item *create_func_isnull(Item* a);
Item *create_func_lcase(Item* a);
Item *create_func_length(Item* a);
+Item *create_func_ln(Item* a);
Item *create_func_locate(Item* a, Item *b);
-Item *create_func_log(Item* a);
+Item *create_func_log2(Item* a);
Item *create_func_log10(Item* a);
Item *create_func_lpad(Item* a, Item *b, Item *c);
Item *create_func_ltrim(Item* a);
@@ -76,6 +80,7 @@ Item *create_func_rtrim(Item* a);
Item *create_func_sec_to_time(Item* a);
Item *create_func_sign(Item* a);
Item *create_func_sin(Item* a);
+Item *create_func_sha(Item* a);
Item *create_func_soundex(Item* a);
Item *create_func_space(Item *);
Item *create_func_sqrt(Item* a);
@@ -89,6 +94,8 @@ Item *create_func_version(void);
Item *create_func_weekday(Item* a);
Item *create_load_file(Item* a);
Item *create_wait_for_master_pos(Item* a, Item* b);
+Item *create_func_is_free_lock(Item* a);
+Item *create_func_quote(Item* a);
Item *create_func_geometry_from_text(Item* a);
Item *create_func_as_text(Item* a);
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 8728187718c..bd811726b47 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -58,6 +58,41 @@ Item_func::Item_func(List<Item> &list)
list.empty(); // Fields are used
}
+
+/*
+ Resolve references to table column for a function and it's argument
+
+ SYNOPSIS:
+ fix_fields()
+ thd Thread object
+ tables List of all open tables involved in the query
+ ref Pointer to where this object is used. This reference
+ is used if we want to replace this object with another
+ one (for example in the summary functions).
+
+ DESCRIPTION
+ Call fix_fields() for all arguments to the function. The main intention
+ is to allow all Item_field() objects to setup pointers to the table fields.
+
+ Sets as a side effect the following class variables:
+ maybe_null Set if any argument may return NULL
+ binary Set if any of the arguments is binary
+ with_sum_func Set if any of the arguments contains a sum function
+ used_table_cache Set to union of the arguments used table
+
+ str_value.charset If this is a string function, set this to the
+ character set for the first argument.
+
+ If for any item any of the defaults are wrong, then this can
+ be fixed in the fix_length_and_dec() function that is called
+ after this one or by writing a specialized fix_fields() for the
+ item.
+
+ RETURN VALUES
+ 0 ok
+ 1 Got error. Stored with my_error().
+*/
+
bool
Item_func::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{
@@ -79,21 +114,16 @@ Item_func::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
maybe_null=1;
if ((*arg)->binary)
binary=1;
- /*
- Change charset to arg charset if it is not equal to
- default_charset_info. This will work for many cases,
- but generally this should be done more carefull. Each string
- function should have it's own fix_fields() method to correctly
- setup it's result's character set taking in account arguments.
- For example: left(a,b) should take in account only first argument,
- but ignore the second one.
- */
- if ((*arg)->str_value.charset() != default_charset_info)
- str_value.set_charset((*arg)->str_value.charset());
with_sum_func= with_sum_func || (*arg)->with_sum_func;
used_tables_cache|=(*arg)->used_tables();
const_item_cache&= (*arg)->const_item();
}
+ /*
+ Set return character set to first argument if we are returning a
+ string.
+ */
+ if (result_type() == STRING_RESULT)
+ str_value.set_charset((*args)->str_value.charset());
}
fix_length_and_dec();
return 0;
@@ -180,6 +210,36 @@ bool Item_func::eq(const Item *item, bool binary_cmp) const
}
+Field *Item_func::tmp_table_field(TABLE *t_arg)
+{
+ Field *res;
+ LINT_INIT(res);
+
+ if (!t_arg)
+ return result_field;
+ switch (args[0]->result_type()) {
+ case INT_RESULT:
+ if (max_length > 11)
+ res= new Field_longlong(max_length, maybe_null, name, t_arg,
+ unsigned_flag);
+ else
+ res= new Field_long(max_length, maybe_null, name, t_arg,
+ unsigned_flag);
+ break;
+ case REAL_RESULT:
+ res= new Field_double(max_length, maybe_null, name, t_arg, decimals);
+ break;
+ case STRING_RESULT:
+ if (max_length > 255)
+ res= new Field_blob(max_length, maybe_null, name, t_arg, binary);
+ else
+ res= new Field_string(max_length, maybe_null, name, t_arg, binary);
+ break;
+ }
+ return res;
+}
+
+
String *Item_real_func::val_str(String *str)
{
double nr=val();
@@ -451,14 +511,43 @@ void Item_func_abs::fix_length_and_dec()
hybrid_type= args[0]->result_type() == INT_RESULT ? INT_RESULT : REAL_RESULT;
}
+/* Gateway to natural LOG function */
+double Item_func_ln::val()
+{
+ double value=args[0]->val();
+ if ((null_value=(args[0]->null_value || value <= 0.0)))
+ return 0.0;
+ return log(value);
+}
+
+/*
+ Extended but so slower LOG function
+ We have to check if all values are > zero and first one is not one
+ as these are the cases then result is not a number.
+*/
double Item_func_log::val()
{
double value=args[0]->val();
if ((null_value=(args[0]->null_value || value <= 0.0)))
- return 0.0; /* purecov: inspected */
+ return 0.0;
+ if (arg_count == 2)
+ {
+ double value2= args[1]->val();
+ if ((null_value=(args[1]->null_value || value2 <= 0.0 || value == 1.0)))
+ return 0.0;
+ return log(value2) / log(value);
+ }
return log(value);
}
+double Item_func_log2::val()
+{
+ double value=args[0]->val();
+ if ((null_value=(args[0]->null_value || value <= 0.0)))
+ return 0.0;
+ return log(value) / log(2.0);
+}
+
double Item_func_log10::val()
{
double value=args[0]->val();
@@ -891,7 +980,8 @@ longlong Item_func_locate::val_int()
return (longlong) start0+1;
}
skipp:
- if ((l=my_ismbchar(a->charset(),ptr,strend))) ptr+=l;
+ if ((l=my_ismbchar(a->charset(),ptr,strend)))
+ ptr+=l;
else ++ptr;
++start0;
}
@@ -946,7 +1036,8 @@ longlong Item_func_ord::val_int()
{
register const char *str=res->ptr();
register uint32 n=0, l=my_ismbchar(res->charset(),str,str+res->length());
- if (!l) return (longlong)((uchar) *str);
+ if (!l)
+ return (longlong)((uchar) *str);
while (l--)
n=(n<<8)|(uint32)((uchar) *str++);
return (longlong) n;
@@ -1006,6 +1097,7 @@ longlong Item_func_find_in_set::val_int()
null_value=0;
int diff;
+ CHARSET_INFO *charset= find->charset();
if ((diff=buffer->length() - find->length()) >= 0)
{
const char *f_pos=find->ptr();
@@ -1019,8 +1111,7 @@ longlong Item_func_find_in_set::val_int()
const char *pos= f_pos;
while (pos != f_end)
{
- if (my_toupper(find->charset(),*str) !=
- my_toupper(find->charset(),*pos))
+ if (my_toupper(charset,*str) != my_toupper(charset,*pos))
goto not_found;
str++;
pos++;
@@ -1464,20 +1555,15 @@ void item_user_lock_release(ULL *ull)
ull->locked=0;
if (mysql_bin_log.is_open())
{
- THD *thd = current_thd;
- uint save_query_length;
char buf[256];
- String tmp(buf,sizeof(buf), default_charset_info);
- tmp.length(0);
- tmp.append("DO RELEASE_LOCK(\"");
+ const char *command="DO RELEASE_LOCK(\"";
+ String tmp(buf,sizeof(buf), system_charset_info);
+ tmp.copy(command, strlen(command));
tmp.append(ull->key,ull->key_length);
tmp.append("\")");
- save_query_length=thd->query_length;
- thd->query_length=tmp.length();
- Query_log_event qev(thd,tmp.ptr());
+ Query_log_event qev(current_thd,tmp.ptr(), tmp.length());
qev.error_code=0; // this query is always safe to run on slave
mysql_bin_log.write(&qev);
- thd->query_length=save_query_length;
}
if (--ull->count)
pthread_cond_signal(&ull->cond);
@@ -1529,10 +1615,11 @@ void debug_sync_point(const char* lock_name, uint lock_timeout)
thd->ull=0;
}
- /* if the lock has not been aquired by some client, we do not want to
- create an entry for it, since we immediately release the lock. In
- this case, we will not be waiting, but rather, just waste CPU and
- memory on the whole deal
+ /*
+ If the lock has not been aquired by some client, we do not want to
+ create an entry for it, since we immediately release the lock. In
+ this case, we will not be waiting, but rather, just waste CPU and
+ memory on the whole deal
*/
if (!(ull= ((ULL*) hash_search(&hash_user_locks,lock_name,
lock_name_len))))
@@ -1542,8 +1629,10 @@ void debug_sync_point(const char* lock_name, uint lock_timeout)
}
ull->count++;
- /* structure is now initialized. Try to get the lock */
- /* Set up control struct to allow others to abort locks */
+ /*
+ Structure is now initialized. Try to get the lock.
+ Set up control struct to allow others to abort locks
+ */
thd->proc_info="User lock";
thd->mysys_var->current_mutex= &LOCK_user_locks;
thd->mysys_var->current_cond= &ull->cond;
@@ -1630,8 +1719,10 @@ longlong Item_func_get_lock::val_int()
}
ull->count++;
- /* structure is now initialized. Try to get the lock */
- /* Set up control struct to allow others to abort locks */
+ /*
+ Structure is now initialized. Try to get the lock.
+ Set up control struct to allow others to abort locks.
+ */
thd->proc_info="User lock";
thd->mysys_var->current_mutex= &LOCK_user_locks;
thd->mysys_var->current_cond= &ull->cond;
@@ -1672,10 +1763,11 @@ longlong Item_func_get_lock::val_int()
/*
-** Release a user level lock.
-** Returns 1 if lock released
-** 0 if lock wasn't held
-** NULL if no such lock
+ Release a user level lock.
+ Return:
+ 1 if lock released
+ 0 if lock wasn't held
+ (SQL) NULL if no such lock
*/
longlong Item_func_release_lock::val_int()
@@ -1744,6 +1836,7 @@ longlong Item_func_benchmark::val_int()
return 0;
}
+
#define extra_size sizeof(double)
static user_var_entry *get_variable(HASH *hash, LEX_STRING &name,
@@ -1782,7 +1875,7 @@ bool Item_func_set_user_var::fix_fields(THD *thd, TABLE_LIST *tables,
Item **ref)
{
if (!thd)
- thd=current_thd;
+ thd=current_thd; // Should never happen
if (Item_func::fix_fields(thd, tables, ref) ||
!(entry= get_variable(&thd->user_vars, name, 1)))
return 1;
@@ -2008,6 +2101,7 @@ void Item_func_get_user_var::print(String *str)
str->append(')');
}
+
bool Item_func_get_user_var::eq(const Item *item, bool binary_cmp) const
{
/* Assume we don't have rtti */
@@ -2067,6 +2161,7 @@ err:
return 0;
}
+
void Item_func_match::init_search(bool no_order)
{
if (ft_handler)
@@ -2086,14 +2181,14 @@ void Item_func_match::init_search(bool no_order)
return;
}
- String *ft_tmp=0;
+ String *ft_tmp= 0;
char tmp1[FT_QUERY_MAXLEN];
String tmp2(tmp1,sizeof(tmp1),default_charset_info);
// MATCH ... AGAINST (NULL) is meaningless, but possible
if (!(ft_tmp=key_item()->val_str(&tmp2)))
{
- ft_tmp=&tmp2;
+ ft_tmp= &tmp2;
tmp2.set("",0,default_charset_info);
}
@@ -2109,6 +2204,7 @@ void Item_func_match::init_search(bool no_order)
}
}
+
bool Item_func_match::fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
{
List_iterator<Item> li(fields);
@@ -2117,10 +2213,11 @@ bool Item_func_match::fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
maybe_null=1;
join_key=0;
- /* const_item is assumed in quite a bit of places, so it would be difficult
- to remove; If it would ever to be removed, this should include
- modifications to find_best and auto_close as complement to auto_init code
- above.
+ /*
+ const_item is assumed in quite a bit of places, so it would be difficult
+ to remove; If it would ever to be removed, this should include
+ modifications to find_best and auto_close as complement to auto_init code
+ above.
*/
if (Item_func::fix_fields(thd, tlist, ref) || !const_item())
{
@@ -2140,7 +2237,7 @@ bool Item_func_match::fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
}
/* check that all columns come from the same table */
if (count_bits(used_tables_cache) != 1)
- key=NO_SUCH_KEY;
+ key=NO_SUCH_KEY;
const_item_cache=0;
table=((Item_field *)fields.head())->field->table;
table->fulltext_searched=1;
@@ -2154,6 +2251,7 @@ bool Item_func_match::fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
return 0;
}
+
bool Item_func_match::fix_index()
{
List_iterator_fast<Item> li(fields);
@@ -2230,16 +2328,15 @@ err:
return 0;
}
my_printf_error(ER_FT_MATCHING_KEY_NOT_FOUND,
- ER(ER_FT_MATCHING_KEY_NOT_FOUND),MYF(0));
+ ER(ER_FT_MATCHING_KEY_NOT_FOUND),MYF(0));
return 1;
}
+
bool Item_func_match::eq(const Item *item, bool binary_cmp) const
{
- if (item->type() != FUNC_ITEM)
- return 0;
-
- if (func_name() != ((Item_func*)item)->func_name())
+ if (item->type() != FUNC_ITEM ||
+ func_name() != ((Item_func*)item)->func_name())
return 0;
Item_func_match *ifm=(Item_func_match*) item;
@@ -2251,6 +2348,7 @@ bool Item_func_match::eq(const Item *item, bool binary_cmp) const
return 0;
}
+
double Item_func_match::val()
{
if (ft_handler == NULL)
@@ -2260,14 +2358,13 @@ double Item_func_match::val()
{
if (table->file->ft_handler)
return ft_handler->please->get_relevance(ft_handler);
-
join_key=0;
}
if (key == NO_SUCH_KEY)
{
- String *a=concat->val_str(&value);
- if ((null_value= (a==0)))
+ String *a= concat->val_str(&value);
+ if ((null_value= (a == 0)))
return 0;
return ft_handler->please->find_relevance(ft_handler,
(byte *)a->ptr(), a->length());
@@ -2276,26 +2373,86 @@ double Item_func_match::val()
return ft_handler->please->find_relevance(ft_handler, record, 0);
}
+
+longlong Item_func_bit_xor::val_int()
+{
+ ulonglong arg1= (ulonglong) args[0]->val_int();
+ ulonglong arg2= (ulonglong) args[1]->val_int();
+ if ((null_value= (args[0]->null_value || args[1]->null_value)))
+ return 0;
+ return (longlong) (arg1 ^ arg2);
+}
+
+
/***************************************************************************
System variables
- This has to be recoded after we get more than 3 system variables
****************************************************************************/
-Item *get_system_var(LEX_STRING name)
+Item *get_system_var(enum_var_type var_type, LEX_STRING name)
{
- if (!my_strcasecmp(system_charset_info, name.str, "IDENTITY"))
- return new Item_int((char*) "@@IDENTITY",
- current_thd->insert_id(),21);
- if (!my_strcasecmp(system_charset_info, name.str, "VERSION"))
+ if (!my_strcasecmp(name.str,"VERSION"))
return new Item_string("@@VERSION",server_version,
- (uint) strlen(server_version), system_charset_info);
- net_printf(&current_thd->net, ER_UNKNOWN_SYSTEM_VARIABLE, name.str);
+ (uint) strlen(server_version));
+
+ THD *thd=current_thd;
+ Item *item;
+ sys_var *var;
+ char buff[MAX_SYS_VAR_LENGTH+3];
+
+ if (!(var= find_sys_var(name.str)))
+ {
+ net_printf(&thd->net, ER_UNKNOWN_SYSTEM_VARIABLE, name.str);
+ return 0;
+ }
+ if (!(item=var->item(thd, var_type)))
+ return 0; // Impossible
+ thd->safe_to_cache_query=0;
+ buff[0]='@';
+ buff[1]='@';
+ memcpy(buff+2, var->name, var->name_length+1);
+ item->set_name(buff,var->name_length+2); // Will allocate name
+ return item;
+}
+
+
+/*
+ Check a user level lock.
+
+ SYNOPSIS:
+ val_int()
+
+ RETURN VALUES
+ 1 Available
+ 0 Already taken
+ NULL Error
+*/
+
+longlong Item_func_is_free_lock::val_int()
+{
+ String *res=args[0]->val_str(&value);
+ THD *thd=current_thd;
+ ULL *ull;
+ int error=0;
+
+ null_value=0;
+ if (!res || !res->length())
+ {
+ null_value=1;
+ return 0;
+ }
+
+ pthread_mutex_lock(&LOCK_user_locks);
+ ull= (ULL*) hash_search(&hash_user_locks,(byte*) res->ptr(),
+ res->length());
+ pthread_mutex_unlock(&LOCK_user_locks);
+ if (!ull || !ull->locked)
+ return 1;
return 0;
}
/**************************************************************************
-Spatial functions
+ Spatial functions
***************************************************************************/
longlong Item_func_dimension::val_int()
@@ -2319,7 +2476,6 @@ longlong Item_func_numinteriorring::val_int()
Geometry geom;
null_value= (!wkb ||
- args[0]->null_value ||
geom.create_from_wkb(wkb->ptr(),wkb->length()) ||
!GEOM_METHOD_PRESENT(geom,num_interior_ring) ||
geom.num_interior_ring(&num));
@@ -2329,12 +2485,11 @@ longlong Item_func_numinteriorring::val_int()
longlong Item_func_numgeometries::val_int()
{
- uint32 num;
+ uint32 num=0;
String *wkb=args[0]->val_str(&value);
Geometry geom;
null_value= (!wkb ||
- args[0]->null_value ||
geom.create_from_wkb(wkb->ptr(),wkb->length()) ||
!GEOM_METHOD_PRESENT(geom,num_geometries) ||
geom.num_geometries(&num));
@@ -2344,7 +2499,7 @@ longlong Item_func_numgeometries::val_int()
longlong Item_func_numpoints::val_int()
{
- uint32 num;
+ uint32 num=0;
String *wkb=args[0]->val_str(&value);
Geometry geom;
@@ -2360,12 +2515,11 @@ longlong Item_func_numpoints::val_int()
double Item_func_x::val()
{
- double res;
+ double res=0;
String *wkb=args[0]->val_str(&value);
Geometry geom;
null_value= (!wkb ||
- args[0]->null_value ||
geom.create_from_wkb(wkb->ptr(),wkb->length()) ||
!GEOM_METHOD_PRESENT(geom,get_x) ||
geom.get_x(&res));
@@ -2376,12 +2530,11 @@ double Item_func_x::val()
double Item_func_y::val()
{
- double res;
+ double res=0;
String *wkb=args[0]->val_str(&value);
Geometry geom;
null_value= (!wkb ||
- args[0]->null_value ||
geom.create_from_wkb(wkb->ptr(),wkb->length()) ||
!GEOM_METHOD_PRESENT(geom,get_y) ||
geom.get_y(&res));
@@ -2392,12 +2545,11 @@ double Item_func_y::val()
double Item_func_area::val()
{
- double res;
+ double res=0;
String *wkb=args[0]->val_str(&value);
Geometry geom;
null_value= (!wkb ||
- args[0]->null_value ||
geom.create_from_wkb(wkb->ptr(),wkb->length()) ||
!GEOM_METHOD_PRESENT(geom,area) ||
geom.area(&res));
@@ -2408,12 +2560,11 @@ double Item_func_area::val()
double Item_func_glength::val()
{
- double res;
+ double res=0;
String *wkb=args[0]->val_str(&value);
Geometry geom;
null_value= (!wkb ||
- args[0]->null_value ||
geom.create_from_wkb(wkb->ptr(),wkb->length()) ||
!GEOM_METHOD_PRESENT(geom,length) ||
geom.length(&res));
diff --git a/sql/item_func.h b/sql/item_func.h
index 2e61ed87c3c..45427bec017 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -39,7 +39,8 @@ public:
enum Functype { UNKNOWN_FUNC,EQ_FUNC,EQUAL_FUNC,NE_FUNC,LT_FUNC,LE_FUNC,
GE_FUNC,GT_FUNC,FT_FUNC,
LIKE_FUNC,NOTLIKE_FUNC,ISNULL_FUNC,ISNOTNULL_FUNC,
- COND_AND_FUNC,COND_OR_FUNC,BETWEEN,IN_FUNC,INTERVAL_FUNC,
+ COND_AND_FUNC, COND_OR_FUNC, CONX_XOR_FUNC, BETWEEN, IN_FUNC,
+ INTERVAL_FUNC,
SP_EQUALS_FUNC, SP_DISJOINT_FUNC,SP_INTERSECTS_FUNC,
SP_TOUCHES_FUNC,SP_CROSSES_FUNC,SP_WITHIN_FUNC,
SP_CONTAINS_FUNC,SP_OVERLAPS_FUNC,
@@ -126,6 +127,7 @@ public:
}
bool is_null() { (void) val_int(); return null_value; }
friend class udf_handler;
+ Field *tmp_table_field(TABLE *t_arg);
};
@@ -140,13 +142,9 @@ public:
longlong val_int() { return (longlong) val(); }
enum Item_result result_type () const { return REAL_RESULT; }
void fix_length_and_dec() { decimals=NOT_FIXED_DEC; max_length=float_length(decimals); }
- Field *tmp_table_field(TABLE *t_arg)
- {
- if (!t_arg) return result_field;
- return new Field_double(max_length, maybe_null, name,t_arg,decimals);
- }
};
+
class Item_num_func :public Item_func
{
protected:
@@ -174,11 +172,6 @@ class Item_num_op :public Item_func
void fix_length_and_dec() { fix_num_length_and_dec(); find_num_type(); }
void find_num_type(void);
bool is_null() { (void) val(); return null_value; }
- Field *tmp_table_field(TABLE *t_arg)
- {
- if (!t_arg) return result_field;
- return args[0]->result_type() == INT_RESULT ? ((max_length > 11) ? (Field *)new Field_longlong(max_length,maybe_null,name, t_arg,unsigned_flag) : (Field *)new Field_long(max_length,maybe_null,name, t_arg,unsigned_flag)) : (Field *) new Field_double(max_length, maybe_null, name,t_arg,decimals);
- }
};
@@ -194,13 +187,9 @@ public:
String *val_str(String*str);
enum Item_result result_type () const { return INT_RESULT; }
void fix_length_and_dec() {}
- Field *tmp_table_field(TABLE *t_arg)
- {
- if (!t_arg) return result_field;
- return (max_length > 11) ? (Field *)new Field_longlong(max_length,maybe_null,name, t_arg,unsigned_flag) : (Field *)new Field_long(max_length,maybe_null,name, t_arg,unsigned_flag);
- }
};
+
class Item_func_signed :public Item_int_func
{
public:
@@ -211,6 +200,7 @@ public:
{ max_length=args[0]->max_length; unsigned_flag=0; }
};
+
class Item_func_unsigned :public Item_int_func
{
public:
@@ -330,15 +320,35 @@ public:
const char *func_name() const { return "exp"; }
};
+
+class Item_func_ln :public Item_dec_func
+{
+public:
+ Item_func_ln(Item *a) :Item_dec_func(a) {}
+ double val();
+ const char *func_name() const { return "ln"; }
+};
+
+
class Item_func_log :public Item_dec_func
{
public:
Item_func_log(Item *a) :Item_dec_func(a) {}
+ Item_func_log(Item *a,Item *b) :Item_dec_func(a,b) {}
double val();
const char *func_name() const { return "log"; }
};
+class Item_func_log2 :public Item_dec_func
+{
+public:
+ Item_func_log2(Item *a) :Item_dec_func(a) {}
+ double val();
+ const char *func_name() const { return "log2"; }
+};
+
+
class Item_func_log10 :public Item_dec_func
{
public:
@@ -937,7 +947,8 @@ public:
Item_func_match(List<Item> &a, Item *b): Item_real_func(b),
fields(a), table(0), master(0), ft_handler(0),
- concat(0), key(0), join_key(0) {}
+ concat(0), key(0), join_key(0)
+ {}
~Item_func_match()
{
if (!master && ft_handler)
@@ -948,7 +959,8 @@ public:
table->file->ft_handler=0;
table->fulltext_searched=0;
}
- if (concat) delete concat;
+ if (concat)
+ delete concat;
}
enum Functype functype() const { return FT_FUNC; }
void update_used_tables() {}
@@ -1003,6 +1015,7 @@ public:
void fix_length_and_dec() { max_length=10; }
};
+
class Item_func_numinteriorring :public Item_int_func
{
String value;
@@ -1013,6 +1026,7 @@ public:
void fix_length_and_dec() { max_length=10; }
};
+
class Item_func_numpoints :public Item_int_func
{
String value;
@@ -1023,6 +1037,7 @@ public:
void fix_length_and_dec() { max_length=10; }
};
+
class Item_func_area :public Item_real_func
{
String value;
@@ -1032,6 +1047,7 @@ public:
const char *func_name() const { return "area"; }
};
+
class Item_func_glength :public Item_real_func
{
String value;
@@ -1041,22 +1057,46 @@ public:
const char *func_name() const { return "glength"; }
};
+
class Item_func_match_nl :public Item_func_match
{
public:
- Item_func_match_nl(List<Item> &a, Item *b):
- Item_func_match(a,b) { mode=FT_NL; }
+ Item_func_match_nl(List<Item> &a, Item *b)
+ :Item_func_match(a,b)
+ { mode=FT_NL; }
const char *func_name() const { return "match_nl"; }
};
+
class Item_func_match_bool :public Item_func_match
{
public:
- Item_func_match_bool(List<Item> &a, Item *b):
- Item_func_match(a,b) { mode=FT_BOOL; }
+ Item_func_match_bool(List<Item> &a, Item *b)
+ :Item_func_match(a,b)
+ { mode=FT_BOOL; }
const char *func_name() const { return "match_bool"; }
};
+
+class Item_func_bit_xor : public Item_int_func
+{
+public:
+ Item_func_bit_xor(Item *a,Item *b) :Item_int_func(a,b) {}
+ longlong val_int();
+ const char *func_name() const { return "^"; }
+ void fix_length_xor_dec() { unsigned_flag=1; }
+};
+
+class Item_func_is_free_lock :public Item_int_func
+{
+ String value;
+public:
+ Item_func_is_free_lock(Item *a) :Item_int_func(a) {}
+ longlong val_int();
+ const char *func_name() const { return "check_lock"; }
+ void fix_length_and_dec() { decimals=0; max_length=1; maybe_null=1;}
+};
+
/* For type casts */
enum Item_cast
@@ -1064,5 +1104,3 @@ enum Item_cast
ITEM_CAST_BINARY, ITEM_CAST_SIGNED_INT, ITEM_CAST_UNSIGNED_INT,
ITEM_CAST_DATE, ITEM_CAST_TIME, ITEM_CAST_DATETIME
};
-
-Item *create_func_cast(Item *a, Item_cast cast_type);
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index dc9d57b1d9d..2bc9b170fc1 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -34,6 +34,8 @@
#include <openssl/des.h>
#endif /* HAVE_OPENSSL */
#include "md5.h"
+#include "sha1.h"
+#include "my_aes.h"
String empty_string("",default_charset_info);
@@ -42,7 +44,7 @@ uint nr_of_decimals(const char *str)
if ((str=strchr(str,'.')))
{
const char *start= ++str;
- for ( ; my_isdigit(system_charset_info,*str) ; str++) ;
+ for (; my_isdigit(system_charset_info,*str) ; str++) ;
return (uint) (str-start);
}
return 0;
@@ -99,10 +101,117 @@ void Item_func_md5::fix_length_and_dec()
max_length=32;
}
+
+String *Item_func_sha::val_str(String *str)
+{
+ String * sptr= args[0]->val_str(str);
+ if (sptr) /* If we got value different from NULL */
+ {
+ SHA1_CONTEXT context; /* Context used to generate SHA1 hash */
+ /* Temporary buffer to store 160bit digest */
+ uint8 digest[SHA1_HASH_SIZE];
+ sha1_reset(&context); /* We do not have to check for error here */
+ /* No need to check error as the only case would be too long message */
+ sha1_input(&context,(const unsigned char *) sptr->ptr(), sptr->length());
+ /* Ensure that memory is free and we got result */
+ if ( !( str->alloc(SHA1_HASH_SIZE*2) || (sha1_result(&context,digest)) ) )
+ {
+ sprintf((char *) str->ptr(),
+ "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\
+%02x%02x%02x%02x%02x%02x%02x%02x",
+ digest[0], digest[1], digest[2], digest[3],
+ digest[4], digest[5], digest[6], digest[7],
+ digest[8], digest[9], digest[10], digest[11],
+ digest[12], digest[13], digest[14], digest[15],
+ digest[16], digest[17], digest[18], digest[19]);
+
+ str->length((uint) SHA1_HASH_SIZE*2);
+ null_value=0;
+ return str;
+ }
+ }
+ null_value=1;
+ return 0;
+}
+
+void Item_func_sha::fix_length_and_dec()
+{
+ max_length=SHA1_HASH_SIZE*2; // size of hex representation of hash
+}
+
+
+/* Implementation of AES encryption routines */
+
+String *Item_func_aes_encrypt::val_str(String *str)
+{
+ String * sptr = args[0]->val_str(str); // String to encrypt
+ String tmp_value; // required to handle second parameter
+ String * key= args[1]->val_str(&tmp_value); // key
+ int aes_length;
+ if (sptr && key) // we need both arguments to be not NULL
+ {
+ null_value=0;
+ aes_length=my_aes_get_size(sptr->length()); // calculate result length
+
+ if (!str->alloc(aes_length)) // Ensure that memory is free
+ {
+ // finally encrypt directly to allocated buffer.
+ if (my_aes_encrypt(sptr->ptr(),sptr->length(), (char*) str->ptr(),
+ key->ptr(), key->length()) == aes_length)
+ {
+ // We got the expected result length
+ str->length((uint) aes_length);
+ return str;
+ }
+ }
+ }
+ null_value=1;
+ return 0;
+}
+
+
+void Item_func_aes_encrypt::fix_length_and_dec()
+{
+ max_length=my_aes_get_size(args[0]->max_length);
+}
+
+
+String *Item_func_aes_decrypt::val_str(String *str)
+{
+ String * sptr= args[0]->val_str(str); // String to decrypt
+ String tmp_value; // temporary string required for parsing
+ String * key= args[1]->val_str(&tmp_value); // key
+ int length; // original length after decrypt
+ if (sptr && key) // Need to have both arguments not NULL
+ {
+ null_value=0;
+ if (!str->alloc(sptr->length())) // Ensure that memory is free
+ {
+ // finally decrypt directly to allocated buffer.
+ length=my_aes_decrypt(sptr->ptr(), sptr->length(), (char*) str->ptr(),
+ key->ptr(), key->length());
+ if (length >= 0) // if we got correct data data
+ {
+ str->length((uint) length);
+ return str;
+ }
+ }
+ }
+ // Bad parameters. No memory or bad data will all go here
+ null_value=1;
+ return 0;
+}
+
+void Item_func_aes_decrypt::fix_length_and_dec()
+{
+ max_length=args[0]->max_length;
+}
+
+
/*
-** Concatinate args with the following premissess
-** If only one arg which is ok, return value of arg
-** Don't reallocate val_str() if not absolute necessary.
+ Concatenate args with the following premises:
+ If only one arg (which is ok), return value of arg
+ Don't reallocate val_str() if not absolute necessary.
*/
String *Item_func_concat::val_str(String *str)
@@ -127,7 +236,8 @@ String *Item_func_concat::val_str(String *str)
goto null;
if (res2->length() == 0)
continue;
- if (res->length()+res2->length() > max_allowed_packet)
+ if (res->length()+res2->length() >
+ current_thd->variables.max_allowed_packet)
goto null; // Error check
if (res->alloced_length() >= res->length()+res2->length())
{ // Use old buffer
@@ -208,8 +318,7 @@ void Item_func_concat::fix_length_and_dec()
/*
Function des_encrypt() by tonu@spam.ee & monty
Works only if compiled with OpenSSL library support.
- This returns a binary string where first character is
- CHAR(128 | key-number).
+ This returns a binary string where first character is CHAR(128 | key-number).
If one uses a string key key_number is 127.
Encryption result is longer than original by formula:
new_length= org_length + (8-(org_length % 8))+1
@@ -317,7 +426,7 @@ String *Item_func_des_decrypt::val_str(String *str)
{
uint key_number=(uint) (*res)[0] & 127;
// Check if automatic key and that we have privilege to uncompress using it
- if (!(current_thd->master_access & PROCESS_ACL) || key_number > 9)
+ if (!(current_thd->master_access & SUPER_ACL) || key_number > 9)
goto error;
VOID(pthread_mutex_lock(&LOCK_des_key_file));
keyschedule= des_keyschedule[key_number];
@@ -397,7 +506,7 @@ String *Item_func_concat_ws::val_str(String *str)
continue; // Skip NULL and empty string
if (res->length() + sep_str->length() + res2->length() >
- max_allowed_packet)
+ current_thd->variables.max_allowed_packet)
goto null; // Error check
if (res->alloced_length() >=
res->length() + sep_str->length() + res2->length())
@@ -609,7 +718,8 @@ redo:
while (j != search_end)
if (*i++ != *j++) goto skipp;
offset= (int) (ptr-res->ptr());
- if (res->length()-from_length + to_length > max_allowed_packet)
+ if (res->length()-from_length + to_length >
+ current_thd->variables.max_allowed_packet)
goto null;
if (!alloced)
{
@@ -629,7 +739,8 @@ skipp:
#endif /* USE_MB */
do
{
- if (res->length()-from_length + to_length > max_allowed_packet)
+ if (res->length()-from_length + to_length >
+ current_thd->variables.max_allowed_packet)
goto null;
if (!alloced)
{
@@ -689,7 +800,8 @@ String *Item_func_insert::val_str(String *str)
return res; // Wrong param; skip insert
if (length > res->length()-start)
length=res->length()-start;
- if (res->length() - length + res2->length() > max_allowed_packet)
+ if (res->length() - length + res2->length() >
+ current_thd->variables.max_allowed_packet)
goto null; // OOM check
res=copy_if_not_alloced(str,res,res->length());
res->replace(start,length,*res2);
@@ -1595,7 +1707,8 @@ String *Item_func_repeat::val_str(String *str)
if (count == 1) // To avoid reallocs
return res;
length=res->length();
- if (length > max_allowed_packet/count)// Safe length check
+ // Safe length check
+ if (length > current_thd->variables.max_allowed_packet/count)
goto err; // Probably an error
tot_length= length*(uint) count;
if (!(res= alloc_buffer(res,str,&tmp_value,tot_length)))
@@ -1653,7 +1766,8 @@ String *Item_func_rpad::val_str(String *str)
return (res);
}
length_pad= rpad->length();
- if ((ulong) count > max_allowed_packet || args[2]->null_value || !length_pad)
+ if ((ulong) count > current_thd->variables.max_allowed_packet ||
+ args[2]->null_value || !length_pad)
goto err;
if (!(res= alloc_buffer(res,str,&tmp_value,count)))
goto err;
@@ -1712,7 +1826,8 @@ String *Item_func_lpad::val_str(String *str)
return (res);
}
length_pad= lpad->length();
- if (count > max_allowed_packet || args[2]->null_value || !length_pad)
+ if (count > current_thd->variables.max_allowed_packet ||
+ args[2]->null_value || !length_pad)
goto err;
if (res->alloced_length() < count)
@@ -2055,7 +2170,7 @@ String *Item_load_file::val_str(String *str)
/* my_error(ER_TEXTFILE_NOT_READABLE, MYF(0), file_name->c_ptr()); */
goto err;
}
- if (stat_info.st_size > (long) max_allowed_packet)
+ if (stat_info.st_size > (long) current_thd->variables.max_allowed_packet)
{
/* my_error(ER_TOO_LONG_STRING, MYF(0), file_name->c_ptr()); */
goto err;
@@ -2129,7 +2244,7 @@ String* Item_func_export_set::val_str(String* str)
str->append(*yes);
else
str->append(*no);
- if(i != num_set_values - 1)
+ if (i != num_set_values - 1)
str->append(*sep);
}
return str;
@@ -2182,6 +2297,99 @@ String* Item_func_inet_ntoa::val_str(String* str)
return str;
}
+
+/*
+ QUOTE() function returns argument string in single quotes suitable for
+ using in a SQL statement.
+
+ DESCRIPTION
+ Adds a \ before all characters that needs to be escaped in a SQL string.
+ We also escape '^Z' (END-OF-FILE in windows) to avoid probelms when
+ running commands from a file in windows.
+
+ This function is very useful when you want to generate SQL statements
+
+ RETURN VALUES
+ str Quoted string
+ NULL Argument to QUOTE() was NULL or out of memory.
+*/
+
+#define get_esc_bit(mask, num) (1 & (*((mask) + ((num) >> 3))) >> ((num) & 7))
+
+String *Item_func_quote::val_str(String *str)
+{
+ /*
+ Bit mask that has 1 for set for the position of the following characters:
+ 0, \, ' and ^Z
+ */
+
+ static char escmask[32]=
+ {
+ 0x01, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+ char *from, *to, *end, *start;
+ String *arg= args[0]->val_str(str);
+ uint arg_length, new_length;
+ if (!arg) // Null argument
+ goto null;
+ arg_length= arg->length();
+ new_length= arg_length+2; /* for beginning and ending ' signs */
+
+ for (from= (char*) arg->ptr(), end= from + arg_length; from < end; from++)
+ new_length+= get_esc_bit(escmask, *from);
+
+ /*
+ We have to use realloc() instead of alloc() as we want to keep the
+ old result in str
+ */
+ if (str->realloc(new_length))
+ goto null;
+
+ /*
+ As 'arg' and 'str' may be the same string, we must replace characters
+ from the end to the beginning
+ */
+ to= (char*) str->ptr() + new_length - 1;
+ *to--= '\'';
+ for (start= (char*) arg->ptr() ; end-- != start; to--)
+ {
+ /*
+ We can't use the bitmask here as we want to replace \O and ^Z with 0
+ and Z
+ */
+ switch (*end) {
+ case 0:
+ *to--= '0';
+ *to= '\\';
+ break;
+ case '\032':
+ *to--= 'Z';
+ *to= '\\';
+ break;
+ case '\'':
+ case '\\':
+ *to--= *end;
+ *to= '\\';
+ break;
+ default:
+ *to= *end;
+ break;
+ }
+ }
+ *to= '\'';
+ str->length(new_length);
+ return str;
+
+null:
+ null_value= 1;
+ return 0;
+}
+
+
/*******************************************************
General functions for spatial objects
********************************************************/
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index 997d9c8d834..4ac1b118863 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -35,16 +35,6 @@ public:
double val();
enum Item_result result_type () const { return STRING_RESULT; }
void left_right_max_length();
- Field *tmp_table_field(TABLE *t_arg)
- {
- if (!t_arg)
- return result_field;
- return (max_length > 255) ?
- (Field *)new Field_blob(max_length,maybe_null, name,t_arg, binary,
- str_value.charset()) :
- (Field *) new Field_string(max_length,maybe_null, name,t_arg, binary,
- str_value.charset());
- }
};
class Item_func_md5 :public Item_str_func
@@ -57,6 +47,35 @@ public:
const char *func_name() const { return "md5"; }
};
+
+class Item_func_sha :public Item_str_func
+{
+public:
+ Item_func_sha(Item *a) :Item_str_func(a) {}
+ String *val_str(String *);
+ void fix_length_and_dec();
+ const char *func_name() const { return "sha"; }
+};
+
+class Item_func_aes_encrypt :public Item_str_func
+{
+public:
+ Item_func_aes_encrypt(Item *a, Item *b) :Item_str_func(a,b) {}
+ String *val_str(String *);
+ void fix_length_and_dec();
+ const char *func_name() const { return "aes_encrypt"; }
+};
+
+class Item_func_aes_decrypt :public Item_str_func
+{
+public:
+ Item_func_aes_decrypt(Item *a, Item *b) :Item_str_func(a,b) {}
+ String *val_str(String *);
+ void fix_length_and_dec();
+ const char *func_name() const { return "aes_decrypt"; }
+};
+
+
class Item_func_concat :public Item_str_func
{
String tmp_value;
@@ -483,6 +502,15 @@ public:
void fix_length_and_dec() { decimals = 0; max_length=3*8+7; }
};
+class Item_func_quote :public Item_str_func
+{
+public:
+ Item_func_quote(Item *a) :Item_str_func(a) {}
+ const char *func_name() const { return "quote"; }
+ String *val_str(String *);
+ void fix_length_and_dec() { max_length= args[0]->max_length * 2 + 2; }
+};
+
class Item_func_conv_charset :public Item_str_func
{
CHARSET_INFO *conv_charset;
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 809dd65d52b..93ced79005f 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -1045,7 +1045,8 @@ bool Item_sum_count_distinct::setup(THD *thd)
}
}
- init_tree(&tree, min(max_heap_table_size, sortbuff_size/16), 0,
+ init_tree(&tree, min(thd->variables.max_heap_table_size,
+ thd->variables.sortbuff_size/16), 0,
key_length, compare_key, 0, NULL, cmp_arg);
use_tree = 1;
@@ -1055,8 +1056,8 @@ bool Item_sum_count_distinct::setup(THD *thd)
but this has to be handled - otherwise someone can crash
the server with a DoS attack
*/
- max_elements_in_tree = ((key_length) ? max_heap_table_size/key_length :
- 1);
+ max_elements_in_tree = ((key_length) ?
+ thd->variables.max_heap_table_size/key_length : 1);
}
return 0;
}
@@ -1107,7 +1108,7 @@ bool Item_sum_count_distinct::add()
*/
if (tree.elements_in_tree > max_elements_in_tree)
{
- if(tree_to_myisam())
+ if (tree_to_myisam())
return 1;
}
else if (!tree_insert(&tree, table->record[0] + rec_offset, 0, tree.custom_arg))
diff --git a/sql/item_sum.h b/sql/item_sum.h
index 3e67f1e3624..3c86370c189 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -70,6 +70,7 @@ public:
void print(String *str);
void fix_num_length_and_dec();
virtual bool setup(THD *thd) {return 0;}
+ unsigned int size_of() { return sizeof(*this);}
};
@@ -84,6 +85,7 @@ public:
longlong val_int() { return (longlong) val(); } /* Real as default */
String *val_str(String*str);
void reset_field();
+ unsigned int size_of() { return sizeof(*this);}
};
@@ -98,6 +100,7 @@ public:
double val() { return (double) val_int(); }
String *val_str(String*str);
enum Item_result result_type () const { return INT_RESULT; }
+ unsigned int size_of() { return sizeof(*this);}
};
@@ -115,6 +118,7 @@ class Item_sum_sum :public Item_sum_num
void reset_field();
void update_field(int offset);
const char *func_name() const { return "sum"; }
+ unsigned int size_of() { return sizeof(*this);}
};
@@ -137,6 +141,7 @@ class Item_sum_count :public Item_sum_int
void reset_field();
void update_field(int offset);
const char *func_name() const { return "count"; }
+ unsigned int size_of() { return sizeof(*this);}
};
@@ -188,6 +193,7 @@ class Item_sum_count_distinct :public Item_sum_int
void update_field(int offset) { return ; } // Never called
const char *func_name() const { return "count_distinct"; }
bool setup(THD *thd);
+ unsigned int size_of() { return sizeof(*this);}
};
@@ -207,6 +213,7 @@ public:
String *val_str(String*);
void make_field(Send_field *field);
void fix_length_and_dec() {}
+ unsigned int size_of() { return sizeof(*this);}
};
@@ -228,6 +235,7 @@ class Item_sum_avg :public Item_sum_num
Item *result_item(Field *field)
{ return new Item_avg_field(this); }
const char *func_name() const { return "avg"; }
+ unsigned int size_of() { return sizeof(*this);}
};
class Item_sum_std;
@@ -244,6 +252,7 @@ public:
bool is_null() { (void) val_int(); return null_value; }
void make_field(Send_field *field);
void fix_length_and_dec() {}
+ unsigned int size_of() { return sizeof(*this);}
};
class Item_sum_std :public Item_sum_num
@@ -264,6 +273,7 @@ class Item_sum_std :public Item_sum_num
Item *result_item(Field *field)
{ return new Item_std_field(this); }
const char *func_name() const { return "std"; }
+ unsigned int size_of() { return sizeof(*this);}
};
@@ -306,6 +316,7 @@ class Item_sum_hybrid :public Item_sum
void min_max_update_str_field(int offset);
void min_max_update_real_field(int offset);
void min_max_update_int_field(int offset);
+ unsigned int size_of() { return sizeof(*this);}
};
@@ -317,6 +328,7 @@ public:
bool add();
const char *func_name() const { return "min"; }
+ unsigned int size_of() { return sizeof(*this);}
};
@@ -328,6 +340,7 @@ public:
bool add();
const char *func_name() const { return "max"; }
+ unsigned int size_of() { return sizeof(*this);}
};
@@ -343,6 +356,7 @@ class Item_sum_bit :public Item_sum_int
void reset();
longlong val_int();
void reset_field();
+ unsigned int size_of() { return sizeof(*this);}
};
@@ -353,6 +367,7 @@ class Item_sum_or :public Item_sum_bit
bool add();
void update_field(int offset);
const char *func_name() const { return "bit_or"; }
+ unsigned int size_of() { return sizeof(*this);}
};
@@ -363,6 +378,7 @@ class Item_sum_and :public Item_sum_bit
bool add();
void update_field(int offset);
const char *func_name() const { return "bit_and"; }
+ unsigned int size_of() { return sizeof(*this);}
};
/*
@@ -393,6 +409,7 @@ public:
bool add();
void reset_field() {};
void update_field(int offset_arg) {};
+ unsigned int size_of() { return sizeof(*this);}
};
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index 297ff30bd9c..566097893a8 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -703,7 +703,7 @@ String *Item_func_date_format::val_str(String *str)
/* Create the result string */
const char *ptr=format->ptr();
const char *end=ptr+format->length();
- for ( ; ptr != end ; ptr++)
+ for (; ptr != end ; ptr++)
{
if (*ptr != '%' || ptr+1 == end)
str->append(*ptr);
@@ -711,7 +711,7 @@ String *Item_func_date_format::val_str(String *str)
{
switch (*++ptr) {
case 'M':
- if(!l_time.month)
+ if (!l_time.month)
{
null_value=1;
return 0;
@@ -719,7 +719,7 @@ String *Item_func_date_format::val_str(String *str)
str->append(month_names[l_time.month-1]);
break;
case 'b':
- if(!l_time.month)
+ if (!l_time.month)
{
null_value=1;
return 0;
@@ -727,7 +727,7 @@ String *Item_func_date_format::val_str(String *str)
str->append(month_names[l_time.month-1].ptr(),3);
break;
case 'W':
- if(date_or_time)
+ if (date_or_time)
{
null_value=1;
return 0;
@@ -736,7 +736,7 @@ String *Item_func_date_format::val_str(String *str)
str->append(day_names[weekday]);
break;
case 'a':
- if(date_or_time)
+ if (date_or_time)
{
null_value=1;
return 0;
@@ -745,7 +745,7 @@ String *Item_func_date_format::val_str(String *str)
str->append(day_names[weekday].ptr(),3);
break;
case 'D':
- if(date_or_time)
+ if (date_or_time)
{
null_value=1;
return 0;
@@ -811,7 +811,7 @@ String *Item_func_date_format::val_str(String *str)
str->append(intbuff);
break;
case 'j':
- if(date_or_time)
+ if (date_or_time)
{
null_value=1;
return 0;
diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h
index 6d016df6eb7..a45ea159014 100644
--- a/sql/item_timefunc.h
+++ b/sql/item_timefunc.h
@@ -73,6 +73,7 @@ public:
void fix_length_and_dec() { decimals=0; max_length=2; maybe_null=1; }
};
+
class Item_func_monthname :public Item_func_month
{
public:
@@ -175,6 +176,7 @@ public:
const char *func_name() const { return "weekday"; }
enum Item_result result_type () const { return INT_RESULT; }
void fix_length_and_dec() { decimals=0; max_length=1; maybe_null=1; }
+ unsigned int size_of() { return sizeof(*this);}
};
class Item_func_dayname :public Item_func_weekday
@@ -200,6 +202,7 @@ public:
{
decimals=0; max_length=10;
}
+ unsigned int size_of() { return sizeof(*this);}
};
@@ -235,9 +238,9 @@ public:
}
Field *tmp_table_field(TABLE *t_arg)
{
- if (!t_arg) return result_field;
- return new Field_date(maybe_null, name, t_arg);
+ return (!t_arg) ? result_field : new Field_date(maybe_null, name, t_arg);
}
+ unsigned int size_of() { return sizeof(*this);}
};
@@ -253,9 +256,10 @@ public:
}
Field *tmp_table_field(TABLE *t_arg)
{
- if (!t_arg) return result_field;
- return new Field_datetime(maybe_null, name, t_arg);
- }
+ return (!t_arg) ? result_field : new Field_datetime(maybe_null, name,
+ t_arg);
+ }
+ unsigned int size_of() { return sizeof(*this);}
};
@@ -280,9 +284,9 @@ public:
}
Field *tmp_table_field(TABLE *t_arg)
{
- if (!t_arg) return result_field;
- return new Field_time(maybe_null, name, t_arg);
+ return (!t_arg) ? result_field : new Field_time(maybe_null, name, t_arg);
}
+ unsigned int size_of() { return sizeof(*this);}
};
@@ -296,6 +300,7 @@ public:
const char *func_name() const { return "curdate"; }
void fix_length_and_dec(); /* Retrieves curtime */
bool get_date(TIME *res,bool fuzzy_date);
+ unsigned int size_of() { return sizeof(*this);}
};
@@ -317,6 +322,7 @@ public:
const char *func_name() const { return "now"; }
void fix_length_and_dec();
bool get_date(TIME *res,bool fuzzy_date);
+ unsigned int size_of() { return sizeof(*this);}
};
@@ -341,6 +347,7 @@ public:
const char *func_name() const { return "date_format"; }
void fix_length_and_dec();
uint format_length(const String *format);
+ unsigned int size_of() { return sizeof(*this);}
};
@@ -373,11 +380,11 @@ public:
}
Field *tmp_table_field(TABLE *t_arg)
{
- if (!t_arg) return result_field;
- return new Field_time(maybe_null, name, t_arg);
- }
+ return (!t_arg) ? result_field : new Field_time(maybe_null, name, t_arg);
+ }
};
+
enum interval_type { INTERVAL_YEAR, INTERVAL_MONTH, INTERVAL_DAY,
INTERVAL_HOUR, INTERVAL_MINUTE, INTERVAL_SECOND,
INTERVAL_YEAR_MONTH, INTERVAL_DAY_HOUR,
@@ -400,6 +407,7 @@ public:
double val() { return (double) val_int(); }
longlong val_int();
bool get_date(TIME *res,bool fuzzy_date);
+ unsigned int size_of() { return sizeof(*this);}
};
class Item_extract :public Item_int_func
@@ -413,6 +421,7 @@ class Item_extract :public Item_int_func
longlong val_int();
const char *func_name() const { return "extract"; }
void fix_length_and_dec();
+ unsigned int size_of() { return sizeof(*this);}
};
class Item_typecast :public Item_str_func
@@ -437,8 +446,7 @@ public:
}
Field *tmp_table_field(TABLE *t_arg)
{
- if (!t_arg) return result_field;
- return new Field_date(maybe_null, name, t_arg);
+ return (!t_arg) ? result_field : new Field_date(maybe_null, name, t_arg);
}
};
@@ -453,9 +461,8 @@ public:
}
Field *tmp_table_field(TABLE *t_arg)
{
- if (!t_arg) return result_field;
- return new Field_time(maybe_null, name, t_arg);
- }
+ return (!t_arg) ? result_field : new Field_time(maybe_null, name, t_arg);
+ }
};
class Item_datetime_typecast :public Item_typecast
@@ -469,7 +476,7 @@ public:
}
Field *tmp_table_field(TABLE *t_arg)
{
- if (!t_arg) return result_field;
- return new Field_datetime(maybe_null, name, t_arg);
- }
+ return (!t_arg) ? result_field : new Field_datetime(maybe_null, name,
+ t_arg);
+ }
};
diff --git a/sql/item_uniq.h b/sql/item_uniq.h
index e56632e7289..6ab01d55e2f 100644
--- a/sql/item_uniq.h
+++ b/sql/item_uniq.h
@@ -29,6 +29,7 @@ public:
:Item_real_func(list) {}
double val() { return 0.0; }
void fix_length_and_dec() { decimals=0; max_length=6; }
+ unsigned int size_of() { return sizeof(*this);}
};
class Item_sum_unique_users :public Item_sum_num
diff --git a/sql/key.cc b/sql/key.cc
index a5d3d0a65b9..fa09a0a6d44 100644
--- a/sql/key.cc
+++ b/sql/key.cc
@@ -59,7 +59,7 @@ int find_ref_key(TABLE *table,Field *field, uint *key_length)
{
if (key_part->offset == fieldpos)
return(i); /* Use this key */
- *key_length+=key_part->length;
+ *key_length+=key_part->store_length;
}
}
return(-1); /* No key is ok */
diff --git a/sql/lex.h b/sql/lex.h
index cd25c3883fe..83890e75c20 100644
--- a/sql/lex.h
+++ b/sql/lex.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+/* Copyright (C) 2000-2002 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -30,9 +30,9 @@
#endif
/*
-** Symbols are breaked in to separated arrays to allow fieldnames with
-** same name as functions
-** Theese are kept sorted for human lookup (the symbols are hashed)
+ Symbols are broken into separated arrays to allow field names with
+ same name as functions.
+ These are kept sorted for human lookup (the symbols are hashed).
*/
static SYMBOL symbols[] = {
@@ -61,7 +61,6 @@ static SYMBOL symbols[] = {
{ "AVG", SYM(AVG_SYM),0,0},
{ "AVG_ROW_LENGTH", SYM(AVG_ROW_LENGTH),0,0},
{ "AUTO_INCREMENT", SYM(AUTO_INC),0,0},
- { "AUTOCOMMIT", SYM(AUTOCOMMIT),0,0},
{ "BACKUP", SYM(BACKUP_SYM),0,0},
{ "BEGIN", SYM(BEGIN_SYM),0,0},
{ "BERKELEYDB", SYM(BERKELEY_DB_SYM),0,0},
@@ -88,6 +87,7 @@ static SYMBOL symbols[] = {
{ "CHECK", SYM(CHECK_SYM),0,0},
{ "CHECKSUM", SYM(CHECKSUM_SYM),0,0},
{ "CIPHER", SYM(CIPHER_SYM),0,0},
+ { "CLIENT", SYM(CLIENT_SYM),0,0},
{ "CLOSE", SYM(CLOSE_SYM),0,0},
{ "COLLATE", SYM(COLLATE_SYM),0,0},
{ "COLUMN", SYM(COLUMN_SYM),0,0},
@@ -100,6 +100,7 @@ static SYMBOL symbols[] = {
{ "CONSTRAINT", SYM(CONSTRAINT),0,0},
{ "CREATE", SYM(CREATE),0,0},
{ "CROSS", SYM(CROSS),0,0},
+ { "CUBE", SYM(CUBE_SYM),0,0},
{ "CURRENT_DATE", SYM(CURDATE),0,0},
{ "CURRENT_TIME", SYM(CURTIME),0,0},
{ "CURRENT_TIMESTAMP", SYM(NOW_SYM),0,0},
@@ -119,7 +120,6 @@ static SYMBOL symbols[] = {
{ "DELAYED", SYM(DELAYED_SYM),0,0},
{ "DELAY_KEY_WRITE", SYM(DELAY_KEY_WRITE_SYM),0,0},
{ "DELETE", SYM(DELETE_SYM),0,0},
- { "DEMAND", SYM(DEMAND_SYM),0,0},
{ "DESC", SYM(DESC),0,0},
{ "DESCRIBE", SYM(DESCRIBE),0,0},
{ "DIRECTORY", SYM(DIRECTORY_SYM),0,0},
@@ -140,6 +140,7 @@ static SYMBOL symbols[] = {
{ "ENCLOSED", SYM(ENCLOSED),0,0},
{ "ENUM", SYM(ENUM),0,0},
{ "EVENTS", SYM(EVENTS_SYM),0,0},
+ { "EXECUTE", SYM(EXECUTE_SYM),0,0},
{ "EXPLAIN", SYM(DESCRIBE),0,0},
{ "EXISTS", SYM(EXISTS),0,0},
{ "EXTENDED", SYM(EXTENDED_SYM),0,0},
@@ -186,7 +187,6 @@ static SYMBOL symbols[] = {
{ "INNOBASE", SYM(INNOBASE_SYM),0,0},
{ "INNODB", SYM(INNOBASE_SYM),0,0},
{ "INSERT", SYM(INSERT),0,0},
- { "INSERT_ID", SYM(INSERT_ID),0,0},
{ "INSERT_METHOD", SYM(INSERT_METHOD),0,0},
{ "INT", SYM(INT_SYM),0,0},
{ "INTEGER", SYM(INT_SYM),0,0},
@@ -208,7 +208,6 @@ static SYMBOL symbols[] = {
{ "KEYS", SYM(KEYS),0,0},
{ "KILL", SYM(KILL_SYM),0,0},
{ "LAST", SYM(LAST_SYM),0,0},
- { "LAST_INSERT_ID", SYM(LAST_INSERT_ID),0,0},
{ "LEADING", SYM(LEADING),0,0},
{ "LEFT", SYM(LEFT),0,0},
{ "LEVEL", SYM(LEVEL_SYM),0,0},
@@ -261,7 +260,6 @@ static SYMBOL symbols[] = {
{ "NOT", SYM(NOT),0,0},
{ "NULL", SYM(NULL_SYM),0,0},
{ "NUMERIC", SYM(NUMERIC_SYM),0,0},
- { "OFF", SYM(OFF),0,0},
{ "ON", SYM(ON),0,0},
{ "OPEN", SYM(OPEN_SYM),0,0},
{ "OPTIMIZE", SYM(OPTIMIZE),0,0},
@@ -295,6 +293,7 @@ static SYMBOL symbols[] = {
{ "RENAME", SYM(RENAME),0,0},
{ "REPAIR", SYM(REPAIR),0,0},
{ "REPLACE", SYM(REPLACE),0,0},
+ { "REPLICATION", SYM(REPLICATION),0,0},
{ "REPEATABLE", SYM(REPEATABLE_SYM),0,0},
{ "REQUIRE", SYM(REQUIRE_SYM),0,0},
{ "RESET", SYM(RESET_SYM),0,0},
@@ -306,6 +305,7 @@ static SYMBOL symbols[] = {
{ "RIGHT", SYM(RIGHT),0,0},
{ "RLIKE", SYM(REGEXP),0,0}, /* Like in mSQL2 */
{ "ROLLBACK", SYM(ROLLBACK_SYM),0,0},
+ { "ROLLUP", SYM(ROLLUP_SYM),0,0},
{ "ROW", SYM(ROW_SYM),0,0},
{ "ROWS", SYM(ROWS_SYM),0,0},
{ "RTREE", SYM(RTREE_SYM),0,0},
@@ -323,28 +323,14 @@ static SYMBOL symbols[] = {
{ "SMALLINT", SYM(SMALLINT),0,0},
{ "SONAME", SYM(UDF_SONAME_SYM),0,0},
{ "SPATIAL", SYM(SPATIAL_SYM),0,0},
- { "SQL_AUTO_IS_NULL", SYM(SQL_AUTO_IS_NULL),0,0},
{ "SQL_BIG_RESULT", SYM(SQL_BIG_RESULT),0,0},
- { "SQL_BIG_SELECTS", SYM(SQL_BIG_SELECTS),0,0},
- { "SQL_BIG_TABLES", SYM(SQL_BIG_TABLES),0,0},
{ "SQL_BUFFER_RESULT", SYM(SQL_BUFFER_RESULT),0,0},
{ "SQL_CACHE", SYM(SQL_CACHE_SYM), 0, 0},
{ "SQL_CALC_FOUND_ROWS", SYM(SQL_CALC_FOUND_ROWS),0,0},
{ "SQL_ERROR_COUNT", SYM(SQL_ERROR_COUNT),0,0},
- { "SQL_LOG_BIN", SYM(SQL_LOG_BIN),0,0},
- { "SQL_LOG_OFF", SYM(SQL_LOG_OFF),0,0},
- { "SQL_LOG_UPDATE", SYM(SQL_LOG_UPDATE),0,0},
- { "SQL_LOW_PRIORITY_UPDATES", SYM(SQL_LOW_PRIORITY_UPDATES),0,0},
- { "SQL_MAX_JOIN_SIZE",SYM(SQL_MAX_JOIN_SIZE), 0, 0},
{ "SQL_NO_CACHE", SYM(SQL_NO_CACHE_SYM), 0, 0},
- { "SQL_QUERY_CACHE_TYPE",SYM(SQL_QUERY_CACHE_TYPE_SYM), 0, 0},
- { "SQL_QUOTE_SHOW_CREATE",SYM(SQL_QUOTE_SHOW_CREATE), 0, 0},
- { "SQL_SAFE_UPDATES", SYM(SQL_SAFE_UPDATES),0,0},
- { "SQL_SELECT_LIMIT", SYM(SQL_SELECT_LIMIT),0,0},
- { "SQL_SLAVE_SKIP_COUNTER", SYM(SQL_SLAVE_SKIP_COUNTER),0,0},
{ "SQL_SMALL_RESULT", SYM(SQL_SMALL_RESULT),0,0},
- { "SQL_THREAD", SYM(SQL_THREAD),0,0},
- { "SQL_WARNINGS", SYM(SQL_WARNINGS),0,0},
+ { "SQL_THREAD", SYM(SQL_THREAD),0,0},
{ "SSL", SYM(SSL_SYM),0,0},
{ "STRAIGHT_JOIN", SYM(STRAIGHT_JOIN),0,0},
{ "START", SYM(START_SYM),0,0},
@@ -354,6 +340,7 @@ static SYMBOL symbols[] = {
{ "STOP", SYM(STOP_SYM),0,0},
{ "STRIPED", SYM(RAID_STRIPED_SYM),0,0},
{ "SUBJECT", SYM(SUBJECT_SYM),0,0},
+ { "SUPER", SYM(SUPER_SYM),0,0},
{ "TABLE", SYM(TABLE_SYM),0,0},
{ "TABLES", SYM(TABLES),0,0},
{ "TEMPORARY", SYM(TEMPORARY),0,0},
@@ -392,6 +379,7 @@ static SYMBOL symbols[] = {
{ "WRITE", SYM(WRITE_SYM),0,0},
{ "WHEN", SYM(WHEN_SYM),0,0},
{ "WHERE", SYM(WHERE),0,0},
+ { "XOR", SYM(XOR),0,0},
{ "X509", SYM(X509_SYM),0,0},
{ "YEAR", SYM(YEAR_SYM),0,0},
{ "YEAR_MONTH", SYM(YEAR_MONTH_SYM),0,0},
@@ -404,6 +392,8 @@ static SYMBOL sql_functions[] = {
{ "ABS", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_abs)},
{ "ACOS", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_acos)},
{ "ADDDATE", SYM(DATE_ADD_INTERVAL),0,0},
+ { "AES_ENCRYPT", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_aes_encrypt)},
+ { "AES_DECRYPT", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_aes_decrypt)},
{ "AREA", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_area)},
{ "ASCII", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ascii)},
{ "ASIN", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_asin)},
@@ -484,15 +474,19 @@ static SYMBOL sql_functions[] = {
{ "ISCLOSED", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_isclosed)},
{ "ISEMPTY", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_isempty)},
{ "ISNULL", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_isnull)},
+ { "IS_FREE_LOCK", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_is_free_lock)},
+ { "LAST_INSERT_ID", SYM(LAST_INSERT_ID),0,0},
{ "ISSIMPLE", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_issimple)},
{ "LCASE", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_lcase)},
{ "LEAST", SYM(LEAST_SYM),0,0},
{ "LENGTH", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_length)},
+ { "LN", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ln)},
{ "LINEFROMTEXT", SYM(LINEFROMTEXT),0,0},
{ "LINESTRING", SYM(LINESTRING),0,0},
{ "LOAD_FILE", SYM(FUNC_ARG1),0,CREATE_FUNC(create_load_file)},
{ "LOCATE", SYM(LOCATE),0,0},
- { "LOG", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_log)},
+ { "LOG", SYM(LOG_SYM),0,0},
+ { "LOG2", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_log2)},
{ "LOG10", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_log10)},
{ "LOWER", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_lcase)},
{ "LPAD", SYM(FUNC_ARG3),0,CREATE_FUNC(create_func_lpad)},
@@ -533,6 +527,7 @@ static SYMBOL sql_functions[] = {
{ "POW", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_pow)},
{ "POWER", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_pow)},
{ "QUARTER", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_quarter)},
+ { "QUOTE", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_quote)},
{ "RADIANS", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_radians)},
{ "RAND", SYM(RAND),0,0},
{ "RELEASE_LOCK", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_release_lock)},
@@ -546,6 +541,8 @@ static SYMBOL sql_functions[] = {
{ "SUBDATE", SYM(DATE_SUB_INTERVAL),0,0},
{ "SIGN", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sign)},
{ "SIN", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sin)},
+ { "SHA", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sha)},
+ { "SHA1", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sha)},
{ "SOUNDEX", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_soundex)},
{ "SPACE", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_space)},
{ "SQRT", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sqrt)},
@@ -576,5 +573,4 @@ static SYMBOL sql_functions[] = {
{ "X", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_x)},
{ "Y", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_y)},
{ "YEARWEEK", SYM(YEARWEEK),0,0}
-
};
diff --git a/sql/lock.cc b/sql/lock.cc
index db849757741..056ed0fec8f 100644
--- a/sql/lock.cc
+++ b/sql/lock.cc
@@ -28,6 +28,7 @@ TODO:
#include "mysql_priv.h"
#include <hash.h>
+#include <assert.h>
extern HASH open_cache;
@@ -135,7 +136,7 @@ static int lock_external(TABLE **tables,uint count)
if ((error=(*tables)->file->external_lock(thd,lock_type)))
{
- for ( ; i-- ; tables--)
+ for (; i-- ; tables--)
{
(*tables)->file->external_lock(thd, F_UNLCK);
(*tables)->current_lock=F_UNLCK;
@@ -427,6 +428,7 @@ int lock_table_name(THD *thd, TABLE_LIST *table_list)
char key[MAX_DBKEY_LENGTH];
uint key_length;
DBUG_ENTER("lock_table_name");
+ safe_mutex_assert_owner(&LOCK_open);
key_length=(uint) (strmov(strmov(key,table_list->db)+1,table_list->name)
-key)+ 1;
@@ -473,7 +475,7 @@ void unlock_table_name(THD *thd, TABLE_LIST *table_list)
static bool locked_named_table(THD *thd, TABLE_LIST *table_list)
{
- for ( ; table_list ; table_list=table_list->next)
+ for (; table_list ; table_list=table_list->next)
{
if (table_list->table && table_is_used(table_list->table,0))
return 1;
@@ -486,6 +488,7 @@ bool wait_for_locked_table_names(THD *thd, TABLE_LIST *table_list)
{
bool result=0;
DBUG_ENTER("wait_for_locked_table_names");
+ safe_mutex_assert_owner(&LOCK_open);
while (locked_named_table(thd,table_list))
{
diff --git a/sql/log.cc b/sql/log.cc
index 02ebb4348ac..b3ce1226210 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -33,7 +33,6 @@
MYSQL_LOG mysql_log,mysql_update_log,mysql_slow_log,mysql_bin_log;
extern I_List<i_string> binlog_do_db, binlog_ignore_db;
-extern ulong max_binlog_size;
static bool test_if_number(const char *str,
long *res, bool allow_wildcards);
@@ -80,10 +79,11 @@ static int find_uniq_filename(char *name)
DBUG_RETURN(0);
}
-MYSQL_LOG::MYSQL_LOG(): last_time(0), query_start(0),index_file(-1),
- name(0), log_type(LOG_CLOSED),write_error(0),
- inited(0), file_id(1),no_rotate(0),
- need_start_event(1),bytes_written(0)
+
+MYSQL_LOG::MYSQL_LOG()
+ :bytes_written(0), last_time(0), query_start(0), name(0),
+ file_id(1), open_count(1), log_type(LOG_CLOSED), write_error(0), inited(0),
+ no_rotate(0), need_start_event(1)
{
/*
We don't want to intialize LOCK_Log here as the thread system may
@@ -91,8 +91,10 @@ MYSQL_LOG::MYSQL_LOG(): last_time(0), query_start(0),index_file(-1),
*/
index_file_name[0] = 0;
bzero((char*) &log_file,sizeof(log_file));
+ bzero((char*) &index_file, sizeof(index_file));
}
+
MYSQL_LOG::~MYSQL_LOG()
{
if (inited)
@@ -103,15 +105,6 @@ MYSQL_LOG::~MYSQL_LOG()
}
}
-void MYSQL_LOG::set_index_file_name(const char* index_file_name)
-{
- if (index_file_name)
- fn_format(this->index_file_name,index_file_name,mysql_data_home,".index",
- 4);
- else
- this->index_file_name[0] = 0;
-}
-
int MYSQL_LOG::generate_new_name(char *new_name, const char *log_name)
{
@@ -132,12 +125,6 @@ int MYSQL_LOG::generate_new_name(char *new_name, const char *log_name)
return 0;
}
-bool MYSQL_LOG::open_index( int options)
-{
- return (index_file < 0 &&
- (index_file = my_open(index_file_name, options | O_BINARY ,
- MYF(MY_WME))) < 0);
-}
void MYSQL_LOG::init(enum_log_type log_type_arg,
enum cache_type io_cache_type_arg,
@@ -148,33 +135,44 @@ void MYSQL_LOG::init(enum_log_type log_type_arg,
no_auto_events = no_auto_events_arg;
if (!inited)
{
- inited=1;
+ inited= 1;
(void) pthread_mutex_init(&LOCK_log,MY_MUTEX_INIT_SLOW);
(void) pthread_mutex_init(&LOCK_index, MY_MUTEX_INIT_SLOW);
(void) pthread_cond_init(&update_cond, 0);
}
}
-void MYSQL_LOG::close_index()
-{
- if (index_file >= 0)
- {
- my_close(index_file, MYF(0));
- index_file = -1;
- }
-}
-void MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg,
- const char *new_name, enum cache_type io_cache_type_arg,
+/*
+ Open a (new) log file.
+
+ DESCRIPTION
+ - If binary logs, also open the index file and register the new
+ file name in it
+ - When calling this when the file is in use, you must have a locks
+ on LOCK_log and LOCK_index.
+
+ RETURN VALUES
+ 0 ok
+ 1 error
+*/
+
+bool MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg,
+ const char *new_name, const char *index_file_name_arg,
+ enum cache_type io_cache_type_arg,
bool no_auto_events_arg)
{
- MY_STAT tmp_stat;
char buff[512];
- File file= -1;
- bool do_magic;
+ File file= -1, index_file_nr= -1;
int open_flags = O_CREAT | O_APPEND | O_BINARY;
+ DBUG_ENTER("MYSQL_LOG::open");
+ DBUG_PRINT("enter",("log_type: %d",(int) log_type));
+
+ last_time=query_start=0;
+ write_error=0;
+
if (!inited && log_type_arg == LOG_BIN && *fn_ext(log_name))
- no_rotate = 1;
+ no_rotate = 1;
init(log_type_arg,io_cache_type_arg,no_auto_events_arg);
if (!(name=my_strdup(log_name,MYF(MY_WME))))
@@ -189,20 +187,16 @@ void MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg,
else
open_flags |= O_WRONLY;
- if (log_type == LOG_BIN && !index_file_name[0])
- fn_format(index_file_name, name, mysql_data_home, ".index", 6);
-
db[0]=0;
- do_magic = ((log_type == LOG_BIN) && !my_stat(log_file_name,
- &tmp_stat, MYF(0)));
-
+ open_count++;
if ((file=my_open(log_file_name,open_flags,
MYF(MY_WME | ME_WAITTANG))) < 0 ||
init_io_cache(&log_file, file, IO_SIZE, io_cache_type,
my_tell(file,MYF(MY_WME)), 0, MYF(MY_WME | MY_NABP)))
goto err;
- if (log_type == LOG_NORMAL)
+ switch (log_type) {
+ case LOG_NORMAL:
{
char *end;
#ifdef __NT__
@@ -214,8 +208,9 @@ void MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg,
if (my_b_write(&log_file, (byte*) buff,(uint) (end-buff)) ||
flush_io_cache(&log_file))
goto err;
+ break;
}
- else if (log_type == LOG_NEW)
+ case LOG_NEW:
{
time_t skr=time(NULL);
struct tm tm_tmp;
@@ -231,49 +226,98 @@ void MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg,
if (my_b_write(&log_file, (byte*) buff,(uint) strlen(buff)) ||
flush_io_cache(&log_file))
goto err;
+ break;
}
- else if (log_type == LOG_BIN)
+ case LOG_BIN:
{
- bool error;
- if (do_magic)
+ bool write_file_name_to_index_file=0;
+
+ myf opt= MY_UNPACK_FILENAME;
+ if (!index_file_name_arg)
+ {
+ index_file_name_arg= name; // Use same basename for index file
+ opt= MY_UNPACK_FILENAME | MY_REPLACE_EXT;
+ }
+
+ if (!my_b_filelength(&log_file))
{
- if (my_b_write(&log_file, (byte*) BINLOG_MAGIC, 4) ||
- open_index(O_APPEND | O_RDWR | O_CREAT))
+ /*
+ The binary log file was empty (probably newly created)
+ This is the normal case and happens when the user doesn't specify
+ an extension for the binary log files.
+ In this case we write a standard header to it.
+ */
+ if (my_b_write(&log_file, (byte*) BINLOG_MAGIC, BIN_LOG_HEADER_SIZE))
goto err;
- bytes_written += 4;
+ bytes_written += BIN_LOG_HEADER_SIZE;
+ write_file_name_to_index_file=1;
}
+ if (!my_b_inited(&index_file))
+ {
+ /*
+ First open of this class instance
+ Create an index file that will hold all file names uses for logging.
+ Add new entries to the end of it.
+ */
+ fn_format(index_file_name, index_file_name_arg, mysql_data_home,
+ ".index", opt);
+ if ((index_file_nr= my_open(index_file_name,
+ O_RDWR | O_CREAT | O_BINARY ,
+ MYF(MY_WME))) < 0 ||
+ init_io_cache(&index_file, index_file_nr,
+ IO_SIZE, WRITE_CACHE,
+ my_seek(index_file_nr,0L,MY_SEEK_END,MYF(0)),
+ 0, MYF(MY_WME)))
+ goto err;
+ }
+ else
+ {
+ safe_mutex_assert_owner(&LOCK_index);
+ reinit_io_cache(&index_file, WRITE_CACHE, my_b_filelength(&index_file),
+ 0, 0);
+ }
if (need_start_event && !no_auto_events)
{
+ need_start_event=0;
Start_log_event s;
s.set_log_pos(this);
s.write(&log_file);
- need_start_event=0;
}
- flush_io_cache(&log_file);
- pthread_mutex_lock(&LOCK_index);
- error=(my_write(index_file, (byte*) log_file_name, strlen(log_file_name),
- MYF(MY_NABP | MY_WME)) ||
- my_write(index_file, (byte*) "\n", 1, MYF(MY_NABP | MY_WME)));
- pthread_mutex_unlock(&LOCK_index);
- if (error)
- {
- close_index();
+ if (flush_io_cache(&log_file))
goto err;
+
+ if (write_file_name_to_index_file)
+ {
+ /* As this is a new log file, we write the file name to the index file */
+ if (my_b_write(&index_file, (byte*) log_file_name,
+ strlen(log_file_name)) ||
+ my_b_write(&index_file, (byte*) "\n", 1) ||
+ flush_io_cache(&index_file))
+ goto err;
}
+ break;
+ }
+ case LOG_CLOSED: // Impossible
+ DBUG_ASSERT(1);
+ break;
}
- return;
+ DBUG_RETURN(0);
err:
- sql_print_error("Could not use %s for logging (error %d)", log_name,errno);
+ sql_print_error("Could not use %s for logging (error %d)", log_name, errno);
if (file >= 0)
my_close(file,MYF(0));
+ if (index_file_nr >= 0)
+ my_close(index_file_nr,MYF(0));
end_io_cache(&log_file);
- x_free(name); name=0;
+ end_io_cache(&index_file);
+ safeFree(name);
log_type=LOG_CLOSED;
- return;
+ DBUG_RETURN(1);
}
+
int MYSQL_LOG::get_current_log(LOG_INFO* linfo)
{
pthread_mutex_lock(&LOCK_log);
@@ -283,480 +327,569 @@ int MYSQL_LOG::get_current_log(LOG_INFO* linfo)
return 0;
}
-// if log_name is "" we stop at the first entry
-int MYSQL_LOG::find_first_log(LOG_INFO* linfo, const char* log_name,
- bool need_mutex)
+
+/*
+ Move all data up in a file in an filename index file
+
+ SYNOPSIS
+ copy_up_file_and_fill()
+ index_file File to move
+ offset Move everything from here to beginning
+
+ NOTE
+ File will be truncated to be 'offset' shorter or filled up with
+ newlines
+
+ IMPLEMENTATION
+ We do the copy outside of the IO_CACHE as the cache buffers would just
+ make things slower and more complicated.
+ In most cases the copy loop should only do one read.
+
+ RETURN VALUES
+ 0 ok
+*/
+
+static bool copy_up_file_and_fill(IO_CACHE *index_file, my_off_t offset)
{
- if (index_file < 0)
- return LOG_INFO_INVALID;
- int error = 0;
- char* fname = linfo->log_file_name;
- uint log_name_len = (uint) strlen(log_name);
- IO_CACHE io_cache;
-
- // mutex needed because we need to make sure the file pointer does not move
- // from under our feet
- if (need_mutex)
- pthread_mutex_lock(&LOCK_index);
- if (init_io_cache(&io_cache, index_file, IO_SIZE, READ_CACHE, (my_off_t) 0,
- 0, MYF(MY_WME)))
+ int bytes_read;
+ my_off_t init_offset= offset;
+ File file= index_file->file;
+ byte io_buf[IO_SIZE*2];
+ DBUG_ENTER("copy_up_file_and_fill");
+
+ for (;; offset+= bytes_read)
{
- error = LOG_INFO_SEEK;
- goto err;
+ (void) my_seek(file, offset, MY_SEEK_SET, MYF(0));
+ if ((bytes_read= (int) my_read(file, io_buf, sizeof(io_buf), MYF(MY_WME)))
+ < 0)
+ goto err;
+ if (!bytes_read)
+ break; // end of file
+ (void) my_seek(file, offset-init_offset, MY_SEEK_SET, MYF(0));
+ if (my_write(file, (byte*) io_buf, bytes_read, MYF(MY_WME | MY_NABP)))
+ goto err;
}
- for(;;)
+ /* The following will either truncate the file or fill the end with \n' */
+ if (my_chsize(file, offset - init_offset, '\n', MYF(MY_WME)))
+ goto err;
+
+ /* Reset data in old index cache */
+ reinit_io_cache(index_file, READ_CACHE, (my_off_t) 0, 0, 1);
+ DBUG_RETURN(0);
+
+err:
+ DBUG_RETURN(1);
+}
+
+
+/*
+ Find the position in the log-index-file for the given log name
+
+ SYNOPSIS
+ find_log_pos()
+ linfo Store here the found log file name and position to
+ the NEXT log file name in the index file.
+ log_name Filename to find in the index file.
+ Is a null pointer if we want to read the first entry
+ need_mutex Set this to 1 if the parent doesn't already have a
+ lock on LOCK_index
+
+ NOTE
+ On systems without the truncate function the file will end with one ore
+ more empty lines
+
+ RETURN VALUES
+ 0 ok
+ LOG_INFO_EOF End of log-index-file found
+ LOG_INFO_IO Got IO error while reading file
+*/
+
+int MYSQL_LOG::find_log_pos(LOG_INFO *linfo, const char *log_name,
+ bool need_lock)
+{
+ int error= 0;
+ char *fname= linfo->log_file_name;
+ uint log_name_len= log_name ? (uint) strlen(log_name) : 0;
+ DBUG_ENTER("find_log_pos");
+ DBUG_PRINT("enter",("log_name: %s", log_name ? log_name : "NULL"));
+
+ /*
+ Mutex needed because we need to make sure the file pointer does not move
+ from under our feet
+ */
+ if (need_lock)
+ pthread_mutex_lock(&LOCK_index);
+ safe_mutex_assert_owner(&LOCK_index);
+
+ /* As the file is flushed, we can't get an error here */
+ (void) reinit_io_cache(&index_file, READ_CACHE, (my_off_t) 0, 0, 0);
+
+ for (;;)
{
uint length;
- if (!(length=my_b_gets(&io_cache, fname, FN_REFLEN-1)))
+ my_off_t offset= my_b_tell(&index_file);
+ /* If we get 0 or 1 characters, this is the end of the file */
+
+ if ((length= my_b_gets(&index_file, fname, FN_REFLEN)) <= 1)
{
- error = !io_cache.error ? LOG_INFO_EOF : LOG_INFO_IO;
- goto err;
+ /* Did not find the given entry; Return not found or error */
+ error= !index_file.error ? LOG_INFO_EOF : LOG_INFO_IO;
+ break;
}
- // if the log entry matches, empty string matching anything
- if (!log_name_len ||
+ // if the log entry matches, null string matching anything
+ if (!log_name ||
(log_name_len == length-1 && fname[log_name_len] == '\n' &&
!memcmp(fname, log_name, log_name_len)))
{
+ DBUG_PRINT("info",("Found log file entry"));
fname[length-1]=0; // remove last \n
- linfo->index_file_offset = my_b_tell(&io_cache);
+ linfo->index_file_start_offset= offset;
+ linfo->index_file_offset = my_b_tell(&index_file);
break;
}
}
- error = 0;
-err:
- if (need_mutex)
+ if (need_lock)
pthread_mutex_unlock(&LOCK_index);
- end_io_cache(&io_cache);
- return error;
-
+ DBUG_RETURN(error);
}
+/*
+ Find the position in the log-index-file for the given log name
+
+ SYNOPSIS
+ find_next_log()
+ linfo Store here the next log file name and position to
+ the file name after that.
+ need_lock Set this to 1 if the parent doesn't already have a
+ lock on LOCK_index
+
+ NOTE
+ - Before calling this function, one has to call find_log_pos()
+ to set up 'linfo'
+ - Mutex needed because we need to make sure the file pointer does not move
+ from under our feet
+
+ RETURN VALUES
+ 0 ok
+ LOG_INFO_EOF End of log-index-file found
+ LOG_INFO_SEEK Could not allocate IO cache
+ LOG_INFO_IO Got IO error while reading file
+*/
+
int MYSQL_LOG::find_next_log(LOG_INFO* linfo, bool need_lock)
{
- // mutex needed because we need to make sure the file pointer does not move
- // from under our feet
- if (index_file < 0) return LOG_INFO_INVALID;
- int error = 0;
- char* fname = linfo->log_file_name;
- IO_CACHE io_cache;
+ int error= 0;
uint length;
+ char *fname= linfo->log_file_name;
+
if (need_lock)
pthread_mutex_lock(&LOCK_index);
- if (init_io_cache(&io_cache, index_file, IO_SIZE,
- READ_CACHE, (my_off_t) linfo->index_file_offset, 0,
- MYF(MY_WME)))
- {
- error = LOG_INFO_SEEK;
- goto err;
- }
- if (!(length=my_b_gets(&io_cache, fname, FN_REFLEN)))
+ safe_mutex_assert_owner(&LOCK_index);
+
+ /* As the file is flushed, we can't get an error here */
+ (void) reinit_io_cache(&index_file, READ_CACHE, linfo->index_file_offset, 0,
+ 0);
+
+ linfo->index_file_start_offset= linfo->index_file_offset;
+ if ((length=my_b_gets(&index_file, fname, FN_REFLEN)) <= 1)
{
- error = !io_cache.error ? LOG_INFO_EOF : LOG_INFO_IO;
+ error = !index_file.error ? LOG_INFO_EOF : LOG_INFO_IO;
goto err;
}
fname[length-1]=0; // kill /n
- linfo->index_file_offset = my_b_tell(&io_cache);
- error = 0;
+ linfo->index_file_offset = my_b_tell(&index_file);
err:
if (need_lock)
pthread_mutex_unlock(&LOCK_index);
- end_io_cache(&io_cache);
return error;
}
-int MYSQL_LOG::reset_logs(THD* thd)
+/*
+ Delete all logs refered to in the index file
+ Start writing to a new log file. The new index file will only contain
+ this file.
+
+ SYNOPSIS
+ reset_logs()
+ thd Thread
+
+ NOTE
+ If not called from slave thread, write start event to new log
+
+
+ RETURN VALUES
+ 0 ok
+ 1 error
+*/
+
+bool MYSQL_LOG::reset_logs(THD* thd)
{
LOG_INFO linfo;
- int error=0;
+ bool error=0;
const char* save_name;
enum_log_type save_log_type;
+ DBUG_ENTER("reset_logs");
+
+ /*
+ We need to get both locks to be sure that no one is trying to
+ write to the index log file.
+ */
pthread_mutex_lock(&LOCK_log);
- if (find_first_log(&linfo,""))
+ pthread_mutex_lock(&LOCK_index);
+
+ /* Save variables so that we can reopen the log */
+ save_name=name;
+ name=0; // Protect against free
+ save_log_type=log_type;
+ close(0); // Don't close the index file
+
+ /* First delete all old log files */
+
+ if (find_log_pos(&linfo, NullS, 0))
{
error=1;
goto err;
}
- for(;;)
+ for (;;)
{
my_delete(linfo.log_file_name, MYF(MY_WME));
- if (find_next_log(&linfo))
+ if (find_next_log(&linfo, 0))
break;
}
- save_name=name;
- name=0;
- save_log_type=log_type;
- close(1);
- my_delete(index_file_name, MYF(MY_WME));
- if (thd && !thd->slave_thread)
+
+ /* Start logging with a new file */
+ close(1); // Close index file
+ my_delete(index_file_name, MYF(MY_WME)); // Reset (open will update)
+ if (!thd->slave_thread)
need_start_event=1;
- open(save_name,save_log_type,0,io_cache_type,no_auto_events);
- my_free((gptr)save_name,MYF(0));
+ open(save_name, save_log_type, 0, index_file_name,
+ io_cache_type, no_auto_events);
+ my_free((gptr) save_name, MYF(0));
+
err:
+ pthread_mutex_unlock(&LOCK_index);
pthread_mutex_unlock(&LOCK_log);
- return error;
+ DBUG_RETURN(error);
}
+/*
+ Delete the current log file, remove it from index file and start on next
+
+ SYNOPSIS
+ purge_first_log()
+ rli Relay log information
+
+ NOTE
+ - This is only called from the slave-execute thread when it has read
+ all commands from a log and want to switch to a new log.
+ - When this happens, we should never be in an active transaction as
+ a transaction is always written as a single block to the binary log.
+
+ IMPLEMENTATION
+ - Protects index file with LOCK_index
+ - Delete first log file,
+ - Copy all file names after this one to the front of the index file
+ - If the OS has truncate, truncate the file, else fill it with \n'
+ - Read the first file name from the index file and store in rli->linfo
+
+ RETURN VALUES
+ 0 ok
+ LOG_INFO_EOF End of log-index-file found
+ LOG_INFO_SEEK Could not allocate IO cache
+ LOG_INFO_IO Got IO error while reading file
+*/
+
int MYSQL_LOG::purge_first_log(struct st_relay_log_info* rli)
{
- // pre-conditions
- DBUG_ASSERT(is_open());
- DBUG_ASSERT(index_file >= 0);
- DBUG_ASSERT(rli->slave_running == 1);
- DBUG_ASSERT(!strcmp(rli->linfo.log_file_name,rli->relay_log_name));
+ int error;
+ DBUG_ENTER("purge_first_log");
+
/*
+ Test pre-conditions.
+
Assume that we have previously read the first log and
stored it in rli->relay_log_name
*/
+ DBUG_ASSERT(is_open());
+ DBUG_ASSERT(rli->slave_running == 1);
+ DBUG_ASSERT(!strcmp(rli->linfo.log_file_name,rli->relay_log_name));
DBUG_ASSERT(rli->linfo.index_file_offset ==
strlen(rli->relay_log_name) + 1);
- int tmp_fd;
- char* fname, *io_buf;
- int error = 0;
- if (!(fname= (char*) my_malloc(IO_SIZE+FN_REFLEN, MYF(MY_WME))))
- return 1;
+ /* We have already processed the relay log, so it's safe to delete it */
+ my_delete(rli->relay_log_name, MYF(0));
pthread_mutex_lock(&LOCK_index);
- my_seek(index_file,rli->linfo.index_file_offset,
- MY_SEEK_SET, MYF(MY_WME));
- io_buf = fname + FN_REFLEN;
- strxmov(fname,rli->relay_log_name,".tmp",NullS);
-
- if ((tmp_fd = my_open(fname,O_CREAT|O_BINARY|O_RDWR, MYF(MY_WME))) < 0)
+ if (copy_up_file_and_fill(&index_file, rli->linfo.index_file_offset))
{
- error = 1;
+ error= LOG_INFO_IO;
goto err;
}
- for (;;)
- {
- int bytes_read;
- bytes_read = my_read(index_file, (byte*) io_buf, IO_SIZE, MYF(0));
- if (bytes_read < 0) // error
- {
- error=1;
- goto err;
- }
- if (!bytes_read)
- break; // end of file
- // otherwise, we've read something and need to write it out
- if (my_write(tmp_fd, (byte*) io_buf, bytes_read, MYF(MY_WME|MY_NABP)))
- {
- error=1;
- goto err;
- }
- }
-err:
- if (tmp_fd)
- my_close(tmp_fd, MYF(MY_WME));
- if (error)
- my_delete(fname, MYF(0)); // do not report error if the file is not there
- else
- {
- MY_STAT s;
- my_close(index_file, MYF(MY_WME));
- if (!my_stat(rli->relay_log_name,&s,MYF(0)))
- {
- sql_print_error("The first log %s failed to stat during purge",
- rli->relay_log_name);
- error=1;
- goto err;
- }
- if (my_rename(fname,index_file_name,MYF(MY_WME)) ||
- (index_file=my_open(index_file_name,O_BINARY|O_RDWR|O_APPEND,
- MYF(MY_WME)))<0 ||
- my_delete(rli->relay_log_name, MYF(MY_WME)))
- error=1;
-
- pthread_mutex_lock(&rli->log_space_lock);
- rli->log_space_total -= s.st_size;
- pthread_mutex_unlock(&rli->log_space_lock);
- // ok to broadcast after the critical region as there is no risk of
- // the mutex being destroyed by this thread later - this helps save
- // context switches
- pthread_cond_broadcast(&rli->log_space_cond);
-
- if ((error=find_first_log(&rli->linfo,"",0/*no mutex*/)))
- {
- char buff[22];
- sql_print_error("next log error=%d,offset=%s,log=%s",error,
- llstr(rli->linfo.index_file_offset,buff),
- rli->linfo.log_file_name);
- goto err2;
- }
- rli->relay_log_pos = 4;
- strnmov(rli->relay_log_name,rli->linfo.log_file_name,
- sizeof(rli->relay_log_name));
- flush_relay_log_info(rli);
- }
/*
- No need to free io_buf because we allocated both fname and io_buf in
- one malloc()
+ Update the space counter used by all relay logs
+ Ok to broadcast after the critical region as there is no risk of
+ the mutex being destroyed by this thread later - this helps save
+ context switches
*/
+ pthread_mutex_lock(&rli->log_space_lock);
+ rli->log_space_total -= rli->relay_log_pos;
+ pthread_mutex_unlock(&rli->log_space_lock);
+ pthread_cond_broadcast(&rli->log_space_cond);
+
+ /*
+ Read the next log file name from the index file and pass it back to
+ the caller
+ */
+ if ((error=find_log_pos(&rli->linfo, NullS, 0 /*no mutex*/)))
+ {
+ char buff[22];
+ sql_print_error("next log error: %d offset: %s log: %s",
+ error,
+ llstr(rli->linfo.index_file_offset,buff),
+ rli->linfo.log_file_name);
+ goto err;
+ }
+ rli->relay_log_pos = BIN_LOG_HEADER_SIZE;
+ strmake(rli->relay_log_name,rli->linfo.log_file_name,
+ sizeof(rli->relay_log_name)-1);
+
+ /* Store where we are in the new file for the execution thread */
+ flush_relay_log_info(rli);
-err2:
+err:
pthread_mutex_unlock(&LOCK_index);
- my_free(fname, MYF(MY_WME));
- return error;
+ DBUG_RETURN(error);
}
+/*
+ Remove all logs before the given log from disk and from the index file.
+
+ SYNOPSIS
+ purge_logs()
+ thd Thread pointer
+ to_log Delete all log file name before this file. This file is not
+ deleted
+
+ NOTES
+ If any of the logs before the deleted one is in use,
+ only purge logs up to this one.
+
+ RETURN VALUES
+ 0 ok
+ LOG_INFO_PURGE_NO_ROTATE Binary file that can't be rotated
+ LOG_INFO_EOF to_log not found
+*/
+
int MYSQL_LOG::purge_logs(THD* thd, const char* to_log)
{
int error;
- char fname[FN_REFLEN];
- char *p;
- uint fname_len, i;
- bool logs_to_purge_inited = 0, logs_to_keep_inited = 0, found_log = 0;
- DYNAMIC_ARRAY logs_to_purge, logs_to_keep;
- my_off_t purge_offset ;
- LINT_INIT(purge_offset);
- IO_CACHE io_cache;
-
- if (index_file < 0)
- return LOG_INFO_INVALID;
+ LOG_INFO log_info;
+ DBUG_ENTER("purge_logs");
+
if (no_rotate)
- return LOG_INFO_PURGE_NO_ROTATE;
+ DBUG_RETURN(LOG_INFO_PURGE_NO_ROTATE);
+
pthread_mutex_lock(&LOCK_index);
-
- if (init_io_cache(&io_cache,index_file, IO_SIZE*2, READ_CACHE, (my_off_t) 0,
- 0, MYF(MY_WME)))
- {
- error = LOG_INFO_MEM;
+ if ((error=find_log_pos(&log_info, to_log, 0 /*no mutex*/)))
goto err;
- }
- if (my_init_dynamic_array(&logs_to_purge, sizeof(char*), 1024, 1024))
- {
- error = LOG_INFO_MEM;
- goto err;
- }
- logs_to_purge_inited = 1;
-
- if (my_init_dynamic_array(&logs_to_keep, sizeof(char*), 1024, 1024))
- {
- error = LOG_INFO_MEM;
- goto err;
- }
- logs_to_keep_inited = 1;
-
- for (;;)
- {
- my_off_t init_purge_offset= my_b_tell(&io_cache);
- if (!(fname_len=my_b_gets(&io_cache, fname, FN_REFLEN)))
- {
- if(!io_cache.error)
- break;
- error = LOG_INFO_IO;
- goto err;
- }
- fname[--fname_len]=0; // kill \n
- if (!memcmp(fname, to_log, fname_len + 1 ))
- {
- found_log = 1;
- purge_offset = init_purge_offset;
- }
-
- // if one of the logs before the target is in use
- if (!found_log && log_in_use(fname))
- {
- error = LOG_INFO_IN_USE;
- goto err;
- }
-
- if (!(p = sql_memdup(fname, fname_len+1)) ||
- insert_dynamic(found_log ? &logs_to_keep : &logs_to_purge,
- (gptr) &p))
- {
- error = LOG_INFO_MEM;
- goto err;
- }
- }
-
- end_io_cache(&io_cache);
- if (!found_log)
- {
- error = LOG_INFO_EOF;
+ /*
+ File name exists in index file; Delete until we find this file
+ or a file that is used.
+ */
+ if ((error=find_log_pos(&log_info, NullS, 0 /*no mutex*/)))
goto err;
- }
-
- for (i = 0; i < logs_to_purge.elements; i++)
+ while (strcmp(to_log,log_info.log_file_name) &&
+ !log_in_use(log_info.log_file_name))
{
- char* l;
- get_dynamic(&logs_to_purge, (gptr)&l, i);
- if (my_delete(l, MYF(MY_WME)))
- sql_print_error("Error deleting %s during purge", l);
+ /* It's not fatal even if we can't delete a log file */
+ my_delete(log_info.log_file_name, MYF(0));
+ if (find_next_log(&log_info, 0))
+ break;
}
-
+
/*
If we get killed -9 here, the sysadmin would have to edit
the log index file after restart - otherwise, this should be safe
*/
-#ifdef HAVE_FTRUNCATE
- if (ftruncate(index_file,0))
- {
- sql_print_error("Could not truncate the binlog index file \
-during log purge for write");
- error = LOG_INFO_FATAL;
- goto err;
- }
- my_seek(index_file, 0, MY_SEEK_CUR,MYF(MY_WME));
-#else
- my_close(index_file, MYF(MY_WME));
- my_delete(index_file_name, MYF(MY_WME));
- if ((index_file = my_open(index_file_name,
- O_CREAT | O_BINARY | O_RDWR | O_APPEND,
- MYF(MY_WME)))<0)
+
+ if (copy_up_file_and_fill(&index_file, log_info.index_file_start_offset))
{
- sql_print_error("Could not re-open the binlog index file \
-during log purge for write");
- error = LOG_INFO_FATAL;
+ error= LOG_INFO_IO;
goto err;
}
-#endif
-
- for (i = 0; i < logs_to_keep.elements; i++)
- {
- char* l;
- get_dynamic(&logs_to_keep, (gptr)&l, i);
- if (my_write(index_file, (byte*) l, strlen(l), MYF(MY_WME|MY_NABP)) ||
- my_write(index_file, (byte*) "\n", 1, MYF(MY_WME|MY_NABP)))
- {
- error = LOG_INFO_FATAL;
- goto err;
- }
- }
- // now update offsets
- adjust_linfo_offsets(purge_offset);
- error = 0;
+ // now update offsets in index file for running threads
+ adjust_linfo_offsets(log_info.index_file_start_offset);
err:
pthread_mutex_unlock(&LOCK_index);
- if (logs_to_purge_inited)
- delete_dynamic(&logs_to_purge);
- if (logs_to_keep_inited)
- delete_dynamic(&logs_to_keep);
- end_io_cache(&io_cache);
- return error;
+ DBUG_RETURN(error);
}
-// we assume that buf has at least FN_REFLEN bytes alloced
+
+/*
+ Create a new log file name
+
+ SYNOPSIS
+ make_log_name()
+ buf buf of at least FN_REFLEN where new name is stored
+
+ NOTE
+ If file name will be longer then FN_REFLEN it will be truncated
+*/
+
void MYSQL_LOG::make_log_name(char* buf, const char* log_ident)
{
- buf[0] = 0; // In case of error
- if (inited)
+ if (inited) // QQ When is this not true ?
{
- int dir_len = dirname_length(log_file_name);
- int ident_len = (uint) strlen(log_ident);
- if (dir_len + ident_len + 1 > FN_REFLEN)
- return; // protection agains malicious buffer overflow
-
- memcpy(buf, log_file_name, dir_len);
- // copy filename + end null
- memcpy(buf + dir_len, log_ident, ident_len + 1);
+ uint dir_len = dirname_length(log_file_name);
+ if (dir_len > FN_REFLEN)
+ dir_len=FN_REFLEN-1;
+ strnmov(buf, log_file_name, dir_len);
+ strmake(buf+dir_len, log_ident, FN_REFLEN - dir_len);
}
}
-bool MYSQL_LOG::is_active(const char* log_file_name)
+
+/*
+ Check if we are writing/reading to the given log file
+*/
+
+bool MYSQL_LOG::is_active(const char *log_file_name_arg)
{
- return inited && !strcmp(log_file_name, this->log_file_name);
+ return inited && !strcmp(log_file_name, log_file_name_arg);
}
-void MYSQL_LOG::new_file(bool inside_mutex)
+
+/*
+ Start writing to a new log file or reopen the old file
+
+ SYNOPSIS
+ new_file()
+ need_lock Set to 1 (default) if caller has not locked
+ LOCK_log and LOCK_index
+
+ NOTE
+ The new file name is stored last in the index file
+*/
+
+void MYSQL_LOG::new_file(bool need_lock)
{
- if (is_open())
+ char new_name[FN_REFLEN], *new_name_ptr, *old_name;
+ enum_log_type save_log_type;
+
+ if (!is_open())
+ return; // Should never happen
+
+ if (need_lock)
{
- char new_name[FN_REFLEN], *old_name=name;
- if (!inside_mutex)
- VOID(pthread_mutex_lock(&LOCK_log));
+ pthread_mutex_lock(&LOCK_log);
+ pthread_mutex_lock(&LOCK_index);
+ }
+ safe_mutex_assert_owner(&LOCK_log);
+ safe_mutex_assert_owner(&LOCK_index);
+
+ new_name_ptr= name; // Reuse old name if not binlog
- if (!no_rotate)
+ /*
+ Only rotate open logs that are marked non-rotatable
+ (binlog with constant name are non-rotatable)
+ */
+ if (!no_rotate)
+ {
+ if (log_type == LOG_BIN)
{
- /*
- only rotate open logs that are marked non-rotatable
- (binlog with constant name are non-rotatable)
- */
if (generate_new_name(new_name, name))
+ goto end; /* Error; Continue using old log file */
+
+ new_name_ptr=new_name;
+ if (!no_auto_events)
{
- if (!inside_mutex)
- VOID(pthread_mutex_unlock(&LOCK_log));
- return; // Something went wrong
- }
- if (log_type == LOG_BIN)
- {
- if (!no_auto_events)
- {
- /*
- We log the whole file name for log file as the user may decide
- to change base names at some point.
- */
- THD* thd = current_thd;
- Rotate_log_event r(thd,new_name+dirname_length(new_name));
- r.set_log_pos(this);
-
- /*
- This log rotation could have been initiated by a master of
- the slave running with log-bin we set the flag on rotate
- event to prevent inifinite log rotation loop
- */
- if (thd && thd->slave_thread)
- r.flags |= LOG_EVENT_FORCED_ROTATE_F;
- r.write(&log_file);
- bytes_written += r.get_event_len();
- }
- // update needs to be signaled even if there is no rotate event
- // log rotation should give the waiting thread a signal to
- // discover EOF and move on to the next log
- signal_update();
+ /*
+ We log the whole file name for log file as the user may decide
+ to change base names at some point.
+ */
+ THD* thd = current_thd;
+ Rotate_log_event r(thd,new_name+dirname_length(new_name));
+ r.set_log_pos(this);
+
+ /*
+ Becasue this log rotation could have been initiated by a master of
+ the slave running with log-bin, we set the flag on rotate
+ event to prevent inifinite log rotation loop
+ */
+ if (thd->slave_thread)
+ r.flags|= LOG_EVENT_FORCED_ROTATE_F;
+ r.write(&log_file);
+ bytes_written += r.get_event_len();
}
- else
- strmov(new_name, old_name); // Reopen old file name
+ /*
+ Update needs to be signaled even if there is no rotate event
+ log rotation should give the waiting thread a signal to
+ discover EOF and move on to the next log.
+ */
+ signal_update();
}
- name=0;
- close();
- open(old_name, log_type, new_name, io_cache_type, no_auto_events);
- my_free(old_name,MYF(0));
- last_time=query_start=0;
- write_error=0;
- if (!inside_mutex)
- VOID(pthread_mutex_unlock(&LOCK_log));
+ }
+ old_name=name;
+ save_log_type=log_type;
+ name=0; // Don't free name
+ close();
+ open(old_name, save_log_type, new_name_ptr, index_file_name, io_cache_type,
+ no_auto_events);
+ my_free(old_name,MYF(0));
+
+end:
+ if (need_lock)
+ {
+ pthread_mutex_unlock(&LOCK_index);
+ pthread_mutex_unlock(&LOCK_log);
}
}
+
bool MYSQL_LOG::append(Log_event* ev)
{
bool error = 0;
pthread_mutex_lock(&LOCK_log);
DBUG_ASSERT(log_file.type == SEQ_READ_APPEND);
- // Log_event::write() is smart enough to use my_b_write() or
- // my_b_append() depending on the kind of cache we have
+ /*
+ Log_event::write() is smart enough to use my_b_write() or
+ my_b_append() depending on the kind of cache we have.
+ */
if (ev->write(&log_file))
{
error=1;
goto err;
}
bytes_written += ev->get_event_len();
- if ((uint)my_b_append_tell(&log_file) > max_binlog_size)
+ if ((uint) my_b_append_tell(&log_file) > max_binlog_size)
{
- new_file(1);
+ pthread_mutex_lock(&LOCK_index);
+ new_file(0);
+ pthread_mutex_unlock(&LOCK_index);
}
- signal_update();
+
err:
pthread_mutex_unlock(&LOCK_log);
+ signal_update(); // Safe as we don't call close
return error;
}
+
bool MYSQL_LOG::appendv(const char* buf, uint len,...)
{
- bool error = 0;
+ bool error= 0;
va_list(args);
va_start(args,len);
@@ -767,24 +900,32 @@ bool MYSQL_LOG::appendv(const char* buf, uint len,...)
{
if (my_b_append(&log_file,(byte*) buf,len))
{
- error = 1;
- break;
+ error= 1;
+ goto err;
}
bytes_written += len;
} while ((buf=va_arg(args,const char*)) && (len=va_arg(args,uint)));
if ((uint) my_b_append_tell(&log_file) > max_binlog_size)
{
- new_file(1);
+ pthread_mutex_lock(&LOCK_index);
+ new_file(0);
+ pthread_mutex_unlock(&LOCK_index);
}
-
+
+err:
+ pthread_mutex_unlock(&LOCK_log);
if (!error)
signal_update();
- pthread_mutex_unlock(&LOCK_log);
return error;
}
+/*
+ Write to normal (not rotable) log
+ This is the format for the 'normal', 'slow' and 'update' logs.
+*/
+
bool MYSQL_LOG::write(THD *thd,enum enum_server_command command,
const char *format,...)
{
@@ -805,7 +946,7 @@ bool MYSQL_LOG::write(THD *thd,enum enum_server_command command,
if (thd)
{ // Normal thread
if ((thd->options & OPTION_LOG_OFF) &&
- (thd->master_access & PROCESS_ACL))
+ (thd->master_access & SUPER_ACL))
{
VOID(pthread_mutex_unlock(&LOCK_log));
return 0; // No logging
@@ -865,28 +1006,33 @@ bool MYSQL_LOG::write(THD *thd,enum enum_server_command command,
}
+/*
+ Write an event to the binary log
+*/
+
bool MYSQL_LOG::write(Log_event* event_info)
{
- /* In most cases this is only called if 'is_open()' is true */
bool error=0;
- bool should_rotate = 0;
if (!inited) // Can't use mutex if not init
return 0;
- VOID(pthread_mutex_lock(&LOCK_log));
+ pthread_mutex_lock(&LOCK_log);
+
+ /* In most cases this is only called if 'is_open()' is true */
if (is_open())
{
+ bool should_rotate = 0;
THD *thd=event_info->thd;
const char* db = event_info->get_db();
#ifdef USING_TRANSACTIONS
- IO_CACHE *file = ((event_info->get_cache_stmt() && thd) ?
+ IO_CACHE *file = ((event_info->get_cache_stmt()) ?
&thd->transaction.trans_log :
&log_file);
#else
IO_CACHE *file = &log_file;
#endif
if ((thd && !(thd->options & OPTION_BIN_LOG) &&
- (thd->master_access & PROCESS_ACL)) ||
+ (thd->master_access & SUPER_ACL)) ||
(db && !db_ok(db, binlog_do_db, binlog_ignore_db)))
{
VOID(pthread_mutex_unlock(&LOCK_log));
@@ -916,19 +1062,15 @@ bool MYSQL_LOG::write(Log_event* event_info)
if (e.write(file))
goto err;
}
- if (thd && thd->convert_set)
+ if (thd && thd->variables.convert_set)
{
char buf[1024] = "SET CHARACTER SET ";
char* p = strend(buf);
- p = strmov(p, thd->convert_set->name);
- int save_query_length = thd->query_length;
- // just in case somebody wants it later
- thd->query_length = (uint)(p - buf);
- Query_log_event e(thd, buf);
+ p = strmov(p, thd->variables.convert_set->name);
+ Query_log_event e(thd, buf, (ulong)(p - buf));
e.set_log_pos(this);
if (e.write(file))
goto err;
- thd->query_length = save_query_length; // clean up
}
event_info->set_log_pos(this);
if (event_info->write(file) ||
@@ -964,13 +1106,19 @@ err:
}
if (file == &log_file)
signal_update();
+ if (should_rotate)
+ {
+ pthread_mutex_lock(&LOCK_index);
+ new_file(0); // inside mutex
+ pthread_mutex_unlock(&LOCK_index);
+ }
}
- if (should_rotate)
- new_file(1); // inside mutex
- VOID(pthread_mutex_unlock(&LOCK_log));
+
+ pthread_mutex_unlock(&LOCK_log);
return error;
}
+
uint MYSQL_LOG::next_file_id()
{
uint res;
@@ -980,68 +1128,102 @@ uint MYSQL_LOG::next_file_id()
return res;
}
+
/*
Write a cached log entry to the binary log
- We only come here if there is something in the cache.
- 'cache' needs to be reinitialized after this functions returns.
+
+ NOTE
+ - We only come here if there is something in the cache.
+ - The thing in the cache is always a complete transcation
+ - 'cache' needs to be reinitialized after this functions returns.
+
+ IMPLEMENTATION
+ - To support transaction over replication, we wrap the transaction
+ with BEGIN/COMMIT in the binary log.
*/
bool MYSQL_LOG::write(THD *thd, IO_CACHE *cache)
{
VOID(pthread_mutex_lock(&LOCK_log));
- bool error=1;
- if (is_open())
+ if (is_open()) // Should always be true
{
uint length;
- //QQ: this looks like a bug - why READ_CACHE?
- if (reinit_io_cache(cache, READ_CACHE, 0, 0, 0))
+
+ /*
+ Add the "BEGIN" and "COMMIT" in the binlog around transactions
+ which may contain more than 1 SQL statement. If we run with
+ AUTOCOMMIT=1, then MySQL immediately writes each SQL statement to
+ the binlog when the statement has been completed. No need to add
+ "BEGIN" ... "COMMIT" around such statements. Otherwise, MySQL uses
+ thd->transaction.trans_log to cache the SQL statements until the
+ explicit commit, and at the commit writes the contents in .trans_log
+ to the binlog.
+
+ We write the "BEGIN" mark first in the buffer (.trans_log) where we
+ store the SQL statements for a transaction. At the transaction commit
+ we will add the "COMMIT mark and write the buffer to the binlog.
+ */
{
- sql_print_error(ER(ER_ERROR_ON_WRITE), cache->file_name, errno);
- goto err;
+ Query_log_event qinfo(thd, "BEGIN", 5, TRUE);
+ if (qinfo.write(&log_file))
+ goto err;
}
+ /* Read from the file used to cache the queries .*/
+ if (reinit_io_cache(cache, READ_CACHE, 0, 0, 0))
+ goto err;
length=my_b_bytes_in_cache(cache);
do
{
+ /* Write data to the binary log file */
if (my_b_write(&log_file, cache->read_pos, length))
- {
- if (!write_error)
- sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno);
goto err;
- }
cache->read_pos=cache->read_end; // Mark buffer used up
} while ((length=my_b_fill(cache)));
- if (flush_io_cache(&log_file))
+
+ /*
+ We write the command "COMMIT" as the last SQL command in the
+ binlog segment cached for this transaction
+ */
+
{
- if (!write_error)
- sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno);
- goto err;
+ Query_log_event qinfo(thd, "COMMIT", 6, TRUE);
+ if (qinfo.write(&log_file) || flush_io_cache(&log_file))
+ goto err;
}
if (cache->error) // Error on read
{
sql_print_error(ER(ER_ERROR_ON_READ), cache->file_name, errno);
+ write_error=1; // Don't give more errors
goto err;
}
- error = ha_report_binlog_offset_and_commit(thd, log_file_name,
- log_file.pos_in_file);
- if (error)
+ if ((ha_report_binlog_offset_and_commit(thd, log_file_name,
+ log_file.pos_in_file)))
goto err;
+ signal_update();
}
- error=0;
+ VOID(pthread_mutex_unlock(&LOCK_log));
+ return 0;
err:
- if (error)
- write_error=1;
- else
- signal_update();
-
+ if (!write_error)
+ {
+ write_error= 1;
+ sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno);
+ }
VOID(pthread_mutex_unlock(&LOCK_log));
-
- return error;
+ return 1;
}
-/* Write update log in a format suitable for incremental backup */
+/*
+ Write update log in a format suitable for incremental backup
+
+ NOTE
+ - This code should be deleted in MySQL 5,0 as the binary log
+ is a full replacement for the update log.
+
+*/
bool MYSQL_LOG::write(THD *thd,const char *query, uint query_length,
time_t query_start)
@@ -1057,7 +1239,7 @@ bool MYSQL_LOG::write(THD *thd,const char *query, uint query_length,
char buff[80],*end;
end=buff;
if (!(thd->options & OPTION_UPDATE_LOG) &&
- (thd->master_access & PROCESS_ACL))
+ (thd->master_access & SUPER_ACL))
{
VOID(pthread_mutex_unlock(&LOCK_log));
return 0;
@@ -1133,16 +1315,16 @@ bool MYSQL_LOG::write(THD *thd,const char *query, uint query_length,
if (end != buff)
{
*end++=';';
- *end++='\n';
- *end=0;
+ *end='\n';
if (my_b_write(&log_file, (byte*) "SET ",4) ||
- my_b_write(&log_file, (byte*) buff+1,(uint) (end-buff)-1))
+ my_b_write(&log_file, (byte*) buff+1,(uint) (end-buff)))
tmp_errno=errno;
}
if (!query)
{
- query="#adminstrator command";
- query_length=21;
+ end=strxmov(buff, "# administrator command: ",
+ command_name[thd->command], NullS);
+ query_length=(ulong) (end-buff);
}
if (my_b_write(&log_file, (byte*) query,query_length) ||
my_b_write(&log_file, (byte*) ";\n",2) ||
@@ -1163,26 +1345,50 @@ bool MYSQL_LOG::write(THD *thd,const char *query, uint query_length,
return error;
}
+/*
+ Wait until we get a signal that the binary log has been updated
+
+ SYNOPSIS
+ wait_for_update()
+ thd Thread variable
+
+ NOTES
+ One must have a lock on LOCK_log before calling this function.
+ This lock will be freed before return!
+
+ The reason for the above is that for enter_cond() / exit_cond() to
+ work the mutex must be got before enter_cond() but releases before
+ exit_cond().
+ If you don't do it this way, you will get a deadlock in THD::awake()
+*/
+
+
void MYSQL_LOG:: wait_for_update(THD* thd)
{
+ safe_mutex_assert_owner(&LOCK_log);
const char* old_msg = thd->enter_cond(&update_cond, &LOCK_log,
"Slave: waiting for binlog update");
pthread_cond_wait(&update_cond, &LOCK_log);
- // this is not a bug - we unlock the mutex for the caller, and expect him
- // to lock it and then not unlock it upon return. This is a rather odd
- // way of doing things, but this is the cleanest way I could think of to
- // solve the race deadlock caused by THD::awake() first acquiring mysys_var
- // mutex and then the current mutex, while wait_for_update being called with
- // the current mutex already aquired and THD::exit_cond() trying to acquire
- // mysys_var mutex. We do need the mutex to be acquired prior to the
- // invocation of wait_for_update in all cases, so mutex acquisition inside
- // wait_for_update() is not an option
- pthread_mutex_unlock(&LOCK_log);
+ pthread_mutex_unlock(&LOCK_log); // See NOTES
thd->exit_cond(old_msg);
-}
+}
+
+
+/*
+ Close the log file
+
+ SYNOPSIS
+ close()
+ exiting Set to 1 if we should also close the index file
+ This can be set to 0 if we are going to do call open
+ at once after close, in which case we don't want to
+ close the index file.
+*/
void MYSQL_LOG::close(bool exiting)
{ // One can't set log_type here!
+ DBUG_ENTER("MYSQL_LOG::close");
+ DBUG_PRINT("enter",("exiting: %d", (int) exiting));
if (is_open())
{
if (log_type == LOG_BIN && !no_auto_events)
@@ -1196,25 +1402,47 @@ void MYSQL_LOG::close(bool exiting)
if (my_close(log_file.file,MYF(0)) < 0 && ! write_error)
{
write_error=1;
- sql_print_error(ER(ER_ERROR_ON_WRITE),name,errno);
+ sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno);
}
}
- if (exiting && index_file >= 0)
+
+ /*
+ The following test is needed even if is_open() is not set, as we may have
+ called a not complete close earlier and the index file is still open.
+ */
+
+ if (exiting && my_b_inited(&index_file))
{
- if (my_close(index_file,MYF(0)) < 0 && ! write_error)
+ end_io_cache(&index_file);
+ if (my_close(index_file.file, MYF(0)) < 0 && ! write_error)
{
- write_error=1;
- sql_print_error(ER(ER_ERROR_ON_WRITE),name,errno);
+ write_error= 1;
+ sql_print_error(ER(ER_ERROR_ON_WRITE), index_file_name, errno);
}
- index_file=-1;
- log_type=LOG_CLOSED;
}
+ log_type= LOG_CLOSED;
safeFree(name);
+ DBUG_VOID_RETURN;
}
- /* Check if a string is a valid number */
- /* Output: TRUE -> number */
+/*
+ Check if a string is a valid number
+
+ SYNOPSIS
+ test_if_number()
+ str String to test
+ res Store value here
+ allow_wildcards Set to 1 if we should ignore '%' and '_'
+
+ NOTE
+ For the moment the allow_wildcards argument is not used
+ Should be move to some other file.
+
+ RETURN VALUES
+ 1 String is a number
+ 0 Error
+*/
static bool test_if_number(register const char *str,
long *res, bool allow_wildcards)
@@ -1285,7 +1513,6 @@ void sql_print_error(const char *format,...)
}
-
void sql_perror(const char *message)
{
#ifdef HAVE_STRERROR
diff --git a/sql/log_event.cc b/sql/log_event.cc
index cd116f867c2..23622bc0141 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -31,9 +31,9 @@ inline int my_b_safe_write(IO_CACHE* file, const byte *buf,
{
/*
Sasha: We are not writing this with the ? operator to avoid hitting
- a possible compiler bug. At least gcc 2.95 cannot deal with
- several layers of ternary operators that evaluated comma(,) operator
- expressions inside - I do have a test case if somebody wants it
+ a possible compiler bug. At least gcc 2.95 cannot deal with
+ several layers of ternary operators that evaluated comma(,) operator
+ expressions inside - I do have a test case if somebody wants it
*/
if (file->type == SEQ_READ_APPEND)
return my_b_append(file, buf,len);
@@ -80,7 +80,7 @@ static void pretty_print_str(String* packet, char* str, int len)
while (str < end)
{
char c;
- switch((c=*str++)) {
+ switch ((c=*str++)) {
case '\n': packet->append( "\\n"); break;
case '\r': packet->append( "\\r"); break;
case '\\': packet->append( "\\\\"); break;
@@ -113,8 +113,7 @@ static inline char* slave_load_file_stem(char*buf, uint file_id,
const char* Log_event::get_type_str()
{
- switch(get_type_code())
- {
+ switch(get_type_code()) {
case START_EVENT: return "Start";
case STOP_EVENT: return "Stop";
case QUERY_EVENT: return "Query";
@@ -132,10 +131,9 @@ 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)
+ :exec_time(0), flags(flags_arg), cached_event_len(0),
+ temp_buf(0), thd(thd_arg)
{
if (thd)
{
@@ -151,6 +149,15 @@ Log_event::Log_event(THD* thd_arg, uint16 flags_arg):
}
}
+/*
+ Delete all temporary files used for SQL_LOAD.
+
+ TODO
+ - When we get a 'server start' event, we should only remove
+ the files associated with the server id that just started.
+ Easily fixable by adding server_id as a prefix to the log files.
+*/
+
static void cleanup_load_tmpdir()
{
MY_DIR *dirp;
@@ -159,11 +166,11 @@ static void cleanup_load_tmpdir()
if (!(dirp=my_dir(slave_load_tmpdir,MYF(MY_WME))))
return;
- for (i=0;i<(uint)dirp->number_off_files;i++)
+ for (i=0 ; i < (uint)dirp->number_off_files; i++)
{
file=dirp->dir_entry+i;
- if (!memcmp(file->name,"SQL_LOAD-",9))
- my_delete(file->name,MYF(MY_WME));
+ if (is_prefix(file->name,"SQL_LOAD-"))
+ my_delete(file->name, MYF(0));
}
my_dirend(dirp);
@@ -171,8 +178,8 @@ static void cleanup_load_tmpdir()
#endif
-Log_event::Log_event(const char* buf, bool old_format):
- cached_event_len(0),temp_buf(0)
+Log_event::Log_event(const char* buf, bool old_format)
+ :cached_event_len(0), temp_buf(0)
{
when = uint4korr(buf);
server_id = uint4korr(buf + SERVER_ID_OFFSET);
@@ -196,7 +203,7 @@ Log_event::Log_event(const char* buf, bool old_format):
int Log_event::exec_event(struct st_relay_log_info* rli)
{
- if (rli)
+ if (rli) // QQ When is this not true ?
{
rli->inc_pos(get_event_len(),log_pos);
DBUG_ASSERT(rli->sql_thd != 0);
@@ -217,9 +224,9 @@ void Query_log_event::pack_info(String* packet)
tmp.length(0);
if (db && db_len)
{
- tmp.append("use ");
+ tmp.append("use `", 5);
tmp.append(db, db_len);
- tmp.append("; ", 2);
+ tmp.append("`; ", 3);
}
if (query && q_len)
@@ -246,7 +253,7 @@ void Load_log_event::pack_info(String* packet)
char buf[256];
String tmp(buf, sizeof(buf), system_charset_info);
tmp.length(0);
- if(db && db_len)
+ if (db && db_len)
{
tmp.append("use ");
tmp.append(db, db_len);
@@ -256,9 +263,9 @@ void Load_log_event::pack_info(String* packet)
tmp.append("LOAD DATA INFILE '");
tmp.append(fname, fname_len);
tmp.append("' ", 2);
- if(sql_ex.opt_flags && REPLACE_FLAG )
+ if (sql_ex.opt_flags && REPLACE_FLAG )
tmp.append(" REPLACE ");
- else if(sql_ex.opt_flags && IGNORE_FLAG )
+ else if (sql_ex.opt_flags && IGNORE_FLAG )
tmp.append(" IGNORE ");
tmp.append("INTO TABLE ");
@@ -303,9 +310,9 @@ void Load_log_event::pack_info(String* packet)
uint i;
const char* field = fields;
tmp.append(" (");
- for(i = 0; i < num_fields; i++)
+ for (i = 0; i < num_fields; i++)
{
- if(i)
+ if (i)
tmp.append(" ,");
tmp.append( field);
@@ -319,24 +326,22 @@ void Load_log_event::pack_info(String* packet)
void Rotate_log_event::pack_info(String* packet)
{
- char buf1[256];
+ char buf1[256], buf[22];
String tmp(buf1, sizeof(buf1), system_charset_info);
tmp.length(0);
- char buf[22];
tmp.append(new_log_ident, ident_len);
tmp.append(";pos=");
tmp.append(llstr(pos,buf));
- if(flags & LOG_EVENT_FORCED_ROTATE_F)
+ if (flags & LOG_EVENT_FORCED_ROTATE_F)
tmp.append("; forced by master");
net_store_data(packet, tmp.ptr(), tmp.length());
}
void Intvar_log_event::pack_info(String* packet)
{
- char buf1[256];
+ char buf1[256], buf[22];
String tmp(buf1, sizeof(buf1), system_charset_info);
tmp.length(0);
- char buf[22];
tmp.append(get_var_type_name());
tmp.append('=');
tmp.append(llstr(val, buf));
@@ -345,14 +350,14 @@ void Intvar_log_event::pack_info(String* packet)
void Slave_log_event::pack_info(String* packet)
{
- char buf1[256];
+ char buf1[256], buf[22], *end;
String tmp(buf1, sizeof(buf1), system_charset_info);
tmp.length(0);
- char buf[22];
tmp.append("host=");
tmp.append(master_host);
tmp.append(",port=");
- tmp.append(llstr(master_port,buf));
+ end= int10_to_str((long) master_port, buf, 10);
+ tmp.append(buf, (uint32) (end-buf));
tmp.append(",log=");
tmp.append(master_log);
tmp.append(",pos=");
@@ -390,18 +395,21 @@ int Log_event::net_send(THD* thd, const char* log_name, my_off_t pos)
return my_net_write(&thd->net, (char*) packet->ptr(), packet->length());
}
-#endif
+#endif /* MYSQL_CLIENT */
+
int Query_log_event::write(IO_CACHE* file)
{
return query ? Log_event::write(file) : -1;
}
+
int Log_event::write(IO_CACHE* file)
{
return (write_header(file) || write_data(file)) ? -1 : 0;
}
+
int Log_event::write_header(IO_CACHE* file)
{
char buf[LOG_EVENT_HEADER_LEN];
@@ -427,54 +435,65 @@ int Log_event::read_log_event(IO_CACHE* file, String* packet,
pthread_mutex_t* log_lock)
{
ulong data_len;
+ int result=0;
char buf[LOG_EVENT_HEADER_LEN];
+ DBUG_ENTER("read_log_event");
+
if (log_lock)
pthread_mutex_lock(log_lock);
if (my_b_read(file, (byte*) buf, sizeof(buf)))
{
- if (log_lock) pthread_mutex_unlock(log_lock);
- // if the read hits eof, we must report it as eof
- // so the caller will know it can go into cond_wait to be woken up
- // on the next update to the log
- if(!file->error) return LOG_READ_EOF;
- return file->error > 0 ? LOG_READ_TRUNC: LOG_READ_IO;
+ /*
+ If the read hits eof, we must report it as eof so the caller
+ will know it can go into cond_wait to be woken up on the next
+ update to the log.
+ */
+ DBUG_PRINT("error",("file->error: %d", file->error));
+ if (!file->error)
+ result= LOG_READ_EOF;
+ else
+ result= (file->error > 0 ? LOG_READ_TRUNC : LOG_READ_IO);
+ goto end;
}
- data_len = uint4korr(buf + EVENT_LEN_OFFSET);
- if (data_len < LOG_EVENT_HEADER_LEN || data_len > max_allowed_packet)
+ data_len= uint4korr(buf + EVENT_LEN_OFFSET);
+ if (data_len < LOG_EVENT_HEADER_LEN ||
+ data_len > current_thd->variables.max_allowed_packet)
{
- if (log_lock) pthread_mutex_unlock(log_lock);
- return (data_len < LOG_EVENT_HEADER_LEN) ? LOG_READ_BOGUS :
- LOG_READ_TOO_LARGE;
+ DBUG_PRINT("error",("data_len: %ld", data_len));
+ result= ((data_len < LOG_EVENT_HEADER_LEN) ? LOG_READ_BOGUS :
+ LOG_READ_TOO_LARGE);
+ goto end;
}
packet->append(buf, sizeof(buf));
- data_len -= LOG_EVENT_HEADER_LEN;
+ data_len-= LOG_EVENT_HEADER_LEN;
if (data_len)
{
if (packet->append(file, data_len))
{
- if(log_lock)
- pthread_mutex_unlock(log_lock);
- // here we should never hit eof in a non-error condtion
- // eof means we are reading the event partially, which should
- // never happen
- return file->error >= 0 ? LOG_READ_TRUNC: LOG_READ_IO;
+ /*
+ Here we should never hit EOF in a non-error condition.
+ EOF means we are reading the event partially, which should
+ never happen.
+ */
+ result= file->error >= 0 ? LOG_READ_TRUNC: LOG_READ_IO;
+ /* Implicit goto end; */
}
}
- if (log_lock) pthread_mutex_unlock(log_lock);
- return 0;
+
+end:
+ if (log_lock)
+ pthread_mutex_unlock(log_lock);
+ DBUG_RETURN(result);
}
#endif // MYSQL_CLIENT
#ifndef MYSQL_CLIENT
-#define UNLOCK_MUTEX if(log_lock) pthread_mutex_unlock(log_lock);
+#define UNLOCK_MUTEX if (log_lock) pthread_mutex_unlock(log_lock);
+#define LOCK_MUTEX if (log_lock) pthread_mutex_lock(log_lock);
+#define max_allowed_packet current_thd->variables.max_allowed_packet
#else
#define UNLOCK_MUTEX
-#endif
-
-#ifndef MYSQL_CLIENT
-#define LOCK_MUTEX if(log_lock) pthread_mutex_lock(log_lock);
-#else
#define LOCK_MUTEX
#endif
@@ -488,19 +507,19 @@ Log_event* Log_event::read_log_event(IO_CACHE* file, bool old_format)
#endif
{
char head[LOG_EVENT_HEADER_LEN];
- uint header_size = old_format ? OLD_HEADER_LEN :
- LOG_EVENT_HEADER_LEN;
+ uint header_size= old_format ? OLD_HEADER_LEN : LOG_EVENT_HEADER_LEN;
+
LOCK_MUTEX;
- if (my_b_read(file, (byte *) head, header_size ))
+ if (my_b_read(file, (byte *) head, header_size))
{
UNLOCK_MUTEX;
return 0;
}
uint data_len = uint4korr(head + EVENT_LEN_OFFSET);
- char* buf = 0;
- const char* error = 0;
- Log_event* res = 0;
+ char *buf= 0;
+ const char *error= 0;
+ Log_event *res= 0;
if (data_len > max_allowed_packet)
{
@@ -522,14 +541,14 @@ Log_event* Log_event::read_log_event(IO_CACHE* file, bool old_format)
}
buf[data_len] = 0;
memcpy(buf, head, header_size);
- if (my_b_read(file, (byte*) buf + header_size,
- data_len - header_size))
+ if (my_b_read(file, (byte*) buf + header_size, data_len - header_size))
{
error = "read error";
goto err;
}
if ((res = read_log_event(buf, data_len, &error, old_format)))
res->register_temp_buf(buf);
+
err:
UNLOCK_MUTEX;
if (error)
@@ -541,17 +560,20 @@ data_len=%d,event_type=%d",error,data_len,head[EVENT_TYPE_OFFSET]);
return res;
}
+
Log_event* Log_event::read_log_event(const char* buf, int event_len,
const char **error, bool old_format)
{
if (event_len < EVENT_LEN_OFFSET ||
- (uint)event_len != uint4korr(buf+EVENT_LEN_OFFSET))
+ (uint) event_len != uint4korr(buf+EVENT_LEN_OFFSET))
+ {
+ *error="Sanity check failed"; // Needed to free buffer
return NULL; // general sanity check - will fail on a partial read
+ }
Log_event* ev = NULL;
- switch(buf[EVENT_TYPE_OFFSET])
- {
+ switch(buf[EVENT_TYPE_OFFSET]) {
case QUERY_EVENT:
ev = new Query_log_event(buf, event_len, old_format);
break;
@@ -591,8 +613,7 @@ Log_event* Log_event::read_log_event(const char* buf, int event_len,
default:
break;
}
- if (!ev) return 0;
- if (!ev->is_valid())
+ if (!ev || !ev->is_valid())
{
*error= "Found invalid event in binary log";
delete ev;
@@ -602,27 +623,24 @@ Log_event* Log_event::read_log_event(const char* buf, int event_len,
return ev;
}
+
#ifdef MYSQL_CLIENT
void Log_event::print_header(FILE* file)
{
char llbuff[22];
fputc('#', file);
print_timestamp(file);
- fprintf(file, " server id %d log_pos %s ", server_id,
+ fprintf(file, " server id %d log_pos %s ", server_id,
llstr(log_pos,llbuff));
}
void Log_event::print_timestamp(FILE* file, time_t* ts)
{
-#ifdef MYSQL_SERVER
- struct tm tm_tmp;
-#endif
struct tm *res;
if (!ts)
- {
ts = &when;
- }
-#ifdef MYSQL_SERVER
+#ifdef MYSQL_SERVER // This is always false
+ struct tm tm_tmp;
localtime_r(ts,(res= &tm_tmp));
#else
res=localtime(ts);
@@ -672,14 +690,16 @@ void Rotate_log_event::print(FILE* file, bool short_form, char* last_db)
if (new_log_ident)
my_fwrite(file, (byte*) new_log_ident, (uint)ident_len,
MYF(MY_NABP | MY_WME));
- fprintf(file, "pos=%s\n", llstr(pos, buf));
+ fprintf(file, " pos: %s\n", llstr(pos, buf));
fflush(file);
}
#endif /* #ifdef MYSQL_CLIENT */
+
Start_log_event::Start_log_event(const char* buf,
- bool old_format) :Log_event(buf, old_format)
+ bool old_format)
+ :Log_event(buf, old_format)
{
buf += (old_format) ? OLD_HEADER_LEN : LOG_EVENT_HEADER_LEN;
binlog_version = uint2korr(buf+ST_BINLOG_VER_OFFSET);
@@ -697,15 +717,15 @@ int Start_log_event::write_data(IO_CACHE* file)
return (my_b_safe_write(file, (byte*) buff, sizeof(buff)) ? -1 : 0);
}
+
Rotate_log_event::Rotate_log_event(const char* buf, int event_len,
- bool old_format):
- Log_event(buf, old_format),new_log_ident(NULL),alloced(0)
+ bool old_format)
+ :Log_event(buf, old_format),new_log_ident(NULL),alloced(0)
{
- // the caller will ensure that event_len is what we have at
- // EVENT_LEN_OFFSET
+ // The caller will ensure that event_len is what we have at EVENT_LEN_OFFSET
int header_size = (old_format) ? OLD_HEADER_LEN : LOG_EVENT_HEADER_LEN;
uint ident_offset;
- if(event_len < header_size)
+ if (event_len < header_size)
return;
buf += header_size;
if (old_format)
@@ -727,34 +747,36 @@ Rotate_log_event::Rotate_log_event(const char* buf, int event_len,
alloced = 1;
}
+
int Rotate_log_event::write_data(IO_CACHE* file)
{
char buf[ROTATE_HEADER_LEN];
int8store(buf, pos + R_POS_OFFSET);
- return my_b_safe_write(file, (byte*)buf, ROTATE_HEADER_LEN) ||
- my_b_safe_write(file, (byte*)new_log_ident, (uint) ident_len);
+ return (my_b_safe_write(file, (byte*)buf, ROTATE_HEADER_LEN) ||
+ my_b_safe_write(file, (byte*)new_log_ident, (uint) ident_len));
}
+
#ifndef MYSQL_CLIENT
Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg,
- bool using_trans):
- Log_event(thd_arg), data_buf(0), query(query_arg), db(thd_arg->db),
- q_len(thd_arg->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_AUTO_COMMIT | OPTION_BEGIN)))
- {
- time_t end_time;
- time(&end_time);
- exec_time = (ulong) (end_time - thd->start_time);
- db_len = (db) ? (uint32) strlen(db) : 0;
- }
+ 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),
+ 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)))
+{
+ time_t end_time;
+ time(&end_time);
+ exec_time = (ulong) (end_time - thd->start_time);
+ db_len = (db) ? (uint32) strlen(db) : 0;
+}
#endif
Query_log_event::Query_log_event(const char* buf, int event_len,
- bool old_format):
- Log_event(buf, old_format),data_buf(0), query(NULL), db(NULL)
+ bool old_format)
+ :Log_event(buf, old_format),data_buf(0), query(NULL), db(NULL)
{
ulong data_len;
if (old_format)
@@ -787,6 +809,7 @@ Query_log_event::Query_log_event(const char* buf, int event_len,
*((char*)query+q_len) = 0;
}
+
#ifdef MYSQL_CLIENT
void Query_log_event::print(FILE* file, bool short_form, char* last_db)
@@ -801,11 +824,11 @@ void Query_log_event::print(FILE* file, bool short_form, char* last_db)
bool same_db = 0;
- if(db && last_db)
- {
- if(!(same_db = !memcmp(last_db, db, db_len + 1)))
- memcpy(last_db, db, db_len + 1);
- }
+ if (db && last_db)
+ {
+ if (!(same_db = !memcmp(last_db, db, db_len + 1)))
+ memcpy(last_db, db, db_len + 1);
+ }
if (db && db[0] && !same_db)
fprintf(file, "use %s;\n", db);
@@ -816,17 +839,18 @@ void Query_log_event::print(FILE* file, bool short_form, char* last_db)
my_fwrite(file, (byte*) query, q_len, MYF(MY_NABP | MY_WME));
fprintf(file, ";\n");
}
-
#endif
+
int Query_log_event::write_data(IO_CACHE* file)
{
- if (!query) return -1;
+ if (!query)
+ return -1;
char buf[QUERY_HEADER_LEN];
int4store(buf + Q_THREAD_ID_OFFSET, thread_id);
int4store(buf + Q_EXEC_TIME_OFFSET, exec_time);
- buf[Q_DB_LEN_OFFSET] = (char)db_len;
+ buf[Q_DB_LEN_OFFSET] = (char) db_len;
int2store(buf + Q_ERR_CODE_OFFSET, error_code);
return (my_b_safe_write(file, (byte*) buf, QUERY_HEADER_LEN) ||
@@ -834,8 +858,8 @@ int Query_log_event::write_data(IO_CACHE* file)
my_b_safe_write(file, (byte*) query, q_len)) ? -1 : 0;
}
-Intvar_log_event::Intvar_log_event(const char* buf, bool old_format):
- Log_event(buf, old_format)
+Intvar_log_event::Intvar_log_event(const char* buf, bool old_format)
+ :Log_event(buf, old_format)
{
buf += (old_format) ? OLD_HEADER_LEN : LOG_EVENT_HEADER_LEN;
type = buf[I_TYPE_OFFSET];
@@ -844,8 +868,7 @@ Intvar_log_event::Intvar_log_event(const char* buf, bool old_format):
const char* Intvar_log_event::get_var_type_name()
{
- switch(type)
- {
+ switch(type) {
case LAST_INSERT_ID_EVENT: return "LAST_INSERT_ID";
case INSERT_ID_EVENT: return "INSERT_ID";
default: /* impossible */ return "UNKNOWN";
@@ -864,28 +887,30 @@ int Intvar_log_event::write_data(IO_CACHE* file)
void Intvar_log_event::print(FILE* file, bool short_form, char* last_db)
{
char llbuff[22];
- if(!short_form)
+ const char *msg;
+ LINT_INIT(msg);
+
+ if (!short_form)
{
print_header(file);
fprintf(file, "\tIntvar\n");
}
fprintf(file, "SET ");
- switch(type)
- {
+ switch (type) {
case LAST_INSERT_ID_EVENT:
- fprintf(file, "LAST_INSERT_ID = ");
+ msg="LAST_INSERT_ID";
break;
case INSERT_ID_EVENT:
- fprintf(file, "INSERT_ID = ");
+ msg="INSERT_ID";
break;
}
- fprintf(file, "%s;\n", llstr(val,llbuff));
+ fprintf(file, "%s=%s;\n", msg, llstr(val,llbuff));
fflush(file);
-
}
#endif
+
int Load_log_event::write_data_header(IO_CACHE* file)
{
char buf[LOAD_HEADER_LEN];
@@ -900,7 +925,8 @@ int Load_log_event::write_data_header(IO_CACHE* file)
int Load_log_event::write_data_body(IO_CACHE* file)
{
- if (sql_ex.write_data(file)) return 1;
+ if (sql_ex.write_data(file))
+ return 1;
if (num_fields && fields && field_lens)
{
if (my_b_safe_write(file, (byte*)field_lens, num_fields) ||
@@ -913,12 +939,14 @@ int Load_log_event::write_data_body(IO_CACHE* file)
}
+
static bool write_str(IO_CACHE *file, char *str, byte length)
{
return (my_b_safe_write(file, &length, 1) ||
my_b_safe_write(file, (byte*) str, (int) length));
}
+
int sql_ex_info::write_data(IO_CACHE* file)
{
if (new_format())
@@ -944,6 +972,7 @@ int sql_ex_info::write_data(IO_CACHE* file)
}
}
+
static inline int read_str(char * &buf, char *buf_end, char * &str,
uint8 &len)
{
@@ -955,17 +984,19 @@ static inline int read_str(char * &buf, char *buf_end, char * &str,
return 0;
}
+
char* sql_ex_info::init(char* buf,char* buf_end,bool use_new_format)
{
cached_new_format = use_new_format;
if (use_new_format)
{
empty_flags=0;
- /* the code below assumes that buf will not disappear from
- under our feet during the lifetime of the event. This assumption
- holds true in the slave thread if the log is in new format, but is not
- the case when we have old format because we will be reusing net buffer
- to read the actual file before we write out the Create_file event
+ /*
+ The code below assumes that buf will not disappear from
+ under our feet during the lifetime of the event. This assumption
+ holds true in the slave thread if the log is in new format, but is not
+ the case when we have old format because we will be reusing net buffer
+ to read the actual file before we write out the Create_file event.
*/
if (read_str(buf, buf_end, field_term, field_term_len) ||
read_str(buf, buf_end, enclosed, enclosed_len) ||
@@ -978,13 +1009,13 @@ char* sql_ex_info::init(char* buf,char* buf_end,bool use_new_format)
else
{
field_term_len= enclosed_len= line_term_len= line_start_len= escaped_len=1;
- field_term = buf++;
- enclosed= buf++;
- line_term= buf++;
- line_start= buf++;
- escaped= buf++;
- opt_flags = *buf++;
- empty_flags=*buf++;
+ field_term = buf++; // Use first byte in string
+ enclosed= buf++;
+ line_term= buf++;
+ line_start= buf++;
+ escaped= buf++;
+ opt_flags = *buf++;
+ empty_flags= *buf++;
if (empty_flags & FIELD_TERM_EMPTY)
field_term_len=0;
if (empty_flags & ENCLOSED_EMPTY)
@@ -1003,81 +1034,83 @@ char* sql_ex_info::init(char* buf,char* buf_end,bool use_new_format)
#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, enum enum_duplicates handle_dup):
- Log_event(thd),thread_id(thd->thread_id),
- num_fields(0),fields(0),field_lens(0),field_block_len(0),
- table_name(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);
- db_len = (db) ? (uint32) strlen(db) : 0;
- table_name_len = (table_name) ? (uint32) strlen(table_name) : 0;
- fname_len = (fname) ? (uint) strlen(fname) : 0;
- sql_ex.field_term = (char*) ex->field_term->ptr();
- sql_ex.field_term_len = (uint8) ex->field_term->length();
- sql_ex.enclosed = (char*) ex->enclosed->ptr();
- sql_ex.enclosed_len = (uint8) ex->enclosed->length();
- sql_ex.line_term = (char*) ex->line_term->ptr();
- sql_ex.line_term_len = (uint8) ex->line_term->length();
- sql_ex.line_start = (char*) ex->line_start->ptr();
- sql_ex.line_start_len = (uint8) ex->line_start->length();
- sql_ex.escaped = (char*) ex->escaped->ptr();
- sql_ex.escaped_len = (uint8) ex->escaped->length();
- sql_ex.opt_flags = 0;
- sql_ex.cached_new_format = -1;
+ List<Item>& fields_arg,
+ enum enum_duplicates handle_dup)
+ :Log_event(thd),thread_id(thd->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);
+ /* db can never be a zero pointer in 4.0 */
+ db_len = (uint32) strlen(db);
+ table_name_len = (uint32) strlen(table_name);
+ fname_len = (fname) ? (uint) strlen(fname) : 0;
+ sql_ex.field_term = (char*) ex->field_term->ptr();
+ sql_ex.field_term_len = (uint8) ex->field_term->length();
+ sql_ex.enclosed = (char*) ex->enclosed->ptr();
+ sql_ex.enclosed_len = (uint8) ex->enclosed->length();
+ sql_ex.line_term = (char*) ex->line_term->ptr();
+ sql_ex.line_term_len = (uint8) ex->line_term->length();
+ sql_ex.line_start = (char*) ex->line_start->ptr();
+ sql_ex.line_start_len = (uint8) ex->line_start->length();
+ sql_ex.escaped = (char*) ex->escaped->ptr();
+ sql_ex.escaped_len = (uint8) ex->escaped->length();
+ sql_ex.opt_flags = 0;
+ sql_ex.cached_new_format = -1;
- if(ex->dumpfile)
- sql_ex.opt_flags |= DUMPFILE_FLAG;
- if(ex->opt_enclosed)
- sql_ex.opt_flags |= OPT_ENCLOSED_FLAG;
-
- sql_ex.empty_flags = 0;
-
- switch(handle_dup)
- {
- case DUP_IGNORE: sql_ex.opt_flags |= IGNORE_FLAG; break;
- case DUP_REPLACE: sql_ex.opt_flags |= REPLACE_FLAG; break;
- case DUP_ERROR: break;
- }
-
-
- if(!ex->field_term->length())
- sql_ex.empty_flags |= FIELD_TERM_EMPTY;
- if(!ex->enclosed->length())
- sql_ex.empty_flags |= ENCLOSED_EMPTY;
- if(!ex->line_term->length())
- sql_ex.empty_flags |= LINE_TERM_EMPTY;
- if(!ex->line_start->length())
- sql_ex.empty_flags |= LINE_START_EMPTY;
- if(!ex->escaped->length())
- sql_ex.empty_flags |= ESCAPED_EMPTY;
+ if (ex->dumpfile)
+ sql_ex.opt_flags |= DUMPFILE_FLAG;
+ if (ex->opt_enclosed)
+ sql_ex.opt_flags |= OPT_ENCLOSED_FLAG;
+
+ sql_ex.empty_flags = 0;
+
+ switch (handle_dup) {
+ case DUP_IGNORE: sql_ex.opt_flags |= IGNORE_FLAG; break;
+ case DUP_REPLACE: sql_ex.opt_flags |= REPLACE_FLAG; break;
+ case DUP_ERROR: break;
+ }
+
+ if (!ex->field_term->length())
+ sql_ex.empty_flags |= FIELD_TERM_EMPTY;
+ if (!ex->enclosed->length())
+ sql_ex.empty_flags |= ENCLOSED_EMPTY;
+ if (!ex->line_term->length())
+ sql_ex.empty_flags |= LINE_TERM_EMPTY;
+ if (!ex->line_start->length())
+ sql_ex.empty_flags |= LINE_START_EMPTY;
+ if (!ex->escaped->length())
+ sql_ex.empty_flags |= ESCAPED_EMPTY;
- skip_lines = ex->skip_lines;
-
- List_iterator<Item> li(fields_arg);
- field_lens_buf.length(0);
- fields_buf.length(0);
- Item* item;
- while((item = li++))
- {
- num_fields++;
- uchar len = (uchar) strlen(item->name);
- field_block_len += len + 1;
- fields_buf.append(item->name, len + 1);
- field_lens_buf.append((char*)&len, 1);
- }
+ skip_lines = ex->skip_lines;
- field_lens = (const uchar*)field_lens_buf.ptr();
- fields = fields_buf.ptr();
+ List_iterator<Item> li(fields_arg);
+ field_lens_buf.length(0);
+ fields_buf.length(0);
+ Item* item;
+ while ((item = li++))
+ {
+ num_fields++;
+ uchar len = (uchar) strlen(item->name);
+ field_block_len += len + 1;
+ fields_buf.append(item->name, len + 1);
+ field_lens_buf.append((char*)&len, 1);
}
+ field_lens = (const uchar*)field_lens_buf.ptr();
+ fields = fields_buf.ptr();
+}
+
#endif
-// the caller must do buf[event_len] = 0 before he starts using the
-// constructed event
+/*
+ The caller must do buf[event_len] = 0 before he starts using the
+ 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),
@@ -1095,7 +1128,7 @@ int Load_log_event::copy_log_event(const char *buf, ulong event_len,
uint data_len;
char* buf_end = (char*)buf + event_len;
const char* data_head = buf + ((old_format) ?
- OLD_HEADER_LEN : LOG_EVENT_HEADER_LEN);
+ OLD_HEADER_LEN : LOG_EVENT_HEADER_LEN);
thread_id = uint4korr(data_head + L_THREAD_ID_OFFSET);
exec_time = uint4korr(data_head + L_EXEC_TIME_OFFSET);
skip_lines = uint4korr(data_head + L_SKIP_LINES_OFFSET);
@@ -1103,13 +1136,16 @@ int Load_log_event::copy_log_event(const char *buf, ulong event_len,
db_len = (uint)data_head[L_DB_LEN_OFFSET];
num_fields = uint4korr(data_head + L_NUM_FIELDS_OFFSET);
- int body_offset = (buf[EVENT_TYPE_OFFSET] == LOAD_EVENT) ?
- LOAD_HEADER_LEN + OLD_HEADER_LEN : get_data_body_offset();
+ int body_offset = ((buf[EVENT_TYPE_OFFSET] == LOAD_EVENT) ?
+ LOAD_HEADER_LEN + OLD_HEADER_LEN :
+ get_data_body_offset());
if ((int) event_len < body_offset)
return 1;
- //sql_ex.init() on success returns the pointer to the first byte after
- //the sql_ex structure, which is the start of field lengths array
+ /*
+ Sql_ex.init() on success returns the pointer to the first byte after
+ the sql_ex structure, which is the start of field lengths array.
+ */
if (!(field_lens=(uchar*)sql_ex.init((char*)buf + body_offset,
buf_end,
buf[EVENT_TYPE_OFFSET] != LOAD_EVENT)))
@@ -1118,11 +1154,9 @@ int Load_log_event::copy_log_event(const char *buf, ulong event_len,
data_len = event_len - body_offset;
if (num_fields > data_len) // simple sanity check against corruption
return 1;
- uint i;
- for (i = 0; i < num_fields; i++)
- {
+ for (uint i = 0; i < num_fields; i++)
field_block_len += (uint)field_lens[i] + 1;
- }
+
fields = (char*)field_lens + num_fields;
table_name = fields + field_block_len;
db = table_name + table_name_len + 1;
@@ -1144,33 +1178,32 @@ void Load_log_event::print(FILE* file, bool short_form, char* last_db)
}
bool same_db = 0;
-
- if(db && last_db)
- {
- if(!(same_db = !memcmp(last_db, db, db_len + 1)))
- memcpy(last_db, db, db_len + 1);
- }
+ if (db && last_db)
+ {
+ if (!(same_db = !memcmp(last_db, db, db_len + 1)))
+ memcpy(last_db, db, db_len + 1);
+ }
- if(db && db[0] && !same_db)
+ if (db && db[0] && !same_db)
fprintf(file, "use %s;\n", db);
fprintf(file, "LOAD DATA INFILE '%-*s' ", fname_len, fname);
- if(sql_ex.opt_flags && REPLACE_FLAG )
+ if (sql_ex.opt_flags && REPLACE_FLAG )
fprintf(file," REPLACE ");
- else if(sql_ex.opt_flags && IGNORE_FLAG )
+ else if (sql_ex.opt_flags && IGNORE_FLAG )
fprintf(file," IGNORE ");
fprintf(file, "INTO TABLE %s ", table_name);
- if(sql_ex.field_term)
+ if (sql_ex.field_term)
{
fprintf(file, " FIELDS TERMINATED BY ");
pretty_print_str(file, sql_ex.field_term, sql_ex.field_term_len);
}
- if(sql_ex.enclosed)
+ if (sql_ex.enclosed)
{
- if(sql_ex.opt_flags && OPT_ENCLOSED_FLAG )
+ if (sql_ex.opt_flags && OPT_ENCLOSED_FLAG )
fprintf(file," OPTIONALLY ");
fprintf(file, " ENCLOSED BY ");
pretty_print_str(file, sql_ex.enclosed, sql_ex.enclosed_len);
@@ -1194,17 +1227,17 @@ void Load_log_event::print(FILE* file, bool short_form, char* last_db)
pretty_print_str(file, sql_ex.line_start, sql_ex.line_start_len);
}
- if((int)skip_lines > 0)
+ if ((int)skip_lines > 0)
fprintf(file, " IGNORE %ld LINES ", (long) skip_lines);
if (num_fields)
{
uint i;
const char* field = fields;
- fprintf( file, " (");
- for(i = 0; i < num_fields; i++)
+ fprintf(file, " (");
+ for (i = 0; i < num_fields; i++)
{
- if(i)
+ if (i)
fputc(',', file);
fprintf(file, field);
@@ -1221,10 +1254,11 @@ void Load_log_event::print(FILE* file, bool short_form, char* last_db)
#ifndef MYSQL_CLIENT
void Log_event::set_log_pos(MYSQL_LOG* log)
- {
- if (!log_pos)
- log_pos = my_b_tell(&log->log_file);
- }
+{
+ if (!log_pos)
+ log_pos = my_b_tell(&log->log_file);
+}
+
void Load_log_event::set_fields(List<Item> &fields)
{
@@ -1242,8 +1276,9 @@ 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)
{
- if (!rli->inited)
- return;
+ DBUG_ENTER("Slave_log_event");
+ if (!rli->inited) // QQ When can this happen ?
+ DBUG_VOID_RETURN;
MASTER_INFO* mi = rli->mi;
// TODO: re-write this better without holding both locks at the same time
@@ -1261,15 +1296,17 @@ Slave_log_event::Slave_log_event(THD* thd_arg,
memcpy(master_log, rli->master_log_name, master_log_len + 1);
master_port = mi->port;
master_pos = rli->master_log_pos;
+ DBUG_PRINT("info", ("master_log: %s pos: %d", master_log,
+ (ulong) master_pos));
}
else
sql_print_error("Out of memory while recording slave event");
pthread_mutex_unlock(&rli->data_lock);
pthread_mutex_unlock(&mi->data_lock);
+ DBUG_VOID_RETURN;
}
-
-#endif
+#endif /* ! MYSQL_CLIENT */
Slave_log_event::~Slave_log_event()
@@ -1282,16 +1319,16 @@ Slave_log_event::~Slave_log_event()
void Slave_log_event::print(FILE* file, bool short_form, char* last_db)
{
char llbuff[22];
- if(short_form)
+ if (short_form)
return;
print_header(file);
fputc('\n', file);
- fprintf(file, "Slave: master_host='%s' master_port=%d \
- master_log=%s master_pos=%s\n",
+ fprintf(file, "Slave: master_host: '%s' master_port: %d \
+master_log: '%s' master_pos: %s\n",
master_host, master_port, master_log, llstr(master_pos, llbuff));
}
-#endif
+#endif /* MYSQL_CLIENT */
int Slave_log_event::get_data_size()
{
@@ -1306,6 +1343,7 @@ int Slave_log_event::write_data(IO_CACHE* file)
return my_b_safe_write(file, (byte*)mem_pool, get_data_size());
}
+
void Slave_log_event::init_from_mem_pool(int data_size)
{
master_pos = uint8korr(mem_pool + SL_MASTER_POS_OFFSET);
@@ -1314,7 +1352,7 @@ void Slave_log_event::init_from_mem_pool(int data_size)
master_host_len = strlen(master_host);
// safety
master_log = master_host + master_host_len + 1;
- if(master_log > mem_pool + data_size)
+ if (master_log > mem_pool + data_size)
{
master_host = 0;
return;
@@ -1322,13 +1360,13 @@ void Slave_log_event::init_from_mem_pool(int data_size)
master_log_len = strlen(master_log);
}
-Slave_log_event::Slave_log_event(const char* buf, int event_len):
- Log_event(buf,0),mem_pool(0),master_host(0)
+Slave_log_event::Slave_log_event(const char* buf, int event_len)
+ :Log_event(buf,0),mem_pool(0),master_host(0)
{
event_len -= LOG_EVENT_HEADER_LEN;
- if(event_len < 0)
+ if (event_len < 0)
return;
- if(!(mem_pool = (char*)my_malloc(event_len + 1, MYF(MY_WME))))
+ if (!(mem_pool = (char*) my_malloc(event_len + 1, MYF(MY_WME))))
return;
memcpy(mem_pool, buf + LOG_EVENT_HEADER_LEN, event_len);
mem_pool[event_len] = 0;
@@ -1339,10 +1377,10 @@ Slave_log_event::Slave_log_event(const char* buf, int event_len):
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),
- fake_base(0),block(block_arg),block_len(block_len_arg),
- file_id(thd_arg->file_id = mysql_bin_log.next_file_id())
+ char* block_arg, uint block_len_arg)
+ :Load_log_event(thd_arg,ex,db_arg,table_name_arg,fields_arg,handle_dup),
+ fake_base(0),block(block_arg),block_len(block_len_arg),
+ file_id(thd_arg->file_id = mysql_bin_log.next_file_id())
{
sql_ex.force_new_format();
}
@@ -1377,8 +1415,8 @@ int Create_file_log_event::write_base(IO_CACHE* file)
}
Create_file_log_event::Create_file_log_event(const char* buf, int len,
- bool old_format):
- Load_log_event(buf,0,old_format),fake_base(0),block(0),inited_from_old(0)
+ bool old_format)
+ :Load_log_event(buf,0,old_format),fake_base(0),block(0),inited_from_old(0)
{
int block_offset;
if (copy_log_event(buf,len,old_format))
@@ -1387,8 +1425,9 @@ Create_file_log_event::Create_file_log_event(const char* buf, int len,
{
file_id = uint4korr(buf + LOG_EVENT_HEADER_LEN +
+ LOAD_HEADER_LEN + CF_FILE_ID_OFFSET);
- block_offset = LOG_EVENT_HEADER_LEN + Load_log_event::get_data_size() +
- CREATE_FILE_HEADER_LEN + 1; // 1 for \0 terminating fname
+ // + 1 for \0 terminating fname
+ block_offset = (LOG_EVENT_HEADER_LEN + Load_log_event::get_data_size() +
+ CREATE_FILE_HEADER_LEN + 1);
if (len < block_offset)
return;
block = (char*)buf + block_offset;
@@ -1409,42 +1448,44 @@ void Create_file_log_event::print(FILE* file, bool short_form,
if (short_form)
return;
Load_log_event::print(file, 1, last_db);
- fprintf(file, " file_id=%d, block_len=%d\n", file_id, block_len);
+ fprintf(file, " file_id: %d block_len: %d\n", file_id, block_len);
}
#endif
#ifndef MYSQL_CLIENT
void Create_file_log_event::pack_info(String* packet)
{
- char buf1[256];
+ char buf1[256],buf[22], *end;
String tmp(buf1, sizeof(buf1), system_charset_info);
tmp.length(0);
- char buf[22];
tmp.append("db=");
tmp.append(db, db_len);
tmp.append(";table=");
tmp.append(table_name, table_name_len);
tmp.append(";file_id=");
- tmp.append(llstr(file_id,buf));
+ end= int10_to_str((long) file_id, buf, 10);
+ tmp.append(buf, (uint32) (end-buf));
tmp.append(";block_len=");
- tmp.append(llstr(block_len,buf));
- net_store_data(packet, (char*)tmp.ptr(), tmp.length());
+ end= int10_to_str((long) block_len, buf, 10);
+ tmp.append(buf, (uint32) (end-buf));
+ net_store_data(packet, (char*) tmp.ptr(), tmp.length());
}
#endif
#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)
+ :Log_event(thd_arg), block(block_arg),block_len(block_len_arg),
+ file_id(thd_arg->file_id)
{
}
#endif
+
-Append_block_log_event::Append_block_log_event(const char* buf, int len):
- Log_event(buf, 0),block(0)
+Append_block_log_event::Append_block_log_event(const char* buf, int len)
+ :Log_event(buf, 0),block(0)
{
- if((uint)len < APPEND_BLOCK_EVENT_OVERHEAD)
+ if ((uint)len < APPEND_BLOCK_EVENT_OVERHEAD)
return;
file_id = uint4korr(buf + LOG_EVENT_HEADER_LEN + AB_FILE_ID_OFFSET);
block = (char*)buf + APPEND_BLOCK_EVENT_OVERHEAD;
@@ -1467,40 +1508,36 @@ void Append_block_log_event::print(FILE* file, bool short_form,
return;
print_header(file);
fputc('\n', file);
- fprintf(file, "#Append_block: file_id=%d, block_len=%d\n",
+ fprintf(file, "#Append_block: file_id: %d block_len: %d\n",
file_id, block_len);
}
#endif
+
#ifndef MYSQL_CLIENT
void Append_block_log_event::pack_info(String* packet)
{
char buf1[256];
- String tmp(buf1, sizeof(buf1), system_charset_info);
- tmp.length(0);
- char buf[22];
- tmp.append(";file_id=");
- tmp.append(llstr(file_id,buf));
- tmp.append(";block_len=");
- tmp.append(llstr(block_len,buf));
- net_store_data(packet, (char*)tmp.ptr(), tmp.length());
+ sprintf(buf1, ";file_id=%u;block_len=%u", file_id, block_len);
+ net_store_data(packet, buf1);
}
-#endif
-#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)
+ :Log_event(thd_arg),file_id(thd_arg->file_id)
{
}
-#endif
+#endif
+
-Delete_file_log_event::Delete_file_log_event(const char* buf, int len):
- Log_event(buf, 0),file_id(0)
+Delete_file_log_event::Delete_file_log_event(const char* buf, int len)
+ :Log_event(buf, 0),file_id(0)
{
- if((uint)len < DELETE_FILE_EVENT_OVERHEAD)
+ if ((uint)len < DELETE_FILE_EVENT_OVERHEAD)
return;
file_id = uint4korr(buf + LOG_EVENT_HEADER_LEN + AB_FILE_ID_OFFSET);
}
+
int Delete_file_log_event::write_data(IO_CACHE* file)
{
byte buf[DELETE_FILE_HEADER_LEN];
@@ -1516,38 +1553,37 @@ void Delete_file_log_event::print(FILE* file, bool short_form,
return;
print_header(file);
fputc('\n', file);
- fprintf(file, "#Delete_file: file_id=%d\n",
- file_id);
+ fprintf(file, "#Delete_file: file_id=%u\n", file_id);
}
-#endif
+#endif
+
#ifndef MYSQL_CLIENT
void Delete_file_log_event::pack_info(String* packet)
{
- char buf1[256];
- String tmp(buf1, sizeof(buf1), system_charset_info);
- tmp.length(0);
- char buf[22];
- tmp.append(";file_id=");
- tmp.append(llstr(file_id,buf));
- net_store_data(packet, (char*)tmp.ptr(), tmp.length());
+ char buf1[64];
+ sprintf(buf1, ";file_id=%u", (uint) file_id);
+ net_store_data(packet, buf1);
}
#endif
+
#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)
+ :Log_event(thd_arg),file_id(thd_arg->file_id)
{
}
#endif
-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)
+ if ((uint)len < EXEC_LOAD_EVENT_OVERHEAD)
return;
file_id = uint4korr(buf + LOG_EVENT_HEADER_LEN + EL_FILE_ID_OFFSET);
}
+
int Execute_load_log_event::write_data(IO_CACHE* file)
{
byte buf[EXEC_LOAD_HEADER_LEN];
@@ -1570,13 +1606,9 @@ void Execute_load_log_event::print(FILE* file, bool short_form,
#ifndef MYSQL_CLIENT
void Execute_load_log_event::pack_info(String* packet)
{
- char buf1[256];
- String tmp(buf1, sizeof(buf1), system_charset_info);
- tmp.length(0);
- char buf[22];
- tmp.append(";file_id=");
- tmp.append(llstr(file_id,buf));
- net_store_data(packet, (char*)tmp.ptr(), tmp.length());
+ char buf[64];
+ sprintf(buf, ";file_id=%u", (uint) file_id);
+ net_store_data(packet, buf);
}
#endif
@@ -1587,6 +1619,14 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli)
init_sql_alloc(&thd->mem_root, 8192,0);
thd->db = rewrite_db((char*)db);
DBUG_ASSERT(q_len == strlen(query));
+
+ /*
+ InnoDB internally stores the master log position it has processed so far;
+ position to store is really pos + pending + event_len
+ since we must store the pos of the END of the current log event
+ */
+ rli->event_len= get_event_len();
+
if (db_ok(thd->db, replicate_do_db, replicate_ignore_db))
{
thd->query = (char*)query;
@@ -1598,16 +1638,18 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli)
thd->query_error = 0; // clear error
thd->net.last_errno = 0;
thd->net.last_error[0] = 0;
- thd->slave_proxy_id = thread_id; // for temp tables
+ thd->slave_proxy_id = thread_id; // for temp tables
- // sanity check to make sure the master did not get a really bad
- // error on the query
+ /*
+ Sanity check to make sure the master did not get a really bad
+ error on the query.
+ */
if (ignored_error_code((expected_error = error_code)) ||
!check_expected_error(thd,rli,expected_error))
{
mysql_parse(thd, thd->query, q_len);
- if (expected_error !=
- (actual_error = thd->net.last_errno) && expected_error &&
+ if ((expected_error != (actual_error = thd->net.last_errno)) &&
+ expected_error &&
!ignored_error_code(actual_error) &&
!ignored_error_code(expected_error))
{
@@ -1619,8 +1661,8 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli)
actual_error);
thd->query_error = 1;
}
- else if (expected_error == actual_error
- || ignored_error_code(actual_error))
+ else if (expected_error == actual_error ||
+ ignored_error_code(actual_error))
{
thd->query_error = 0;
*rli->last_slave_error = 0;
@@ -1631,23 +1673,23 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli)
{
// master could be inconsistent, abort and tell DBA to check/fix it
thd->db = thd->query = 0;
- thd->convert_set = 0;
+ thd->variables.convert_set = 0;
close_thread_tables(thd);
free_root(&thd->mem_root,0);
return 1;
}
}
- thd->db = 0; // prevent db from being freed
- thd->query = 0; // just to be sure
+ thd->db= 0; // prevent db from being freed
+ thd->query= 0; // just to be sure
// assume no convert for next query unless set explictly
- thd->convert_set = 0;
+ thd->variables.convert_set = 0;
close_thread_tables(thd);
if (thd->query_error || thd->fatal_error)
{
slave_print_error(rli,actual_error, "error '%s' on query '%s'",
- actual_error ? thd->net.last_error :
- "unexpected success or fatal error", query);
+ actual_error ? thd->net.last_error :
+ "unexpected success or fatal error", query);
free_root(&thd->mem_root,0);
return 1;
}
@@ -1655,6 +1697,7 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli)
return Log_event::exec_event(rli);
}
+
int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli)
{
init_sql_alloc(&thd->mem_root, 8192,0);
@@ -1662,7 +1705,7 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli)
thd->query = 0;
thd->query_error = 0;
- if(db_ok(thd->db, replicate_do_db, replicate_ignore_db))
+ if (db_ok(thd->db, replicate_do_db, replicate_ignore_db))
{
thd->set_time((time_t)when);
thd->current_tablenr = 0;
@@ -1676,7 +1719,7 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli)
tables.name = tables.real_name = (char*)table_name;
tables.lock_type = TL_WRITE;
// the table will be opened in mysql_load
- if(table_rules_on && !tables_ok(thd, &tables))
+ if (table_rules_on && !tables_ok(thd, &tables))
{
// TODO: this is a bug - this needs to be moved to the I/O thread
if (net)
@@ -1690,10 +1733,14 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli)
handle_dup = DUP_REPLACE;
sql_exchange ex((char*)fname, sql_ex.opt_flags &&
DUMPFILE_FLAG );
- String field_term(sql_ex.field_term,sql_ex.field_term_len, system_charset_info);
- String enclosed(sql_ex.enclosed,sql_ex.enclosed_len, system_charset_info);
- String line_term(sql_ex.line_term,sql_ex.line_term_len, system_charset_info);
- String line_start(sql_ex.line_start,sql_ex.line_start_len, system_charset_info);
+ String field_term(sql_ex.field_term,sql_ex.field_term_len,
+ system_charset_info);
+ String enclosed(sql_ex.enclosed,sql_ex.enclosed_len,
+ system_charset_info);
+ String line_term(sql_ex.line_term,sql_ex.line_term_len,
+ system_charset_info);
+ String line_start(sql_ex.line_start,sql_ex.line_start_len,
+ system_charset_info);
String escaped(sql_ex.escaped,sql_ex.escaped_len, system_charset_info);
ex.opt_enclosed = (sql_ex.opt_flags & OPT_ENCLOSED_FLAG);
@@ -1708,34 +1755,37 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli)
{
// mysql_load will use thd->net to read the file
thd->net.vio = net->vio;
- // make sure the client does not get confused
- // about the packet sequence
+ /*
+ Make sure the client does not get confused about the packet sequence
+ */
thd->net.pkt_nr = net->pkt_nr;
}
- if(mysql_load(thd, &ex, &tables, fields, handle_dup, net != 0,
- TL_WRITE))
+ if (mysql_load(thd, &ex, &tables, fields, handle_dup, net != 0,
+ TL_WRITE))
thd->query_error = 1;
- if(thd->cuted_fields)
+ if (thd->cuted_fields)
sql_print_error("Slave: load data infile at position %s in log \
'%s' produced %d warning(s)", llstr(rli->master_log_pos,llbuff), RPL_LOG_NAME,
thd->cuted_fields );
- if(net)
- net->pkt_nr = thd->net.pkt_nr;
+ if (net)
+ net->pkt_nr= thd->net.pkt_nr;
}
}
else
{
- // we will just ask the master to send us /dev/null if we do not
- // want to load the data
- // TODO: this a bug - needs to be done in I/O thread
+ /*
+ We will just ask the master to send us /dev/null if we do not
+ want to load the data.
+ TODO: this a bug - needs to be done in I/O thread
+ */
if (net)
skip_load_data_infile(net);
}
thd->net.vio = 0;
- thd->db = 0;// prevent db from being freed
+ thd->db= 0; // prevent db from being freed
close_thread_tables(thd);
- if(thd->query_error)
+ if (thd->query_error)
{
int sql_error = thd->net.last_errno;
if (!sql_error)
@@ -1743,13 +1793,13 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli)
slave_print_error(rli,sql_error,
"Slave: Error '%s' running load data infile ",
- ER_SAFE(sql_error));
+ ER_SAFE(sql_error));
free_root(&thd->mem_root,0);
return 1;
}
free_root(&thd->mem_root,0);
- if(thd->fatal_error)
+ if (thd->fatal_error)
{
sql_print_error("Slave: Fatal error running LOAD DATA INFILE ");
return 1;
@@ -1758,53 +1808,105 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli)
return Log_event::exec_event(rli);
}
+
+/*
+ The master started
+
+ IMPLEMENTATION
+ - To handle the case where the master died without a stop event,
+ we clean up all temporary tables + locks that we got.
+
+ TODO
+ - Remove all active user locks
+ - If we have an active transaction at this point, the master died
+ in the middle while writing the transaction to the binary log.
+ In this case we should stop the slave.
+*/
+
int Start_log_event::exec_event(struct st_relay_log_info* rli)
{
+ /* All temporary tables was deleted on the master */
close_temporary_tables(thd);
- // if we have old format, load_tmpdir is cleaned up by the I/O thread
- // TODO: cleanup_load_tmpdir() needs to remove only the files associated
- // with the server id that has just started
+ /*
+ If we have old format, load_tmpdir is cleaned up by the I/O thread
+ */
if (!rli->mi->old_format)
cleanup_load_tmpdir();
return Log_event::exec_event(rli);
}
+
+/*
+ The master stopped. Clean up all temporary tables + locks that the
+ master may have set.
+
+ TODO
+ - Remove all active user locks
+*/
+
int Stop_log_event::exec_event(struct st_relay_log_info* rli)
{
// do not clean up immediately after rotate event
- if (rli->master_log_pos > 4)
+ if (rli->master_log_pos > BIN_LOG_HEADER_SIZE)
{
close_temporary_tables(thd);
cleanup_load_tmpdir();
}
/*
We do not want to update master_log pos because we get a rotate event
- before stop, so by now master_log_name is set to the next log
- if we updated it, we will have incorrect master coordinates and this
+ before stop, so by now master_log_name is set to the next log.
+ If we updated it, we will have incorrect master coordinates and this
could give false triggers in MASTER_POS_WAIT() that we have reached
- the targed position when in fact we have not
+ the target position when in fact we have not.
*/
rli->inc_pos(get_event_len(), 0);
flush_relay_log_info(rli);
return 0;
}
+
+/*
+ Got a rotate log even from the master
+
+ IMPLEMENTATION
+ - Rotate the log file if the name of the log file changed
+ (In practice this should always be the case)
+
+ TODO
+ - Investigate/Test if we can't ignore all rotate log events
+ that we get from the master (and not even write it to the local
+ binary log).
+
+ RETURN VALUES
+ 0 ok
+ 1 Impossible new log file name (rotate log event is ignored)
+*/
+
+
int Rotate_log_event::exec_event(struct st_relay_log_info* rli)
{
bool rotate_binlog = 0, write_slave_event = 0;
char* log_name = rli->master_log_name;
+ DBUG_ENTER("Rotate_log_event::exec_event");
+
pthread_mutex_lock(&rli->data_lock);
- // TODO: probably needs re-write
- // rotate local binlog only if the name of remote has changed
- if (!*log_name || !(log_name[ident_len] == 0 &&
- !memcmp(log_name, new_log_ident, ident_len)))
+ /*
+ TODO: probably needs re-write
+ rotate local binlog only if the name of remote has changed
+ */
+ if (!*log_name || (memcmp(log_name, new_log_ident, ident_len) ||
+ log_name[ident_len] != 0))
{
- write_slave_event = (!(flags & LOG_EVENT_FORCED_ROTATE_F)
- && mysql_bin_log.is_open());
+ write_slave_event = (!(flags & LOG_EVENT_FORCED_ROTATE_F) &&
+ mysql_bin_log.is_open());
rotate_binlog = (*log_name && write_slave_event);
if (ident_len >= sizeof(rli->master_log_name))
- return 1;
- memcpy(log_name, new_log_ident,ident_len);
+ {
+ // This should be impossible
+ pthread_mutex_unlock(&rli->data_lock);
+ DBUG_RETURN(1);
+ }
+ memcpy(log_name, new_log_ident, ident_len);
log_name[ident_len] = 0;
}
rli->master_log_pos = pos;
@@ -1812,8 +1914,9 @@ int Rotate_log_event::exec_event(struct st_relay_log_info* rli)
if (rotate_binlog)
{
mysql_bin_log.new_file();
- rli->master_log_pos = 4;
+ rli->master_log_pos = BIN_LOG_HEADER_SIZE;
}
+ DBUG_PRINT("info", ("master_log_pos: %d", (ulong) rli->master_log_pos));
pthread_cond_broadcast(&rli->data_cond);
pthread_mutex_unlock(&rli->data_lock);
flush_relay_log_info(rli);
@@ -1828,13 +1931,12 @@ int Rotate_log_event::exec_event(struct st_relay_log_info* rli)
mysql_bin_log.write(&s);
}
}
- return 0;
+ DBUG_RETURN(0);
}
int Intvar_log_event::exec_event(struct st_relay_log_info* rli)
{
- switch (type)
- {
+ switch (type) {
case LAST_INSERT_ID_EVENT:
thd->last_insert_id_used = 1;
thd->last_insert_id = val;
@@ -1849,7 +1951,7 @@ int Intvar_log_event::exec_event(struct st_relay_log_info* rli)
int Slave_log_event::exec_event(struct st_relay_log_info* rli)
{
- if(mysql_bin_log.is_open())
+ if (mysql_bin_log.is_open())
mysql_bin_log.write(this);
return Log_event::exec_event(rli);
}
@@ -1901,7 +2003,8 @@ int Create_file_log_event::exec_event(struct st_relay_log_info* rli)
}
if (mysql_bin_log.is_open())
mysql_bin_log.write(this);
- error=0;
+ error=0; // Everything is ok
+
err:
if (error)
end_io_cache(&file);
@@ -1913,12 +2016,11 @@ err:
int Delete_file_log_event::exec_event(struct st_relay_log_info* rli)
{
char fname[FN_REFLEN+10];
- char* p;
- p = slave_load_file_stem(fname, file_id, server_id);
+ char *p= slave_load_file_stem(fname, file_id, server_id);
memcpy(p, ".data", 6);
- (void)my_delete(fname, MYF(MY_WME));
+ (void) my_delete(fname, MYF(MY_WME));
memcpy(p, ".info", 6);
- (void)my_delete(fname, MYF(MY_WME));
+ (void) my_delete(fname, MYF(MY_WME));
if (mysql_bin_log.is_open())
mysql_bin_log.write(this);
return Log_event::exec_event(rli);
@@ -1927,10 +2029,10 @@ int Delete_file_log_event::exec_event(struct st_relay_log_info* rli)
int Append_block_log_event::exec_event(struct st_relay_log_info* rli)
{
char fname[FN_REFLEN+10];
- char* p;
- int fd = -1;
+ char *p= slave_load_file_stem(fname, file_id, server_id);
+ int fd;
int error = 1;
- p = slave_load_file_stem(fname, file_id, server_id);
+
memcpy(p, ".data", 6);
if ((fd = my_open(fname, O_WRONLY|O_APPEND|O_BINARY, MYF(MY_WME))) < 0)
{
@@ -1945,6 +2047,7 @@ int Append_block_log_event::exec_event(struct st_relay_log_info* rli)
if (mysql_bin_log.is_open())
mysql_bin_log.write(this);
error=0;
+
err:
if (fd >= 0)
my_close(fd, MYF(0));
@@ -1954,15 +2057,14 @@ err:
int Execute_load_log_event::exec_event(struct st_relay_log_info* rli)
{
char fname[FN_REFLEN+10];
- char* p;
- int fd = -1;
+ char *p= slave_load_file_stem(fname, file_id, server_id);
+ int fd;
int error = 1;
ulong save_options;
IO_CACHE file;
Load_log_event* lev = 0;
- p = slave_load_file_stem(fname, file_id, server_id);
+
memcpy(p, ".info", 6);
- bzero((char*)&file, sizeof(file));
if ((fd = my_open(fname, O_RDONLY|O_BINARY, MYF(MY_WME))) < 0 ||
init_io_cache(&file, fd, IO_SIZE, READ_CACHE, (my_off_t)0, 0,
MYF(MY_WME|MY_NABP)))
@@ -1972,17 +2074,18 @@ int Execute_load_log_event::exec_event(struct st_relay_log_info* rli)
}
if (!(lev = (Load_log_event*)Log_event::read_log_event(&file,
(pthread_mutex_t*)0,
- (bool)0))
- || lev->get_type_code() != NEW_LOAD_EVENT)
+ (bool)0)) ||
+ lev->get_type_code() != NEW_LOAD_EVENT)
{
slave_print_error(rli,0, "File '%s' appears corrupted", fname);
goto err;
}
- // we want to disable binary logging in slave thread
- // because we need the file events to appear in the same order
- // as they do on the master relative to other events, so that we
- // can preserve ascending order of log sequence numbers - needed
- // to handle failover
+ /*
+ We want to disable binary logging in slave thread because we need the file
+ events to appear in the same order as they do on the master relative to
+ other events, so that we can preserve ascending order of log sequence
+ numbers - needed to handle failover .
+ */
save_options = thd->options;
thd->options &= ~ (ulong) (OPTION_BIN_LOG);
lev->thd = thd;
@@ -1993,19 +2096,21 @@ int Execute_load_log_event::exec_event(struct st_relay_log_info* rli)
goto err;
}
thd->options = save_options;
- (void)my_delete(fname, MYF(MY_WME));
+ (void) my_delete(fname, MYF(MY_WME));
memcpy(p, ".data", 6);
- (void)my_delete(fname, MYF(MY_WME));
+ (void) my_delete(fname, MYF(MY_WME));
if (mysql_bin_log.is_open())
mysql_bin_log.write(this);
error = 0;
+
err:
delete lev;
- end_io_cache(&file);
if (fd >= 0)
+ {
my_close(fd, MYF(0));
+ end_io_cache(&file);
+ }
return error ? error : Log_event::exec_event(rli);
}
-
-#endif
+#endif /* !MYSQL_CLIENT */
diff --git a/sql/log_event.h b/sql/log_event.h
index a29c3952d46..b69643c366a 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -15,8 +15,8 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-#ifndef _LOG_EVENT_H
-#define _LOG_EVENT_H
+#ifndef _log_event_h
+#define _log_event_h
#ifdef __EMX__
#undef write // remove pthread.h macro definition, conflict with write() class member
@@ -36,74 +36,76 @@
#define LOG_EVENT_OFFSET 4
#define BINLOG_VERSION 3
-/* we could have used SERVER_VERSION_LENGTH, but this introduces an
- obscure dependency - if somebody decided to change SERVER_VERSION_LENGTH
- this would have broke the replication protocol
+/*
+ We could have used SERVER_VERSION_LENGTH, but this introduces an
+ obscure dependency - if somebody decided to change SERVER_VERSION_LENGTH
+ this would have broke the replication protocol
*/
#define ST_SERVER_VER_LEN 50
-#define DUMPFILE_FLAG 0x1
-#define OPT_ENCLOSED_FLAG 0x2
-#define REPLACE_FLAG 0x4
-#define IGNORE_FLAG 0x8
+#define DUMPFILE_FLAG 0x1
+#define OPT_ENCLOSED_FLAG 0x2
+#define REPLACE_FLAG 0x4
+#define IGNORE_FLAG 0x8
-#define FIELD_TERM_EMPTY 0x1
-#define ENCLOSED_EMPTY 0x2
-#define LINE_TERM_EMPTY 0x4
-#define LINE_START_EMPTY 0x8
-#define ESCAPED_EMPTY 0x10
+#define FIELD_TERM_EMPTY 0x1
+#define ENCLOSED_EMPTY 0x2
+#define LINE_TERM_EMPTY 0x4
+#define LINE_START_EMPTY 0x8
+#define ESCAPED_EMPTY 0x10
struct old_sql_ex
- {
- char field_term;
- char enclosed;
- char line_term;
- char line_start;
- char escaped;
- char opt_flags;
- char empty_flags;
- };
+{
+ char field_term;
+ char enclosed;
+ char line_term;
+ char line_start;
+ char escaped;
+ char opt_flags;
+ char empty_flags;
+};
#define NUM_LOAD_DELIM_STRS 5
-
struct sql_ex_info
- {
- char* field_term;
- char* enclosed;
- char* line_term;
- char* line_start;
- char* escaped;
- uint8 field_term_len,enclosed_len,line_term_len,line_start_len,
- escaped_len;
- char opt_flags;
- char empty_flags;
- int cached_new_format;
+{
+ char* field_term;
+ char* enclosed;
+ char* line_term;
+ char* line_start;
+ char* escaped;
+ int cached_new_format;
+ uint8 field_term_len,enclosed_len,line_term_len,line_start_len, escaped_len;
+ char opt_flags;
+ char empty_flags;
- // store in new format even if old is possible
- void force_new_format() { cached_new_format = 1;}
- int data_size() { return new_format() ?
- field_term_len + enclosed_len + line_term_len +
- line_start_len + escaped_len + 6 : 7;}
- int write_data(IO_CACHE* file);
- char* init(char* buf,char* buf_end,bool use_new_format);
- bool new_format()
- {
- return (cached_new_format != -1) ? cached_new_format :
- (cached_new_format=(field_term_len > 1 ||
- enclosed_len > 1 ||
- line_term_len > 1 || line_start_len > 1 ||
- escaped_len > 1));
- }
- } ;
-
-/* Binary log consists of events. Each event has a fixed length header,
- followed by possibly variable ( depending on the type of event) length
- data body. The data body consists of an optional fixed length segment
- (post-header), and an optional variable length segment. See #defines and
- comments below for the format specifics
-*/
+ // store in new format even if old is possible
+ void force_new_format() { cached_new_format = 1;}
+ int data_size()
+ {
+ return (new_format() ?
+ field_term_len + enclosed_len + line_term_len +
+ line_start_len + escaped_len + 6 : 7);
+ }
+ int write_data(IO_CACHE* file);
+ char* init(char* buf,char* buf_end,bool use_new_format);
+ bool new_format()
+ {
+ return ((cached_new_format != -1) ? cached_new_format :
+ (cached_new_format=(field_term_len > 1 ||
+ enclosed_len > 1 ||
+ line_term_len > 1 || line_start_len > 1 ||
+ escaped_len > 1)));
+ }
+};
+/*
+ Binary log consists of events. Each event has a fixed length header,
+ followed by possibly variable ( depending on the type of event) length
+ data body. The data body consists of an optional fixed length segment
+ (post-header), and an optional variable length segment. See #defines and
+ comments below for the format specifics
+*/
/* event-specific post-header sizes */
#define LOG_EVENT_HEADER_LEN 19
@@ -139,11 +141,11 @@ struct sql_ex_info
/* query event post-header */
-#define Q_THREAD_ID_OFFSET 0
-#define Q_EXEC_TIME_OFFSET 4
-#define Q_DB_LEN_OFFSET 8
-#define Q_ERR_CODE_OFFSET 9
-#define Q_DATA_OFFSET QUERY_HEADER_LEN
+#define Q_THREAD_ID_OFFSET 0
+#define Q_EXEC_TIME_OFFSET 4
+#define Q_DB_LEN_OFFSET 8
+#define Q_ERR_CODE_OFFSET 9
+#define Q_DATA_OFFSET QUERY_HEADER_LEN
/* Intvar event post-header */
@@ -159,7 +161,7 @@ struct sql_ex_info
#define L_DB_LEN_OFFSET 13
#define L_NUM_FIELDS_OFFSET 14
#define L_SQL_EX_OFFSET 18
-#define L_DATA_OFFSET LOAD_HEADER_LEN
+#define L_DATA_OFFSET LOAD_HEADER_LEN
/* Rotate event post-header */
@@ -176,10 +178,10 @@ struct sql_ex_info
#define DF_FILE_ID_OFFSET 0
-#define QUERY_EVENT_OVERHEAD (LOG_EVENT_HEADER_LEN+QUERY_HEADER_LEN)
-#define QUERY_DATA_OFFSET (LOG_EVENT_HEADER_LEN+QUERY_HEADER_LEN)
-#define ROTATE_EVENT_OVERHEAD (LOG_EVENT_HEADER_LEN+ROTATE_HEADER_LEN)
-#define LOAD_EVENT_OVERHEAD (LOG_EVENT_HEADER_LEN+LOAD_HEADER_LEN)
+#define QUERY_EVENT_OVERHEAD (LOG_EVENT_HEADER_LEN+QUERY_HEADER_LEN)
+#define QUERY_DATA_OFFSET (LOG_EVENT_HEADER_LEN+QUERY_HEADER_LEN)
+#define ROTATE_EVENT_OVERHEAD (LOG_EVENT_HEADER_LEN+ROTATE_HEADER_LEN)
+#define LOAD_EVENT_OVERHEAD (LOG_EVENT_HEADER_LEN+LOAD_HEADER_LEN)
#define CREATE_FILE_EVENT_OVERHEAD (LOG_EVENT_HEADER_LEN+\
+LOAD_HEADER_LEN+CREATE_FILE_HEADER_LEN)
#define DELETE_FILE_EVENT_OVERHEAD (LOG_EVENT_HEADER_LEN+DELETE_FILE_HEADER_LEN)
@@ -192,13 +194,19 @@ struct sql_ex_info
#define LOG_EVENT_TIME_F 0x1
#define LOG_EVENT_FORCED_ROTATE_F 0x2
-enum Log_event_type { START_EVENT = 1, QUERY_EVENT =2,
- STOP_EVENT=3, ROTATE_EVENT = 4, INTVAR_EVENT=5,
- LOAD_EVENT=6, SLAVE_EVENT=7, CREATE_FILE_EVENT=8,
- APPEND_BLOCK_EVENT=9, EXEC_LOAD_EVENT=10, DELETE_FILE_EVENT=11,
- NEW_LOAD_EVENT=12};
-enum Int_event_type { INVALID_INT_EVENT = 0, LAST_INSERT_ID_EVENT = 1, INSERT_ID_EVENT = 2
- };
+enum Log_event_type
+{
+ START_EVENT = 1, QUERY_EVENT =2, STOP_EVENT=3, ROTATE_EVENT = 4,
+ INTVAR_EVENT=5, LOAD_EVENT=6, SLAVE_EVENT=7, CREATE_FILE_EVENT=8,
+ APPEND_BLOCK_EVENT=9, EXEC_LOAD_EVENT=10, DELETE_FILE_EVENT=11,
+ NEW_LOAD_EVENT=12
+};
+
+enum Int_event_type
+{
+ INVALID_INT_EVENT = 0, LAST_INSERT_ID_EVENT = 1, INSERT_ID_EVENT = 2
+};
+
#ifndef MYSQL_CLIENT
class String;
@@ -206,8 +214,6 @@ class MYSQL_LOG;
class THD;
#endif
-extern uint32 server_id;
-
struct st_relay_log_info;
class Log_event
@@ -220,15 +226,38 @@ public:
uint16 flags;
int cached_event_len;
char* temp_buf;
-#ifndef MYSQL_CLIENT
+
+#ifndef MYSQL_CLIENT
THD* thd;
+
+ Log_event(THD* thd_arg, uint16 flags_arg = 0);
+ // if mutex is 0, the read will proceed without mutex
+ static Log_event* read_log_event(IO_CACHE* file,
+ pthread_mutex_t* log_lock,
+ bool old_format);
+ static int read_log_event(IO_CACHE* file, String* packet,
+ pthread_mutex_t* log_lock);
+ void set_log_pos(MYSQL_LOG* log);
+ virtual void pack_info(String* packet);
+ int net_send(THD* thd, const char* log_name, my_off_t pos);
+ static void init_show_field_list(List<Item>* field_list);
+ virtual int exec_event(struct st_relay_log_info* rli);
+ virtual const char* get_db()
+ {
+ return thd ? thd->db : 0;
+ }
+#else
+ // avoid having to link mysqlbinlog against libpthread
+ static Log_event* read_log_event(IO_CACHE* file, bool old_format);
+ virtual void print(FILE* file, bool short_form = 0, char* last_db = 0) = 0;
+ void print_timestamp(FILE* file, time_t *ts = 0);
+ void print_header(FILE* file);
#endif
static void *operator new(size_t size)
{
return (void*) my_malloc((uint)size, MYF(MY_WME|MY_FAE));
}
-
static void operator delete(void *ptr, size_t size)
{
my_free((gptr) ptr, MYF(MY_WME|MY_ALLOW_ZERO_PTR));
@@ -237,64 +266,35 @@ public:
int write(IO_CACHE* file);
int write_header(IO_CACHE* file);
virtual int write_data(IO_CACHE* file)
- { return write_data_header(file) || write_data_body(file); }
+ { return write_data_header(file) || write_data_body(file); }
virtual int write_data_header(IO_CACHE* file __attribute__((unused)))
- { return 0; }
+ { return 0; }
virtual int write_data_body(IO_CACHE* file __attribute__((unused)))
- { return 0; }
+ { return 0; }
virtual Log_event_type get_type_code() = 0;
virtual bool is_valid() = 0;
virtual bool get_cache_stmt() { return 0; }
Log_event(const char* buf, bool old_format);
-#ifndef MYSQL_CLIENT
- Log_event(THD* thd_arg, uint16 flags_arg = 0);
-#endif
virtual ~Log_event() { free_temp_buf();}
void register_temp_buf(char* buf) { temp_buf = buf; }
void free_temp_buf()
+ {
+ if (temp_buf)
{
- if (temp_buf)
- {
- my_free(temp_buf, MYF(0));
- temp_buf = 0;
- }
+ my_free(temp_buf, MYF(0));
+ temp_buf = 0;
}
+ }
virtual int get_data_size() { return 0;}
virtual int get_data_body_offset() { return 0; }
- int get_event_len() { return cached_event_len ? cached_event_len :
- (cached_event_len = LOG_EVENT_HEADER_LEN + get_data_size()); }
-#ifdef MYSQL_CLIENT
- virtual void print(FILE* file, bool short_form = 0, char* last_db = 0) = 0;
- void print_timestamp(FILE* file, time_t *ts = 0);
- void print_header(FILE* file);
-#endif
-
-#ifndef MYSQL_CLIENT
- // if mutex is 0, the read will proceed without mutex
- static Log_event* read_log_event(IO_CACHE* file,
- pthread_mutex_t* log_lock,
- bool old_format);
-#else // avoid having to link mysqlbinlog against libpthread
- static Log_event* read_log_event(IO_CACHE* file, bool old_format);
-#endif
+ int get_event_len()
+ {
+ return (cached_event_len ? cached_event_len :
+ (cached_event_len = LOG_EVENT_HEADER_LEN + get_data_size()));
+ }
static Log_event* read_log_event(const char* buf, int event_len,
const char **error, bool old_format);
const char* get_type_str();
-
-#ifndef MYSQL_CLIENT
- static int read_log_event(IO_CACHE* file, String* packet,
- pthread_mutex_t* log_lock);
- void set_log_pos(MYSQL_LOG* log);
- virtual void pack_info(String* packet);
- int net_send(THD* thd, const char* log_name, my_off_t pos);
- static void init_show_field_list(List<Item>* field_list);
- virtual int exec_event(struct st_relay_log_info* rli);
- virtual const char* get_db()
- {
- return thd ? thd->db : 0;
- }
-#endif
-
};
@@ -305,21 +305,26 @@ protected:
public:
const char* query;
const char* db;
- uint32 q_len; // if we already know the length of the query string
- // we pass it here, so we would not have to call strlen()
- // otherwise, set it to 0, in which case, we compute it with strlen()
+ /*
+ If we already know the length of the query string
+ we pass it with q_len, so we would not have to call strlen()
+ otherwise, set it to 0, in which case, we compute it with strlen()
+ */
+ uint32 q_len;
uint32 db_len;
uint16 error_code;
ulong thread_id;
-#if !defined(MYSQL_CLIENT)
+#ifndef MYSQL_CLIENT
bool cache_stmt;
- Query_log_event(THD* thd_arg, const char* query_arg,
- bool using_trans=0);
+ Query_log_event(THD* thd_arg, const char* query_arg, ulong query_length,
+ bool using_trans=0);
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
Query_log_event(const char* buf, int event_len, bool old_format);
@@ -336,17 +341,15 @@ public:
bool is_valid() { return query != 0; }
int get_data_size()
{
- return q_len + db_len + 2 +
- 4 // thread_id
- + 4 // exec_time
- + 2 // error_code
- ;
+ return (q_len + db_len + 2
+ + 4 // thread_id
+ + 4 // exec_time
+ + 2 // error_code
+ );
}
-#ifdef MYSQL_CLIENT
- void print(FILE* file, bool short_form = 0, char* last_db = 0);
-#endif
};
+
class Slave_log_event: public Log_event
{
protected:
@@ -364,18 +367,16 @@ public:
Slave_log_event(THD* thd_arg, struct st_relay_log_info* rli);
void pack_info(String* packet);
int exec_event(struct st_relay_log_info* rli);
-#endif
-
+#else
+ void print(FILE* file, bool short_form = 0, char* last_db = 0);
+#endif
+
Slave_log_event(const char* buf, int event_len);
~Slave_log_event();
int get_data_size();
bool is_valid() { return master_host != 0; }
Log_event_type get_type_code() { return SLAVE_EVENT; }
-#ifdef MYSQL_CLIENT
- void print(FILE* file, bool short_form = 0, char* last_db = 0);
-#endif
int write_data(IO_CACHE* file );
-
};
class Load_log_event: public Log_event
@@ -399,27 +400,28 @@ public:
uint32 skip_lines;
sql_ex_info sql_ex;
-#if !defined(MYSQL_CLIENT)
+#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,
+ const char* table_name_arg,
List<Item>& fields_arg, enum enum_duplicates handle_dup);
void set_fields(List<Item> &fields_arg);
void pack_info(String* packet);
const char* get_db() { return db; }
int exec_event(struct st_relay_log_info* rli)
- {
- return exec_event(thd->slave_net,rli);
- }
+ {
+ return exec_event(thd->slave_net,rli);
+ }
int exec_event(NET* net, struct st_relay_log_info* rli);
+#else
+ void print(FILE* file, bool short_form = 0, char* last_db = 0);
#endif
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; }
int write_data_header(IO_CACHE* file);
@@ -427,18 +429,14 @@ public:
bool is_valid() { return table_name != 0; }
int get_data_size()
{
- return table_name_len + 2 + db_len + 2 + fname_len
- + 4 // thread_id
- + 4 // exec_time
- + 4 // skip_lines
- + 4 // field block len
- + sql_ex.data_size() + field_block_len + num_fields;
- ;
+ return (table_name_len + 2 + db_len + 2 + fname_len
+ + 4 // thread_id
+ + 4 // exec_time
+ + 4 // skip_lines
+ + 4 // field block len
+ + sql_ex.data_size() + field_block_len + num_fields);
}
int get_data_body_offset() { return LOAD_EVENT_OVERHEAD; }
-#ifdef MYSQL_CLIENT
- void print(FILE* file, bool short_form = 0, char* last_db = 0);
-#endif
};
extern char server_version[SERVER_VERSION_LENGTH];
@@ -449,13 +447,19 @@ public:
uint32 created;
uint16 binlog_version;
char server_version[ST_SERVER_VER_LEN];
-#ifndef MYSQL_CLIENT
+
+#ifndef MYSQL_CLIENT
Start_log_event() :Log_event((THD*)0),binlog_version(BINLOG_VERSION)
{
created = (uint32) when;
memcpy(server_version, ::server_version, ST_SERVER_VER_LEN);
}
+ void pack_info(String* packet);
+ int exec_event(struct st_relay_log_info* rli);
+#else
+ void print(FILE* file, bool short_form = 0, char* last_db = 0);
#endif
+
Start_log_event(const char* buf, bool old_format);
~Start_log_event() {}
Log_event_type get_type_code() { return START_EVENT;}
@@ -465,25 +469,25 @@ public:
{
return START_HEADER_LEN;
}
-#ifndef MYSQL_CLIENT
- void pack_info(String* packet);
- int exec_event(struct st_relay_log_info* rli);
-#endif
-#ifdef MYSQL_CLIENT
- void print(FILE* file, bool short_form = 0, char* last_db = 0);
-#endif
};
+
class Intvar_log_event: public Log_event
{
public:
ulonglong val;
uchar type;
+
#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)
{}
-#endif
+ void pack_info(String* packet);
+ int exec_event(struct st_relay_log_info* rli);
+#else
+ void print(FILE* file, bool short_form = 0, char* last_db = 0);
+#endif
+
Intvar_log_event(const char* buf, bool old_format);
~Intvar_log_event() {}
Log_event_type get_type_code() { return INTVAR_EVENT;}
@@ -491,38 +495,29 @@ public:
int get_data_size() { return sizeof(type) + sizeof(val);}
int write_data(IO_CACHE* file);
bool is_valid() { return 1; }
-#ifndef MYSQL_CLIENT
- void pack_info(String* packet);
- int exec_event(struct st_relay_log_info* rli);
-#endif
-
-#ifdef MYSQL_CLIENT
- void print(FILE* file, bool short_form = 0, char* last_db = 0);
-#endif
};
+
class Stop_log_event: public Log_event
{
public:
#ifndef MYSQL_CLIENT
Stop_log_event() :Log_event((THD*)0)
{}
+ int exec_event(struct st_relay_log_info* rli);
+#else
+ void print(FILE* file, bool short_form = 0, char* last_db = 0);
#endif
- Stop_log_event(const char* buf, bool old_format):Log_event(buf,
- old_format)
- {
- }
+
+ Stop_log_event(const char* buf, bool old_format):
+ Log_event(buf, old_format)
+ {}
~Stop_log_event() {}
Log_event_type get_type_code() { return STOP_EVENT;}
bool is_valid() { return 1; }
-#ifdef MYSQL_CLIENT
- void print(FILE* file, bool short_form = 0, char* last_db = 0);
-#endif
-#ifndef MYSQL_CLIENT
- int exec_event(struct st_relay_log_info* rli);
-#endif
};
+
class Rotate_log_event: public Log_event
{
public:
@@ -532,14 +527,18 @@ 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 = 4)
+ : Log_event(thd_arg), new_log_ident(new_log_ident_arg),
ident_len(ident_len_arg ? ident_len_arg :
(uint) strlen(new_log_ident_arg)), pos(pos_arg),
alloced(0)
{}
-#endif
+ void pack_info(String* packet);
+ int exec_event(struct st_relay_log_info* rli);
+#else
+ void print(FILE* file, bool short_form = 0, char* last_db = 0);
+#endif
+
Rotate_log_event(const char* buf, int event_len, bool old_format);
~Rotate_log_event()
{
@@ -550,13 +549,6 @@ public:
int get_data_size() { return ident_len + ROTATE_HEADER_LEN;}
bool is_valid() { return new_log_ident != 0; }
int write_data(IO_CACHE* file);
-#ifdef MYSQL_CLIENT
- void print(FILE* file, bool short_form = 0, char* last_db = 0);
-#endif
-#ifndef MYSQL_CLIENT
- void pack_info(String* packet);
- int exec_event(struct st_relay_log_info* rli);
-#endif
};
/* the classes below are for the new LOAD DATA INFILE logging */
@@ -564,51 +556,59 @@ public:
class Create_file_log_event: public Load_log_event
{
protected:
- // pretend we are Load event, so we can write out just
- // our Load part - used on the slave when writing event out to
- // SQL_LOAD-*.info file
+ /*
+ Pretend we are Load event, so we can write out just
+ our Load part - used on the slave when writing event out to
+ SQL_LOAD-*.info file
+ */
bool fake_base;
public:
char* block;
uint block_len;
uint file_id;
bool inited_from_old;
+
#ifndef MYSQL_CLIENT
Create_file_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,
char* block_arg, uint block_len_arg);
+ void pack_info(String* packet);
+ int exec_event(struct st_relay_log_info* rli);
+#else
+ void print(FILE* file, bool short_form = 0, char* last_db = 0);
#endif
Create_file_log_event(const char* buf, int event_len, bool old_format);
- ~Create_file_log_event()
+ ~Create_file_log_event() {}
+
+ Log_event_type get_type_code()
{
+ return fake_base ? Load_log_event::get_type_code() : CREATE_FILE_EVENT;
+ }
+ int get_data_size()
+ {
+ return (fake_base ? Load_log_event::get_data_size() :
+ Load_log_event::get_data_size() +
+ 4 + 1 + block_len);
+ }
+ int get_data_body_offset()
+ {
+ return (fake_base ? LOAD_EVENT_OVERHEAD:
+ LOAD_EVENT_OVERHEAD + CREATE_FILE_HEADER_LEN);
}
- Log_event_type get_type_code()
- {
- return fake_base ? Load_log_event::get_type_code() : CREATE_FILE_EVENT;
- }
- int get_data_size() { return fake_base ? Load_log_event::get_data_size() :
- Load_log_event::get_data_size() +
- 4 + 1 + block_len;}
- int get_data_body_offset() { return fake_base ? LOAD_EVENT_OVERHEAD:
- LOAD_EVENT_OVERHEAD + CREATE_FILE_HEADER_LEN; }
bool is_valid() { return inited_from_old || block != 0; }
int write_data_header(IO_CACHE* file);
int write_data_body(IO_CACHE* file);
- int write_base(IO_CACHE* file); // cut out Create_file extentions and
- // write it as Load event - used on the slave
-
-#ifdef MYSQL_CLIENT
- void print(FILE* file, bool short_form = 0, char* last_db = 0);
-#endif
-#ifndef MYSQL_CLIENT
- void pack_info(String* packet);
- int exec_event(struct st_relay_log_info* rli);
-#endif
+ /*
+ Cut out Create_file extentions and
+ write it as Load event - used on the slave
+ */
+ int write_base(IO_CACHE* file);
};
+
class Append_block_log_event: public Log_event
{
public:
@@ -618,27 +618,22 @@ public:
#ifndef MYSQL_CLIENT
Append_block_log_event(THD* thd, char* block_arg,
- uint block_len_arg);
+ uint block_len_arg);
int exec_event(struct st_relay_log_info* rli);
-#endif
+ void pack_info(String* packet);
+#else
+ void print(FILE* file, bool short_form = 0, char* last_db = 0);
+#endif
Append_block_log_event(const char* buf, int event_len);
- ~Append_block_log_event()
- {
- }
+ ~Append_block_log_event() {}
Log_event_type get_type_code() { return APPEND_BLOCK_EVENT;}
int get_data_size() { return block_len + APPEND_BLOCK_HEADER_LEN ;}
bool is_valid() { return block != 0; }
int write_data(IO_CACHE* file);
-
-#ifdef MYSQL_CLIENT
- void print(FILE* file, bool short_form = 0, char* last_db = 0);
-#endif
-#ifndef MYSQL_CLIENT
- void pack_info(String* packet);
-#endif
};
+
class Delete_file_log_event: public Log_event
{
public:
@@ -646,24 +641,18 @@ public:
#ifndef MYSQL_CLIENT
Delete_file_log_event(THD* thd);
+ void pack_info(String* packet);
+ int exec_event(struct st_relay_log_info* rli);
+#else
+ void print(FILE* file, bool short_form = 0, char* last_db = 0);
#endif
Delete_file_log_event(const char* buf, int event_len);
- ~Delete_file_log_event()
- {
- }
+ ~Delete_file_log_event() {}
Log_event_type get_type_code() { return DELETE_FILE_EVENT;}
int get_data_size() { return DELETE_FILE_HEADER_LEN ;}
bool is_valid() { return file_id != 0; }
int write_data(IO_CACHE* file);
-
-#ifdef MYSQL_CLIENT
- void print(FILE* file, bool short_form = 0, char* last_db = 0);
-#endif
-#ifndef MYSQL_CLIENT
- void pack_info(String* packet);
- int exec_event(struct st_relay_log_info* rli);
-#endif
};
class Execute_load_log_event: public Log_event
@@ -673,27 +662,18 @@ public:
#ifndef MYSQL_CLIENT
Execute_load_log_event(THD* thd);
+ void pack_info(String* packet);
+ int exec_event(struct st_relay_log_info* rli);
+#else
+ void print(FILE* file, bool short_form = 0, char* last_db = 0);
#endif
Execute_load_log_event(const char* buf, int event_len);
- ~Execute_load_log_event()
- {
- }
+ ~Execute_load_log_event() {}
Log_event_type get_type_code() { return EXEC_LOAD_EVENT;}
int get_data_size() { return EXEC_LOAD_HEADER_LEN ;}
bool is_valid() { return file_id != 0; }
int write_data(IO_CACHE* file);
-
-#ifdef MYSQL_CLIENT
- void print(FILE* file, bool short_form = 0, char* last_db = 0);
-#endif
-#ifndef MYSQL_CLIENT
- void pack_info(String* packet);
- int exec_event(struct st_relay_log_info* rli);
-#endif
};
-#endif
-
-
-
+#endif /* _log_event_h */
diff --git a/sql/mini_client.cc b/sql/mini_client.cc
index ffb5d659238..5bd88e9b09a 100644
--- a/sql/mini_client.cc
+++ b/sql/mini_client.cc
@@ -20,20 +20,14 @@
Note: all file-global symbols must begin with mc_ , even the static ones, just
in case we decide to make them external at some point
- */
-
-#ifdef EMBEDDED_LIBRARY
-#define net_read_timeout net_read_timeout1
-#define net_write_timeout net_write_timeout1
-#endif
-
-#if defined(__WIN__)
-#include <winsock.h>
-#include <odbcinst.h> /* QQ: Is this really needed ? */
-#define DONT_USE_THR_ALARM
-#endif
+*/
#include <my_global.h>
+/* my_pthread must be included early to be able to fix things */
+#if defined(THREAD)
+#include <my_pthread.h> /* because of signal() */
+#endif
+#include <thr_alarm.h>
#include <mysql_embed.h>
#include <mysql_com.h>
#include <violite.h>
@@ -52,8 +46,6 @@
#define ER CER
#endif
-extern ulong net_read_timeout;
-
extern "C" { // Because of SCO 3.2V4.2
#include <sys/stat.h>
#include <signal.h>
@@ -75,20 +67,12 @@ extern "C" { // Because of SCO 3.2V4.2
#ifdef HAVE_SYS_UN_H
# include <sys/un.h>
#endif
-#if defined(THREAD)
-#include <my_pthread.h> /* because of signal() */
-#endif
-#include <thr_alarm.h>
#ifndef INADDR_NONE
#define INADDR_NONE -1
#endif
}
static void mc_free_rows(MYSQL_DATA *cur);
-static MYSQL_FIELD *unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields,
- my_bool default_value,
- my_bool long_flag_protocol);
-
void mc_end_server(MYSQL *mysql);
static int mc_sock_connect(File s, const struct sockaddr *name, uint namelen, uint to);
static void mc_free_old_query(MYSQL *mysql);
@@ -119,6 +103,8 @@ static my_bool is_NT(void)
}
#endif
+extern ulong slave_net_timeout;
+
/*
** Create a named pipe connection
*/
@@ -209,6 +195,7 @@ MYSQL *mc_mysql_init(MYSQL *mysql)
#ifdef __WIN__
mysql->options.connect_timeout=20;
#endif
+ mysql->net.read_timeout = slave_net_timeout;
return mysql;
}
@@ -354,7 +341,7 @@ mc_net_safe_read(MYSQL *mysql)
if (socket_errno != SOCKET_EINTR)
{
mc_end_server(mysql);
- if(net->last_errno != ER_NET_PACKET_TOO_LARGE)
+ if (net->last_errno != ER_NET_PACKET_TOO_LARGE)
{
net->last_errno=CR_SERVER_LOST;
strmov(net->last_error,ER(net->last_errno));
@@ -362,7 +349,7 @@ mc_net_safe_read(MYSQL *mysql)
else
strmov(net->last_error, "Packet too large - increase \
max_allowed_packet on this server");
- }
+ }
return(packet_error);
}
if (net->read_pos[0] == 255)
@@ -375,7 +362,7 @@ max_allowed_packet on this server");
net->last_errno=uint2korr(pos);
pos+=2;
len-=2;
- if(!net->last_errno)
+ if (!net->last_errno)
net->last_errno = CR_UNKNOWN_ERROR;
}
else
@@ -409,24 +396,28 @@ int mc_mysql_errno(MYSQL *mysql)
return (mysql)->net.last_errno;
}
-my_bool mc_mysql_reconnect(MYSQL *mysql)
+
+my_bool mc_mysql_reconnect(MYSQL *mysql)
{
MYSQL tmp_mysql;
DBUG_ENTER("mc_mysql_reconnect");
if (!mysql->reconnect)
+ {
+ mysql->net.last_errno=CR_SERVER_GONE_ERROR;
+ strmov(mysql->net.last_error, ER(mysql->net.last_errno));
DBUG_RETURN(1);
-
+ }
mc_mysql_init(&tmp_mysql);
tmp_mysql.options=mysql->options;
if (!mc_mysql_connect(&tmp_mysql,mysql->host,mysql->user,mysql->passwd,
- mysql->db, mysql->port, mysql->unix_socket,
- mysql->client_flag))
- {
- tmp_mysql.reconnect=0;
- mc_mysql_close(&tmp_mysql);
- DBUG_RETURN(1);
- }
+ mysql->db, mysql->port, mysql->unix_socket,
+ mysql->client_flag, mysql->net.read_timeout))
+ {
+ mysql->net.last_errno= tmp_mysql.net.last_errno;
+ strmov(mysql->net.last_error, tmp_mysql.net.last_error);
+ DBUG_RETURN(1);
+ }
tmp_mysql.free_me=mysql->free_me;
mysql->free_me=0;
bzero((char*) &mysql->options,sizeof(&mysql->options));
@@ -449,11 +440,7 @@ mc_simple_command(MYSQL *mysql,enum enum_server_command command,
if (mysql->net.vio == 0)
{ /* Do reconnect if possible */
if (mc_mysql_reconnect(mysql))
- {
- net->last_errno=CR_SERVER_GONE_ERROR;
- strmov(net->last_error,ER(net->last_errno));
goto end;
- }
}
if (mysql->status != MYSQL_STATUS_READY)
{
@@ -474,8 +461,9 @@ mc_simple_command(MYSQL *mysql,enum enum_server_command command,
{
DBUG_PRINT("error",("Can't send command to server. Error: %d",socket_errno));
mc_end_server(mysql);
- if (mc_mysql_reconnect(mysql) ||
- net_write_command(net,(uchar) command,arg,
+ if (mc_mysql_reconnect(mysql))
+ goto end;
+ if (net_write_command(net,(uchar) command,arg,
length ? length :(uint) strlen(arg)))
{
net->last_errno=CR_SERVER_GONE_ERROR;
@@ -494,17 +482,19 @@ mc_simple_command(MYSQL *mysql,enum enum_server_command command,
MYSQL *
mc_mysql_connect(MYSQL *mysql,const char *host, const char *user,
- const char *passwd, const char *db,
- uint port, const char *unix_socket,uint client_flag)
+ const char *passwd, const char *db,
+ uint port, const char *unix_socket,uint client_flag,
+ uint net_read_timeout)
{
- char buff[100],*end,*host_info;
+ char buff[NAME_LEN+USERNAME_LENGTH+100],*end,*host_info;
my_socket sock;
ulong ip_addr;
struct sockaddr_in sock_addr;
ulong pkt_length;
NET *net= &mysql->net;
thr_alarm_t alarmed;
- ALARM alarm_buff;
+ ALARM alarm_buff;
+ ulong max_allowed_packet;
#ifdef __WIN__
HANDLE hPipe=INVALID_HANDLE_VALUE;
@@ -513,15 +503,13 @@ mc_mysql_connect(MYSQL *mysql,const char *host, const char *user,
struct sockaddr_un UNIXaddr;
#endif
DBUG_ENTER("mc_mysql_connect");
-
- DBUG_PRINT("enter",("host: %s db: %s user: %s",
+ DBUG_PRINT("enter",("host: %s db: %s user: %s connect_time_out: %u read_timeout: %u",
host ? host : "(Null)",
db ? db : "(Null)",
- user ? user : "(Null)"));
- thr_alarm_init(&alarmed);
- thr_alarm(&alarmed,(uint) net_read_timeout,&alarm_buff);
+ user ? user : "(Null)",
+ net_read_timeout,
+ (uint) slave_net_timeout));
- bzero((char*) &mysql->options,sizeof(mysql->options));
net->vio = 0; /* If something goes wrong */
mysql->charset=default_charset_info; /* Set character set */
if (!port)
@@ -530,13 +518,16 @@ mc_mysql_connect(MYSQL *mysql,const char *host, const char *user,
unix_socket=MYSQL_UNIX_ADDR;
mysql->reconnect=1; /* Reconnect as default */
+ mysql->server_status=SERVER_STATUS_AUTOCOMMIT;
+ if (!mysql->options.connect_timeout)
+ mysql->options.connect_timeout= net_read_timeout;
/*
** Grab a socket and connect it to the server
*/
#if defined(HAVE_SYS_UN_H)
- if (!host || !strcmp(host,LOCAL_HOST))
+ if ((!host || !strcmp(host,LOCAL_HOST)) && unix_socket)
{
host=LOCAL_HOST;
host_info=(char*) ER(CR_LOCALHOST_CONNECTION);
@@ -601,7 +592,11 @@ mc_mysql_connect(MYSQL *mysql,const char *host, const char *user,
host=LOCAL_HOST;
sprintf(host_info=buff,ER(CR_TCP_CONNECTION),host);
DBUG_PRINT("info",("Server name: '%s'. TCP sock: %d", host,port));
- if ((sock = socket(AF_INET,SOCK_STREAM,0)) == SOCKET_ERROR)
+ thr_alarm_init(&alarmed);
+ thr_alarm(&alarmed, net_read_timeout, &alarm_buff);
+ sock = (my_socket) socket(AF_INET,SOCK_STREAM,0);
+ thr_end_alarm(&alarmed);
+ if (sock == SOCKET_ERROR)
{
net->last_errno=CR_IPSOCK_ERROR;
sprintf(net->last_error,ER(net->last_errno),socket_errno);
@@ -644,30 +639,33 @@ mc_mysql_connect(MYSQL *mysql,const char *host, const char *user,
socket_errno,host));
net->last_errno= CR_CONN_HOST_ERROR;
sprintf(net->last_error ,ER(CR_CONN_HOST_ERROR), host, socket_errno);
- if (thr_alarm_in_use(&alarmed))
- thr_end_alarm(&alarmed);
goto error;
}
- if (thr_alarm_in_use(&alarmed))
- thr_end_alarm(&alarmed);
}
if (!net->vio || my_net_init(net, net->vio))
{
vio_delete(net->vio);
- net->vio = 0; // safety
+ net->vio = 0;
net->last_errno=CR_OUT_OF_MEMORY;
strmov(net->last_error,ER(net->last_errno));
goto error;
}
vio_keepalive(net->vio,TRUE);
-
+ net->read_timeout=slave_net_timeout;
/* Get version info */
mysql->protocol_version= PROTOCOL_VERSION; /* Assume this */
+ if (mysql->options.connect_timeout &&
+ vio_poll_read(net->vio, mysql->options.connect_timeout))
+ {
+ net->last_errno= CR_SERVER_LOST;
+ strmov(net->last_error,ER(net->last_errno));
+ goto error;
+ }
if ((pkt_length=mc_net_safe_read(mysql)) == packet_error)
goto error;
- /* Check if version of protocoll matches current one */
+ /* Check if version of protocol matches current one */
mysql->protocol_version= net->read_pos[0];
DBUG_DUMP("packet",(char*) net->read_pos,10);
@@ -685,8 +683,15 @@ mc_mysql_connect(MYSQL *mysql,const char *host, const char *user,
mysql->thread_id=uint4korr(end+1);
end+=5;
strmake(mysql->scramble_buff,end,8);
- if (pkt_length > (uint) (end+9 - (char*) net->read_pos))
- mysql->server_capabilities=uint2korr(end+9);
+ end+=9;
+ if (pkt_length >= (uint) (end+1 - (char*) net->read_pos))
+ mysql->server_capabilities=uint2korr(end);
+ if (pkt_length >= (uint) (end+18 - (char*) net->read_pos))
+ {
+ /* New protocol with 16 bytes to describe server characteristics */
+ mysql->server_language=end[2];
+ mysql->server_status=uint2korr(end+3);
+ }
/* Save connection information */
if (!user) user="";
@@ -713,7 +718,7 @@ mc_mysql_connect(MYSQL *mysql,const char *host, const char *user,
mysql->unix_socket=0;
strmov(mysql->server_version,(char*) net->read_pos+1);
mysql->port=port;
- mysql->client_flag=client_flag | mysql->options.client_flag;
+ client_flag|=mysql->options.client_flag;
DBUG_PRINT("info",("Server version = '%s' capabilites: %ld",
mysql->server_version,mysql->server_capabilities));
@@ -721,6 +726,10 @@ mc_mysql_connect(MYSQL *mysql,const char *host, const char *user,
client_flag|=CLIENT_CAPABILITIES;
#ifdef HAVE_OPENSSL
+ if (mysql->options.ssl_key || mysql->options.ssl_cert ||
+ mysql->options.ssl_ca || mysql->options.ssl_capath ||
+ mysql->options.ssl_cipher)
+ mysql->options.use_ssl= 1;
if (mysql->options.use_ssl)
client_flag|=CLIENT_SSL;
#endif /* HAVE_OPENSSL */
@@ -728,8 +737,8 @@ mc_mysql_connect(MYSQL *mysql,const char *host, const char *user,
if (db)
client_flag|=CLIENT_CONNECT_WITH_DB;
#ifdef HAVE_COMPRESS
- if (mysql->server_capabilities & CLIENT_COMPRESS &&
- (mysql->options.compress || client_flag & CLIENT_COMPRESS))
+ if ((mysql->server_capabilities & CLIENT_COMPRESS) &&
+ (mysql->options.compress || (client_flag & CLIENT_COMPRESS)))
client_flag|=CLIENT_COMPRESS; /* We will use compression */
else
#endif
@@ -756,55 +765,54 @@ mc_mysql_connect(MYSQL *mysql,const char *host, const char *user,
mysql->client_flag=client_flag;
#ifdef HAVE_OPENSSL
- if ((mysql->server_capabilities & CLIENT_SSL) &&
- (mysql->options.use_ssl || (client_flag & CLIENT_SSL)))
- {
- DBUG_PRINT("info", ("Changing IO layer to SSL"));
- client_flag |= CLIENT_SSL;
- }
- else
- {
- if (client_flag & CLIENT_SSL)
- {
- DBUG_PRINT("info", ("Leaving IO layer intact because server doesn't support SSL"));
- }
- client_flag &= ~CLIENT_SSL;
- }
- /* Oops.. are we careful enough to not send ANY information */
- /* without encryption? */
+ /*
+ Oops.. are we careful enough to not send ANY information without
+ encryption?
+ */
if (client_flag & CLIENT_SSL)
{
if (my_net_write(net,buff,(uint) (2)) || net_flush(net))
+ {
+ net->last_errno= CR_SERVER_LOST;
+ strmov(net->last_error,ER(net->last_errno));
goto error;
+ }
/* Do the SSL layering. */
DBUG_PRINT("info", ("IO layer change in progress..."));
DBUG_PRINT("info", ("IO context %p",((struct st_VioSSLConnectorFd*)mysql->connector_fd)->ssl_context_));
- sslconnect((struct st_VioSSLConnectorFd*)(mysql->connector_fd),mysql->net.vio,60L);
+ sslconnect((struct st_VioSSLConnectorFd*)(mysql->connector_fd),mysql->net.vio, (long)(mysql->options.connect_timeout));
DBUG_PRINT("info", ("IO layer change done!"));
}
#endif /* HAVE_OPENSSL */
+ max_allowed_packet=mysql->net.max_packet_size;
int3store(buff+2,max_allowed_packet);
if (user && user[0])
strmake(buff+5,user,32);
else
- {
- user = getenv("USER");
- if(!user) user = "mysql";
- strmov((char*) buff+5, user );
- }
+ {
+ user = getenv("USER");
+ if (!user) user = "mysql";
+ strmov((char*) buff+5, user );
+ }
DBUG_PRINT("info",("user: %s",buff+5));
end=scramble(strend(buff+5)+1, mysql->scramble_buff, passwd,
(my_bool) (mysql->protocol_version == 9));
if (db)
{
- end=strmov(end+1,db);
+ end=strmake(end+1,db,NAME_LEN);
mysql->db=my_strdup(db,MYF(MY_WME));
+ db=0;
+ }
+ if (my_net_write(net,buff,(ulong) (end-buff)) || net_flush(net))
+ {
+ net->last_errno= CR_SERVER_LOST;
+ strmov(net->last_error,ER(net->last_errno));
+ goto error;
}
- if (my_net_write(net,buff,(uint) (end-buff)) || net_flush(net) ||
- mc_net_safe_read(mysql) == packet_error)
+ if (mc_net_safe_read(mysql) == packet_error)
goto error;
if (client_flag & CLIENT_COMPRESS) /* We will use compression */
net->compress=1;
@@ -839,10 +847,12 @@ mysql_ssl_clear(MYSQL *mysql)
my_free(mysql->options.ssl_cert, MYF(MY_ALLOW_ZERO_PTR));
my_free(mysql->options.ssl_ca, MYF(MY_ALLOW_ZERO_PTR));
my_free(mysql->options.ssl_capath, MYF(MY_ALLOW_ZERO_PTR));
+ my_free(mysql->options.ssl_cipher, MYF(MY_ALLOW_ZERO_PTR));
mysql->options.ssl_key = 0;
mysql->options.ssl_cert = 0;
mysql->options.ssl_ca = 0;
mysql->options.ssl_capath = 0;
+ mysql->options.ssl_cipher= 0;
mysql->options.use_ssl = FALSE;
my_free(mysql->connector_fd,MYF(MY_ALLOW_ZERO_PTR));
mysql->connector_fd = 0;
@@ -876,7 +886,6 @@ mc_mysql_close(MYSQL *mysql)
/* Clear pointers for better safety */
mysql->host_info=mysql->user=mysql->passwd=mysql->db=0;
bzero((char*) &mysql->options,sizeof(mysql->options));
- mysql->net.vio = 0;
#ifdef HAVE_OPENSSL
mysql_ssl_clear(mysql);
#endif /* HAVE_OPENSSL */
@@ -964,13 +973,13 @@ mc_unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields,
DBUG_RETURN(result);
}
-int
-mc_mysql_send_query(MYSQL* mysql, const char* query, uint length)
+int mc_mysql_send_query(MYSQL* mysql, const char* query, uint length)
{
return mc_simple_command(mysql, COM_QUERY, query, length, 1);
}
-int mc_mysql_read_query_result(MYSQL *mysql)
+
+int mc_mysql_read_query_result(MYSQL *mysql)
{
uchar *pos;
ulong field_count;
diff --git a/sql/mini_client.h b/sql/mini_client.h
index 6721b072080..24c13646170 100644
--- a/sql/mini_client.h
+++ b/sql/mini_client.h
@@ -19,23 +19,18 @@
MYSQL* mc_mysql_connect(MYSQL *mysql,const char *host, const char *user,
- const char *passwd, const char *db,
- uint port, const char *unix_socket,uint client_flag);
-
-int mc_simple_command(MYSQL *mysql,enum enum_server_command command, const char *arg,
- uint length, my_bool skipp_check);
+ const char *passwd, const char *db,
+ uint port, const char *unix_socket,uint client_flag,
+ uint net_read_timeout);
+int mc_simple_command(MYSQL *mysql,enum enum_server_command command,
+ const char *arg, uint length, my_bool skipp_check);
void mc_mysql_close(MYSQL *mysql);
-
-MYSQL * mc_mysql_init(MYSQL *mysql);
-
+MYSQL *mc_mysql_init(MYSQL *mysql);
void mc_mysql_debug(const char *debug);
-
ulong mc_net_safe_read(MYSQL *mysql);
-
-char * mc_mysql_error(MYSQL *mysql);
+char *mc_mysql_error(MYSQL *mysql);
int mc_mysql_errno(MYSQL *mysql);
my_bool mc_mysql_reconnect(MYSQL* mysql);
-
int mc_mysql_send_query(MYSQL* mysql, const char* query, uint length);
int mc_mysql_read_query_result(MYSQL *mysql);
int mc_mysql_query(MYSQL *mysql, const char *query, uint length);
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 9fff4880573..61973c5af91 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -14,14 +14,11 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-#ifndef _MYSQL_PRIV_H
-#define _MYSQL_PRIV_H
-
#include <my_global.h>
-#include "mysql_embed.h"
+#include <mysql_version.h>
+#include <mysql_embed.h>
#include <my_sys.h>
#include <m_string.h>
-#include <mysql_version.h>
#include <hash.h>
#include <signal.h>
#include <thr_lock.h>
@@ -29,7 +26,7 @@
#include <my_bitmap.h>
#ifdef __EMX__
-#undef write // remove pthread.h macro definition for EMX
+#undef write /* remove pthread.h macro definition for EMX */
#endif
typedef ulong table_map; /* Used for table bits in join */
@@ -48,7 +45,7 @@ char *sql_strmake(const char *str,uint len);
gptr sql_memdup(const void * ptr,unsigned size);
void sql_element_free(void *ptr);
void kill_one_thread(THD *thd, ulong id);
-int net_request_file(NET* net, const char* fname);
+bool net_request_file(NET* net, const char* fname);
char* query_table_status(THD *thd,const char *db,const char *table_name);
#define x_free(A) { my_free((gptr) (A),MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR)); }
@@ -75,14 +72,14 @@ char* query_table_status(THD *thd,const char *db,const char *table_name);
#define MAX_FIELDS_BEFORE_HASH 32
#define USER_VARS_HASH_SIZE 16
#define STACK_MIN_SIZE 8192 // Abort if less stack during eval.
-#define STACK_BUFF_ALLOC 32 // For stack overrun checks
+#define STACK_BUFF_ALLOC 64 // For stack overrun checks
#ifndef MYSQLD_NET_RETRY_COUNT
#define MYSQLD_NET_RETRY_COUNT 10 // Abort read after this many int.
#endif
#define TEMP_POOL_SIZE 128
/*
The following parameters is to decide when to use an extra cache to
- optimise seeks when reading a big table in sorted order
+ optimise seeks when reading a big table in sorted order
*/
#define MIN_FILE_LENGTH_TO_USE_ROW_CACHE (16L*1024*1024)
#define MIN_ROWS_TO_USE_TABLE_CACHE 100
@@ -165,29 +162,34 @@ char* query_table_status(THD *thd,const char *db,const char *table_name);
#define OPTION_BIG_SELECTS 1024 /* for SQL OPTION */
#define OPTION_LOG_OFF 2048
#define OPTION_UPDATE_LOG 4096 /* update log flag */
-#define OPTION_LOW_PRIORITY_UPDATES 8192
+#define TMP_TABLE_ALL_COLUMNS 8192
#define OPTION_WARNINGS 16384
#define OPTION_AUTO_IS_NULL 32768
#define OPTION_FOUND_COMMENT 65536L
#define OPTION_SAFE_UPDATES OPTION_FOUND_COMMENT*2
#define OPTION_BUFFER_RESULT OPTION_SAFE_UPDATES*2
#define OPTION_BIN_LOG OPTION_BUFFER_RESULT*2
-#define OPTION_NOT_AUTO_COMMIT OPTION_BIN_LOG*2
-#define OPTION_BEGIN OPTION_NOT_AUTO_COMMIT*2
+#define OPTION_NOT_AUTOCOMMIT OPTION_BIN_LOG*2
+#define OPTION_BEGIN OPTION_NOT_AUTOCOMMIT*2
#define OPTION_TABLE_LOCK OPTION_BEGIN*2
#define OPTION_QUICK OPTION_TABLE_LOCK*2
#define OPTION_QUOTE_SHOW_CREATE OPTION_QUICK*2
#define OPTION_INTERNAL_SUBTRANSACTIONS OPTION_QUOTE_SHOW_CREATE*2
/* Set if we are updating a non-transaction safe table */
-#define OPTION_STATUS_NO_TRANS_UPDATE OPTION_INTERNAL_SUBTRANSACTIONS*2
+#define OPTION_STATUS_NO_TRANS_UPDATE OPTION_INTERNAL_SUBTRANSACTIONS*2
/* The following is set when parsing the query */
#define QUERY_NO_INDEX_USED OPTION_STATUS_NO_TRANS_UPDATE*2
#define QUERY_NO_GOOD_INDEX_USED QUERY_NO_INDEX_USED*2
-
-#define SELECT_NO_UNLOCK (QUERY_NO_GOOD_INDEX_USED*2)
-#define TMP_TABLE_ALL_COLUMNS (SELECT_NO_UNLOCK*2)
+/* The following can be set when importing tables in a 'wrong order'
+ to suppress foreign key checks */
+#define OPTION_NO_FOREIGN_KEY_CHECKS QUERY_NO_GOOD_INDEX_USED*2
+/* The following speeds up inserts to InnoDB tables by suppressing unique
+ key checks in some cases */
+#define OPTION_RELAXED_UNIQUE_CHECKS OPTION_NO_FOREIGN_KEY_CHECKS*2
+#define SELECT_NO_UNLOCK ((ulong) OPTION_RELAXED_UNIQUE_CHECKS*2)
+/* NOTE: we have now used up all 32 bits of the OPTION flag! */
/* Bits for different SQL modes modes (including ANSI mode) */
#define MODE_REAL_AS_FLOAT 1
@@ -200,18 +202,20 @@ char* query_table_status(THD *thd,const char *db,const char *table_name);
#define RAID_BLOCK_SIZE 1024
-// Sync points allow us to force the server to reach a certain line of code
-// and block there until the client tells the server it is ok to go on.
-// The client tells the server to block with SELECT GET_LOCK()
-// and unblocks it with SELECT RELEASE_LOCK(). Used for debugging difficult
-// concurrency problems
#ifdef EXTRA_DEBUG
+/*
+ Sync points allow us to force the server to reach a certain line of code
+ and block there until the client tells the server it is ok to go on.
+ The client tells the server to block with SELECT GET_LOCK()
+ and unblocks it with SELECT RELEASE_LOCK(). Used for debugging difficult
+ concurrency problems
+*/
#define DBUG_SYNC_POINT(lock_name,lock_timeout) \
debug_sync_point(lock_name,lock_timeout)
void debug_sync_point(const char* lock_name, uint lock_timeout);
#else
#define DBUG_SYNC_POINT(lock_name,lock_timeout)
-#endif
+#endif /* EXTRA_DEBUG */
/* BINLOG_DUMP options */
@@ -292,10 +296,13 @@ inline THD *_current_thd(void)
int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create, bool silent);
int mysql_alter_db(THD *thd, char *db, HA_CREATE_INFO *create, bool silent);
int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent);
-void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags);
+void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos, ushort flags);
int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists);
int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
bool log_query);
+int mysql_rm_table_part2_with_lock(THD *thd, TABLE_LIST *tables,
+ bool if_exists,
+ bool log_query);
int quick_rm_table(enum db_type base,const char *db,
const char *table_name);
bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list);
@@ -322,11 +329,11 @@ void table_cache_free(void);
uint cached_tables(void);
void kill_mysql(void);
void close_connection(NET *net,uint errcode=0,bool lock=1);
-bool check_access(THD *thd,uint access,const char *db=0,uint *save_priv=0,
+bool check_access(THD *thd, ulong access, const char *db=0, ulong *save_priv=0,
bool no_grant=0, bool no_errors=0);
-bool check_table_access(THD *thd,uint want_access, TABLE_LIST *tables,
+bool check_table_access(THD *thd, ulong want_access, TABLE_LIST *tables,
bool no_errors=0);
-bool check_process_priv(THD *thd=0);
+bool check_global_access(THD *thd, ulong want_access);
int mysql_backup_table(THD* thd, TABLE_LIST* table_list);
int mysql_restore_table(THD* thd, TABLE_LIST* table_list);
@@ -339,6 +346,7 @@ int mysql_analyze_table(THD* thd, TABLE_LIST* table_list,
HA_CHECK_OPT* check_opt);
int mysql_optimize_table(THD* thd, TABLE_LIST* table_list,
HA_CHECK_OPT* check_opt);
+bool check_simple_select();
/* net_pkg.c */
void send_warning(NET *net, uint sql_errno, const char *err=0);
@@ -367,7 +375,8 @@ SORT_FIELD * make_unireg_sortorder(ORDER *order, uint *length);
int setup_order(THD *thd,TABLE_LIST *tables, List<Item> &fields,
List <Item> &all_fields, ORDER *order);
int setup_group(THD *thd,TABLE_LIST *tables,List<Item> &fields,
- List<Item> &all_fields, ORDER *order, bool *hidden_group_fields);
+ List<Item> &all_fields, ORDER *order,
+ bool *hidden_group_fields);
int handle_select(THD *thd, LEX *lex, select_result *result);
int mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &list,COND *conds,
@@ -382,14 +391,7 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
int mysql_create_table(THD *thd,const char *db, const char *table_name,
HA_CREATE_INFO *create_info,
List<create_field> &fields, List<Key> &keys,
- bool tmp_table, bool no_log, uint select_field_count);
-/*
- no_log is needed for the case of CREATE ... SELECT,
- as the logging will be done later in sql_insert.cc
- select_field_count is also used for CREATE ... SELECT,
- and must be zero for standart create of table
-*/
-
+ bool tmp_table, bool no_log);
TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
const char *db, const char *name,
List<create_field> *extra_fields,
@@ -481,7 +483,8 @@ int mysqld_show_create_db(THD *thd, const char *dbname);
void mysqld_list_processes(THD *thd,const char *user,bool verbose);
int mysqld_show_status(THD *thd);
int mysqld_show_variables(THD *thd,const char *wild);
-int mysqld_show(THD *thd, const char *wild, show_var_st *variables);
+int mysqld_show(THD *thd, const char *wild, show_var_st *variables,
+ enum enum_var_type value_type);
int mysqld_show_charsets(THD *thd,const char *wild);
int mysqld_show_table_types(THD *thd);
int mysqld_show_privileges(THD *thd);
@@ -492,8 +495,8 @@ void mysql_com_prepare(THD *thd,char*packet,uint packet_length);
void mysql_init_query(THD *thd);/* sql_parse. cc */
void mysql_com_execute(THD *thd);
void mysql_com_longdata(THD *thd);
-int check_insert_fields(THD *thd,TABLE *table,List<Item> &fields,
- List<Item> &values, ulong counter);
+int check_insert_fields(THD *thd,TABLE *table,List<Item> &fields,
+ List<Item> &values, ulong counter);
/* sql_error.cc */
void push_error(uint code, const char *msg);
@@ -584,8 +587,6 @@ 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;
-extern pthread_mutex_t LOCK_manager;
-extern pthread_cond_t COND_manager;
pthread_handler_decl(handle_manager, arg);
/* sql_test.cc */
@@ -609,34 +610,75 @@ void sql_print_error(const char *format,...)
__attribute__ ((format (printf, 1, 2)));
bool fn_format_relative_to_data_home(my_string to, const char *name,
const char *dir, const char *extension);
-void open_log(MYSQL_LOG *log, const char *hostname,
- const char *opt_name, const char *extension,
+bool open_log(MYSQL_LOG *log, const char *hostname,
+ const char *opt_name, const char *extension,
+ const char *index_file_name,
enum_log_type type, bool read_append = 0,
bool no_auto_events = 0);
-extern uint32 server_id;
+/*
+ External variables
+*/
+
+extern time_t start_time;
extern char *mysql_data_home,server_version[SERVER_VERSION_LENGTH],
- mysql_real_data_home[];
+ mysql_real_data_home[], *charsets_list;
extern my_string mysql_tmpdir;
+extern const char *command_name[];
extern const char *first_keyword, *localhost, *delayed_user;
-extern ulong refresh_version,flush_version, thread_id,query_id,opened_tables,
- created_tmp_tables, created_tmp_disk_tables,
- aborted_threads,aborted_connects,
- delayed_insert_timeout,
- delayed_insert_limit, delayed_queue_size,
- delayed_insert_threads, delayed_insert_writes,
- delayed_rows_in_use,delayed_insert_errors;
+extern const char **errmesg; /* Error messages */
+extern const char *myisam_recover_options_str;
+extern uchar *days_in_month;
+extern char language[LIBLEN],reg_ext[FN_EXTLEN];
+extern char glob_hostname[FN_REFLEN], mysql_home[FN_REFLEN];
+extern char pidfile_name[FN_REFLEN], time_zone[30], *opt_init_file;
+extern char blob_newline;
+extern double log_10[32];
+extern ulong refresh_version,flush_version, thread_id,query_id,opened_tables;
+extern ulong created_tmp_tables, created_tmp_disk_tables;
+extern ulong aborted_threads,aborted_connects;
+extern ulong delayed_insert_timeout;
+extern ulong delayed_insert_limit, delayed_queue_size;
+extern ulong delayed_insert_threads, delayed_insert_writes;
+extern ulong delayed_rows_in_use,delayed_insert_errors;
extern ulong filesort_rows, filesort_range_count, filesort_scan_count;
extern ulong filesort_merge_passes;
extern ulong select_range_check_count, select_range_count, select_scan_count;
-extern ulong select_full_range_join_count,select_full_join_count,
- slave_open_temp_tables;
-extern uint test_flags,select_errors,ha_open_options;
+extern ulong select_full_range_join_count,select_full_join_count;
+extern ulong slave_open_temp_tables, query_cache_size;
extern ulong thd_startup_options, slow_launch_threads, slow_launch_time;
-extern ulong query_cache_startup_type;
-extern time_t start_time;
-extern const char *command_name[];
-extern I_List<THD> threads;
+extern ulong server_id, concurrency;
+extern ulong ha_read_count, ha_write_count, ha_delete_count, ha_update_count;
+extern ulong ha_read_key_count, ha_read_next_count, ha_read_prev_count;
+extern ulong ha_read_first_count, ha_read_last_count;
+extern ulong ha_read_rnd_count, ha_read_rnd_next_count;
+extern ulong ha_commit_count, ha_rollback_count;
+extern ulong keybuff_size,table_cache_size;
+extern ulong max_connections,max_connect_errors, connect_timeout;
+extern ulong max_insert_delayed_threads, max_user_connections;
+extern ulong long_query_count, what_to_log,flush_time,opt_sql_mode;
+extern ulong query_buff_size, thread_stack,thread_stack_min;
+extern ulong binlog_cache_size, max_binlog_cache_size, open_files_limit;
+extern ulong max_binlog_size, rpl_recovery_rank, thread_cache_size;
+extern ulong com_stat[(uint) SQLCOM_END], com_other, back_log;
+extern ulong specialflag, current_pid;
+
+extern uint test_flags,select_errors,ha_open_options;
+extern uint protocol_version,dropping_tables;
+extern uint delay_key_write_options;
+extern bool opt_endinfo, using_udf_functions, locked_in_memory;
+extern bool opt_using_transactions, mysql_embedded;
+extern bool using_update_log, opt_large_files;
+extern bool opt_log, opt_update_log, opt_bin_log, opt_slow_log;
+extern bool opt_disable_networking, opt_skip_show_db;
+extern bool volatile abort_loop, shutdown_in_progress, grant_option;
+extern uint volatile thread_count, thread_running, global_read_lock;
+extern my_bool opt_sql_bin_update, opt_safe_user_create, opt_no_mix_types;
+extern my_bool opt_safe_show_db, opt_local_infile, lower_case_table_names;
+extern my_bool opt_slave_compressed_protocol, use_temp_pool;
+extern my_bool opt_enable_named_pipe;
+extern char f_fyllchar;
+
extern MYSQL_LOG mysql_log,mysql_update_log,mysql_slow_log,mysql_bin_log;
extern FILE *bootstrap_file;
extern pthread_key(MEM_ROOT*,THR_MALLOC);
@@ -645,59 +687,33 @@ extern pthread_mutex_t LOCK_mysql_create_db,LOCK_Acl,LOCK_open,
LOCK_thread_count,LOCK_mapped_file,LOCK_user_locks, LOCK_status,
LOCK_grant, LOCK_error_log, LOCK_delayed_insert,
LOCK_delayed_status, LOCK_delayed_create, LOCK_crypt, LOCK_timezone,
- LOCK_server_id, LOCK_slave_list, LOCK_active_mi;
-extern pthread_cond_t COND_refresh,COND_thread_count;
+ LOCK_slave_list, LOCK_active_mi, LOCK_manager,
+ LOCK_global_system_variables;
+extern pthread_cond_t COND_refresh, COND_thread_count, COND_manager;
extern pthread_attr_t connection_attrib;
-extern bool opt_endinfo, using_udf_functions, locked_in_memory,
- opt_using_transactions, use_temp_pool, mysql_embedded;
-extern my_bool opt_local_infile;
-extern char f_fyllchar;
-extern ulong ha_read_count, ha_write_count, ha_delete_count, ha_update_count,
- ha_read_key_count, ha_read_next_count, ha_read_prev_count,
- ha_read_first_count, ha_read_last_count,
- ha_read_rnd_count, ha_read_rnd_next_count,
- ha_commit_count, ha_rollback_count;
+extern I_List<THD> threads;
extern MY_BITMAP temp_pool;
-extern uchar *days_in_month;
extern DATE_FORMAT dayord;
-extern double log_10[32];
-extern uint protocol_version,dropping_tables;
-extern ulong keybuff_size,sortbuff_size,max_item_sort_length,table_cache_size,
- max_join_size,join_buff_size,tmp_table_size,
- max_connections,max_connect_errors,long_query_time,
- max_insert_delayed_threads, max_user_connections,
- long_query_count,net_wait_timeout,net_interactive_timeout,
- net_read_timeout,net_write_timeout,
- what_to_log,flush_time,opt_sql_mode,
- max_tmp_tables,max_heap_table_size,query_buff_size,
- lower_case_table_names,thread_stack,thread_stack_min,
- binlog_cache_size, max_binlog_cache_size, record_rnd_cache_size;
-extern ulong com_stat[(uint) SQLCOM_END], com_other;
-extern ulong specialflag, current_pid;
-extern bool low_priority_updates, using_update_log;
-extern bool opt_sql_bin_update, opt_safe_show_db, opt_warnings,
- opt_safe_user_create, opt_no_mix_types;
-extern char language[LIBLEN],reg_ext[FN_EXTLEN],blob_newline;
-extern const char **errmesg; /* Error messages */
-extern const char *default_tx_isolation_name;
extern String empty_string;
-extern struct show_var_st init_vars[];
-extern struct show_var_st status_vars[];
+extern SHOW_VAR init_vars[],status_vars[], internal_vars[];
extern struct show_table_type_st table_type_vars[];
extern SHOW_COMP_OPTION have_isam;
extern SHOW_COMP_OPTION have_innodb;
extern SHOW_COMP_OPTION have_berkeley_db;
-extern enum db_type default_table_type;
-extern enum enum_tx_isolation default_tx_isolation;
-extern char glob_hostname[FN_REFLEN];
+extern struct system_variables global_system_variables;
+extern struct system_variables max_system_variables;
+
+/* optional things, have_* variables */
+
+extern SHOW_COMP_OPTION have_isam, have_innodb, have_berkeley_db;
+extern SHOW_COMP_OPTION have_raid, have_openssl, have_symlink;
+extern SHOW_COMP_OPTION have_query_cache, have_berkeley_db, have_innodb;
+
#ifndef __WIN__
extern pthread_t signal_thread;
#endif
-extern bool volatile abort_loop, shutdown_in_progress, grant_option;
-extern uint volatile thread_count, thread_running, global_read_lock;
-
MYSQL_LOCK *mysql_lock_tables(THD *thd,TABLE **table,uint count);
void mysql_unlock_tables(THD *thd, MYSQL_LOCK *sql_lock);
void mysql_unlock_read_tables(THD *thd, MYSQL_LOCK *sql_lock);
@@ -795,11 +811,14 @@ void hostname_cache_free();
void hostname_cache_refresh(void);
bool get_interval_info(const char *str,uint length,uint count,
long *values);
-/* sql_cache */
+/* sql_cache.cc */
extern bool sql_cache_init();
extern void sql_cache_free();
extern int sql_cache_hit(THD *thd, char *inBuf, uint length);
+/* item.cc */
+Item *get_system_var(enum_var_type var_type, LEX_STRING name);
+
/* Some inline functions for more speed */
inline bool add_item_to_list(Item *item)
@@ -824,5 +843,3 @@ inline void mark_as_null_row(TABLE *table)
table->status|=STATUS_NULL_ROW;
bfill(table->null_flags,table->null_bytes,255);
}
-
-#endif
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 59630644e5a..89f1c07b2fe 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -15,7 +15,6 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "mysql_priv.h"
-#include <mysql.h>
#include <m_ctype.h>
#include <my_dir.h>
#include "sql_acl.h"
@@ -38,14 +37,14 @@
#define ONE_THREAD
#endif
-#ifdef SAFEMALLOC
-#define SHUTDOWN_THD shutdown_th=pthread_self();
-#define MAIN_THD main_th=pthread_self();
-#define SIGNAL_THD signal_th=pthread_self();
-#else
#define SHUTDOWN_THD
#define MAIN_THD
#define SIGNAL_THD
+
+#ifdef PURIFY
+#define IF_PURIFY(A,B) (A)
+#else
+#define IF_PURIFY(A,B) (B)
#endif
/* stack traces are only supported on linux intel */
@@ -102,14 +101,14 @@ extern "C" { // Because of SCO 3.2V4.2
int allow_severity = LOG_INFO;
int deny_severity = LOG_WARNING;
-#ifdef __linux__
-#define my_fromhost(A) fromhost()
-#define my_hosts_access(A) hosts_access()
-#define my_eval_client(A) eval_client()
-#else
+#ifdef __STDC__
#define my_fromhost(A) fromhost(A)
#define my_hosts_access(A) hosts_access(A)
#define my_eval_client(A) eval_client(A)
+#else
+#define my_fromhost(A) fromhost()
+#define my_hosts_access(A) hosts_access()
+#define my_eval_client(A) eval_client()
#endif
#endif /* HAVE_LIBWRAP */
@@ -182,10 +181,11 @@ static SECURITY_DESCRIPTOR sdPipeDescriptor;
static HANDLE hPipe = INVALID_HANDLE_VALUE;
static pthread_cond_t COND_handler_count;
static uint handler_count;
-static bool opt_enable_named_pipe = 0;
#endif
#ifdef __WIN__
-static bool opt_console=0,start_mode=0;
+static bool opt_console=0, start_mode=0, use_opt_args;
+static int opt_argc;
+static char **opt_argv;
#endif
/* Set prefix for windows binary */
@@ -229,37 +229,55 @@ SHOW_COMP_OPTION have_openssl=SHOW_OPTION_YES;
#else
SHOW_COMP_OPTION have_openssl=SHOW_OPTION_NO;
#endif
+#ifdef HAVE_BROKEN_REALPATH
+SHOW_COMP_OPTION have_symlink=SHOW_OPTION_NO;
+#else
SHOW_COMP_OPTION have_symlink=SHOW_OPTION_YES;
+#endif
#ifdef HAVE_QUERY_CACHE
SHOW_COMP_OPTION have_query_cache=SHOW_OPTION_YES;
#else
SHOW_COMP_OPTION have_query_cache=SHOW_OPTION_NO;
#endif
-bool opt_skip_slave_start = 0; // If set, slave is not autostarted
+bool opt_large_files= sizeof(my_off_t) > 4;
+
+/*
+ Variables to store startup options
+*/
+
+my_bool opt_skip_slave_start = 0; // If set, slave is not autostarted
+/*
+ If set, some standard measures to enforce slave data integrity will not
+ be performed
+*/
+my_bool opt_reckless_slave = 0;
+
+ulong back_log, connect_timeout, concurrency;
+char mysql_home[FN_REFLEN], pidfile_name[FN_REFLEN], time_zone[30];
+bool opt_log, opt_update_log, opt_bin_log, opt_slow_log;
+bool opt_disable_networking=0, opt_skip_show_db=0;
+my_bool opt_enable_named_pipe= 0;
+my_bool opt_local_infile, opt_external_locking, opt_slave_compressed_protocol;
+uint delay_key_write_options= (uint) DELAY_KEY_WRITE_ON;
-/* if set, some standard measures to enforce
- slave data intergity will not be performed
- */
-bool opt_reckless_slave = 0;
static bool opt_do_pstack = 0;
static ulong opt_specialflag=SPECIAL_ENGLISH;
-static ulong back_log,connect_timeout,concurrency;
+
static ulong opt_myisam_block_size;
static my_socket unix_sock= INVALID_SOCKET,ip_sock= INVALID_SOCKET;
static my_string opt_logname=0,opt_update_logname=0,
opt_binlog_index_name = 0,opt_slow_logname=0;
-static char mysql_home[FN_REFLEN],pidfile_name[FN_REFLEN];
+
static char* mysql_home_ptr= mysql_home;
static char* pidfile_name_ptr= pidfile_name;
static pthread_t select_thread;
-static bool opt_log,opt_update_log,opt_bin_log,opt_slow_log,opt_noacl,
- opt_disable_networking=0, opt_bootstrap=0,opt_skip_show_db=0,
- opt_myisam_log=0,
- opt_large_files=sizeof(my_off_t) > 4;
-bool opt_sql_bin_update = 0, opt_log_slave_updates = 0, opt_safe_show_db=0,
- opt_show_slave_auth_info = 0, opt_old_rpl_compat = 0,
- opt_safe_user_create = 0, opt_no_mix_types = 0;
+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 opt_show_slave_auth_info, opt_sql_bin_update = 0;
+my_bool opt_log_slave_updates= 0;
+
volatile bool mqh_used = 0;
FILE *bootstrap_file=0;
int segfaulted = 0; // ensure we do not enter SIGSEGV handler twice
@@ -272,14 +290,13 @@ int segfaulted = 0; // ensure we do not enter SIGSEGV handler twice
static bool kill_in_progress=FALSE;
static struct rand_struct sql_rand;
static int cleanup_done;
-static char **defaults_argv,time_zone[30];
-static const char *default_table_type_name;
+static char **defaults_argv;
char glob_hostname[FN_REFLEN];
#include "sslopt-vars.h"
#ifdef HAVE_OPENSSL
char *des_key_file = 0;
-struct st_VioSSLAcceptorFd * ssl_acceptor_fd = 0;
+struct st_VioSSLAcceptorFd *ssl_acceptor_fd= 0;
#endif /* HAVE_OPENSSL */
I_List <i_string_pair> replicate_rewrite_db;
@@ -288,7 +305,7 @@ I_List<i_string> replicate_do_db, replicate_ignore_db;
I_List<i_string> binlog_do_db, binlog_ignore_db;
/* if we guessed server_id , we need to know about it */
-uint32 server_id = 0;
+ulong server_id= 0; // Must be long becasue of set_var.cc
bool server_id_supplied = 0;
uint mysql_port;
@@ -298,19 +315,21 @@ uint volatile thread_count=0, thread_running=0, kill_cached_threads=0,
ulong thd_startup_options=(OPTION_UPDATE_LOG | OPTION_AUTO_IS_NULL |
OPTION_BIN_LOG | OPTION_QUOTE_SHOW_CREATE );
uint protocol_version=PROTOCOL_VERSION;
-ulong keybuff_size,sortbuff_size,max_item_sort_length,table_cache_size,
- max_join_size,join_buff_size,tmp_table_size,thread_stack,
- thread_stack_min,net_wait_timeout,what_to_log= ~ (1L << (uint) COM_TIME),
- query_buff_size, lower_case_table_names, mysqld_net_retry_count,
- net_interactive_timeout, slow_launch_time = 2L,
- net_read_timeout,net_write_timeout,slave_open_temp_tables=0,
- open_files_limit=0, max_binlog_size, record_rnd_cache_size;
+struct system_variables global_system_variables;
+struct system_variables max_system_variables;
+ulong keybuff_size,table_cache_size,
+ thread_stack,
+ thread_stack_min,what_to_log= ~ (1L << (uint) COM_TIME),
+ query_buff_size,
+ slow_launch_time = 2L,
+ slave_open_temp_tables=0,
+ open_files_limit=0, max_binlog_size;
ulong com_stat[(uint) SQLCOM_END], com_other;
ulong slave_net_timeout;
ulong thread_cache_size=0, binlog_cache_size=0, max_binlog_cache_size=0;
ulong query_cache_size=0;
#ifdef HAVE_QUERY_CACHE
-ulong query_cache_limit=0, query_cache_startup_type=1;
+ulong query_cache_limit=0;
Query_cache query_cache;
#endif
@@ -329,16 +348,15 @@ uint master_port = MYSQL_PORT, master_connect_retry = 60;
uint report_port = MYSQL_PORT;
bool master_ssl = 0;
-ulong max_tmp_tables,max_heap_table_size,master_retry_count=0;
+ulong master_retry_count=0;
ulong bytes_sent = 0L, bytes_received = 0L;
-bool opt_endinfo,using_udf_functions,low_priority_updates, locked_in_memory;
-bool opt_using_transactions, using_update_log, opt_warnings=0;
-my_bool opt_local_infile=1;
+bool opt_endinfo,using_udf_functions, locked_in_memory;
+bool opt_using_transactions, using_update_log;
bool volatile abort_loop,select_thread_in_use,grant_option;
bool volatile ready_to_exit,shutdown_in_progress;
ulong refresh_version=1L,flush_version=1L; /* Increments on each reload */
-ulong query_id=1L,long_query_count,long_query_time,aborted_threads,
+ulong query_id=1L,long_query_count,aborted_threads,
aborted_connects,delayed_insert_timeout,delayed_insert_limit,
delayed_queue_size,delayed_insert_threads,delayed_insert_writes,
delayed_rows_in_use,delayed_insert_errors,flush_time, thread_created;
@@ -352,15 +370,13 @@ ulong max_connections,max_insert_delayed_threads,max_used_connections,
max_connect_errors, max_user_connections = 0;
ulong thread_id=1L,current_pid;
ulong slow_launch_threads = 0;
-ulong myisam_max_sort_file_size, myisam_max_extra_sort_file_size;
char mysql_real_data_home[FN_REFLEN],
language[LIBLEN],reg_ext[FN_EXTLEN],
- default_charset[LIBLEN],mysql_charsets_dir[FN_REFLEN], *charsets_list,
+ mysql_charsets_dir[FN_REFLEN], *charsets_list,
blob_newline,f_fyllchar,max_sort_char,*mysqld_user,*mysqld_chroot,
*opt_init_file;
char *language_ptr= language;
-char *default_charset_ptr= default_charset;
#ifndef EMBEDDED_LIBRARY
char mysql_data_home_buff[2], *mysql_data_home=mysql_data_home_buff;
bool mysql_embedded=0;
@@ -376,12 +392,9 @@ const char *first_keyword="first";
const char **errmesg; /* Error messages */
const char *myisam_recover_options_str="OFF";
const char *sql_mode_str="OFF";
-const char *default_tx_isolation_name;
-enum_tx_isolation default_tx_isolation=ISO_READ_COMMITTED;
+ulong rpl_recovery_rank=0;
-uint rpl_recovery_rank=0;
-
-my_string mysql_unix_port=NULL, mysql_tmpdir=NULL, allocated_mysql_tmpdir=NULL;
+my_string mysql_unix_port=NULL, opt_mysql_tmpdir=NULL, mysql_tmpdir=NULL;
ulong my_bind_addr; /* the address we bind to */
DATE_FORMAT dayord;
double log_10[32]; /* 10 potences */
@@ -396,7 +409,7 @@ TYPELIB sql_mode_typelib= {array_elements(sql_mode_names)-1,"",
sql_mode_names};
MY_BITMAP temp_pool;
-bool use_temp_pool=0;
+my_bool use_temp_pool=0;
pthread_key(MEM_ROOT*,THR_MALLOC);
pthread_key(THD*, THR_THD);
@@ -406,15 +419,14 @@ pthread_mutex_t LOCK_mysql_create_db, LOCK_Acl, LOCK_open, LOCK_thread_count,
LOCK_error_log,
LOCK_delayed_insert, LOCK_delayed_status, LOCK_delayed_create,
LOCK_crypt, LOCK_bytes_sent, LOCK_bytes_received,
- LOCK_server_id,
+ LOCK_global_system_variables,
LOCK_user_conn, LOCK_slave_list, LOCK_active_mi;
-pthread_cond_t COND_refresh,COND_thread_count,COND_binlog_update,
- COND_slave_stopped, COND_slave_start;
+pthread_cond_t COND_refresh,COND_thread_count, COND_slave_stopped,
+ COND_slave_start;
pthread_cond_t COND_thread_cache,COND_flush_thread_cache;
pthread_t signal_thread;
pthread_attr_t connection_attrib;
-enum db_type default_table_type=DB_TYPE_MYISAM;
#ifdef __WIN__
#undef getpid
@@ -582,9 +594,7 @@ static void close_connections(void)
(void) pthread_mutex_unlock(&LOCK_thread_count); // For unlink from list
if (thread_count)
- {
sleep(1); // Give threads time to die
- }
/* Force remaining threads to die by closing the connection to the client */
@@ -638,29 +648,45 @@ static void close_server_sock()
if (tmp_sock != INVALID_SOCKET)
{
ip_sock=INVALID_SOCKET;
- DBUG_PRINT("info",("closing TCP/IP socket"));
+ DBUG_PRINT("info",("calling shutdown on TCP/IP socket"));
VOID(shutdown(tmp_sock,2));
+#ifdef NOT_USED
+ /*
+ The following code is disabled as it causes MySQL to hang on
+ AIX 4.3 during shutdown
+ */
+ DBUG_PRINT("info",("calling closesocket on TCP/IP socket"));
VOID(closesocket(tmp_sock));
+#endif
}
tmp_sock=unix_sock;
if (tmp_sock != INVALID_SOCKET)
{
unix_sock=INVALID_SOCKET;
- DBUG_PRINT("info",("closing Unix socket"));
+ DBUG_PRINT("info",("calling shutdown on unix socket"));
VOID(shutdown(tmp_sock,2));
+#ifdef NOT_USED
+ /*
+ The following code is disabled as it may cause MySQL to hang on
+ AIX 4.3 during shutdown (not tested, but likely)
+ */
+ DBUG_PRINT("info",("calling closesocket on unix/IP socket"));
VOID(closesocket(tmp_sock));
+#endif
VOID(unlink(mysql_unix_port));
}
DBUG_VOID_RETURN;
#endif
}
+
void kill_mysql(void)
{
DBUG_ENTER("kill_mysql");
#ifdef SIGNALS_DONT_BREAK_READ
- close_server_sock(); /* force accept to wake up */
+ abort_loop=1; // Break connection loops
+ close_server_sock(); // Force accept to wake up
#endif
#if defined(__WIN__)
@@ -681,17 +707,17 @@ void kill_mysql(void)
#elif defined(OS2)
pthread_cond_signal( &eventShutdown); // post semaphore
#elif defined(HAVE_PTHREAD_KILL)
- if (pthread_kill(signal_thread,SIGTERM)) /* End everything nicely */
+ if (pthread_kill(signal_thread, MYSQL_KILL_SIGNAL))
{
DBUG_PRINT("error",("Got error %d from pthread_kill",errno)); /* purecov: inspected */
}
#elif !defined(SIGNALS_DONT_BREAK_READ)
- kill(current_pid,SIGTERM);
+ kill(current_pid, MYSQL_KILL_SIGNAL);
#endif
DBUG_PRINT("quit",("After pthread_kill"));
shutdown_in_progress=1; // Safety if kill didn't work
#ifdef SIGNALS_DONT_BREAK_READ
- if (!abort_loop)
+ if (!kill_in_progress)
{
pthread_t tmp;
abort_loop=1;
@@ -732,7 +758,6 @@ static void __cdecl kill_server(int sig_ptr)
sql_print_error(ER(ER_GOT_SIGNAL),my_progname,sig); /* purecov: inspected */
#if defined(USE_ONE_SIGNAL_HAND) && !defined(__WIN__) && !defined(OS2)
- SHUTDOWN_THD;
my_thread_init(); // If this is a new thread
#endif
close_connections();
@@ -763,9 +788,12 @@ static pthread_handler_decl(kill_server_thread,arg __attribute__((unused)))
static sig_handler print_signal_warning(int sig)
{
- if (opt_warnings)
- sql_print_error("Warning: Got signal %d from thread %d",
- sig,my_thread_id());
+ if (!DBUG_IN_USE)
+ {
+ if (global_system_variables.log_warnings)
+ sql_print_error("Warning: Got signal %d from thread %d",
+ sig,my_thread_id());
+ }
#ifdef DONT_REMEMBER_SIGNAL
sigset(sig,print_signal_warning); /* int. thread system calls */
#endif
@@ -810,6 +838,7 @@ void clean_up(bool print_message)
hostname_cache_free();
item_user_lock_free();
lex_free(); /* Free some memory */
+ set_var_free();
#ifdef HAVE_DLOPEN
if (!opt_noacl)
udf_free();
@@ -819,19 +848,10 @@ void clean_up(bool print_message)
#ifdef USE_RAID
end_raid();
#endif
-#ifdef HAVE_OPENSSL
- my_free(opt_ssl_key,MYF(MY_ALLOW_ZERO_PTR));
- my_free(opt_ssl_cert,MYF(MY_ALLOW_ZERO_PTR));
- my_free(opt_ssl_ca,MYF(MY_ALLOW_ZERO_PTR));
- my_free(opt_ssl_capath,MYF(MY_ALLOW_ZERO_PTR));
- my_free(opt_ssl_cipher,MYF(MY_ALLOW_ZERO_PTR));
- my_free((gptr) ssl_acceptor_fd, MYF(MY_ALLOW_ZERO_PTR));
- opt_ssl_key=opt_ssl_cert=opt_ssl_ca=opt_ssl_capath=0;
-#endif /* HAVE_OPENSSL */
-
- free_defaults(defaults_argv);
+ if (defaults_argv)
+ free_defaults(defaults_argv);
my_free(charsets_list, MYF(MY_ALLOW_ZERO_PTR));
- my_free(allocated_mysql_tmpdir,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(mysql_tmpdir,MYF(MY_ALLOW_ZERO_PTR));
my_free(slave_load_tmpdir,MYF(MY_ALLOW_ZERO_PTR));
x_free(opt_bin_logname);
x_free(opt_relay_logname);
@@ -1015,8 +1035,6 @@ static void server_init(void)
unireg_abort(1);
}
}
- if (mysqld_chroot)
- set_root(mysqld_chroot);
set_user(mysqld_user); // Works also with mysqld_user==NULL
#ifdef __NT__
@@ -1047,8 +1065,8 @@ static void server_init(void)
PIPE_READMODE_BYTE |
PIPE_WAIT,
PIPE_UNLIMITED_INSTANCES,
- (int) net_buffer_length,
- (int) net_buffer_length,
+ (int) global_system_variables.net_buffer_length,
+ (int) global_system_variables.net_buffer_length,
NMPWAIT_USE_DEFAULT_WAIT,
&saPipeSecurity )) == INVALID_HANDLE_VALUE)
{
@@ -1145,7 +1163,7 @@ sig_handler end_thread_signal(int sig __attribute__((unused)))
{
THD *thd=current_thd;
DBUG_ENTER("end_thread_signal");
- if (thd)
+ if (thd && ! thd->bootstrap)
end_thread(thd,0);
DBUG_VOID_RETURN; /* purecov: deadcode */
}
@@ -1185,9 +1203,8 @@ void end_thread(THD *thd, bool put_in_cache)
DBUG_PRINT("info", ("sending a broadcast"))
/* Tell main we are ready */
- // TODO: explain why we broadcast outside of the lock or
- // fix the bug - Sasha
(void) pthread_mutex_unlock(&LOCK_thread_count);
+ /* It's safe to broadcast outside a lock (COND... is not deleted here) */
(void) pthread_cond_broadcast(&COND_thread_count);
DBUG_PRINT("info", ("unlocked thread_count mutex"))
#ifdef ONE_THREAD
@@ -1226,11 +1243,11 @@ void flush_thread_cache()
}
- /*
- ** Aborts a thread nicely. Commes here on SIGPIPE
- ** TODO: One should have to fix that thr_alarm know about this
- ** thread too
- */
+/*
+ Aborts a thread nicely. Commes here on SIGPIPE
+ TODO: One should have to fix that thr_alarm know about this
+ thread too.
+*/
#ifdef THREAD_SPECIFIC_SIGPIPE
static sig_handler abort_thread(int sig __attribute__((unused)))
@@ -1244,9 +1261,9 @@ static sig_handler abort_thread(int sig __attribute__((unused)))
#endif
/******************************************************************************
-** Setup a signal thread with handles all signals
-** Because linux doesn't support scemas use a mutex to check that
-** the signal thread is ready before continuing
+ Setup a signal thread with handles all signals.
+ Because Linux doesn't support schemas use a mutex to check that
+ the signal thread is ready before continuing
******************************************************************************/
#if defined(__WIN__) || defined(OS2)
@@ -1269,13 +1286,14 @@ static void start_signal_handler(void)
#elif defined(__EMX__)
static void sig_reload(int signo)
{
- reload_acl_and_cache((THD*) 0,REFRESH_LOG, (TABLE_LIST*) 0); // Flush everything
+ // Flush everything
+ reload_acl_and_cache((THD*) 0,REFRESH_LOG, (TABLE_LIST*) 0);
signal(signo, SIG_ACK);
}
static void sig_kill(int signo)
{
- if (!abort_loop)
+ if (!kill_in_progress)
{
abort_loop=1; // mark abort for threads
kill_server((void*) signo);
@@ -1333,15 +1351,16 @@ We will try our best to scrape up some info that will hopefully help diagnose\n\
the problem, but since we have already crashed, something is definitely wrong\n\
and this may fail.\n\n");
fprintf(stderr, "key_buffer_size=%ld\n", keybuff_size);
- fprintf(stderr, "record_buffer=%ld\n", my_default_record_cache_size);
- fprintf(stderr, "sort_buffer=%ld\n", sortbuff_size);
+ fprintf(stderr, "read_buffer_size=%ld\n", global_system_variables.read_buff_size);
+ fprintf(stderr, "sort_buffer_size=%ld\n", thd->variables.sortbuff_size);
fprintf(stderr, "max_used_connections=%ld\n", max_used_connections);
fprintf(stderr, "max_connections=%ld\n", max_connections);
fprintf(stderr, "threads_connected=%d\n", thread_count);
fprintf(stderr, "It is possible that mysqld could use up to \n\
-key_buffer_size + (record_buffer + sort_buffer)*max_connections = %ld K\n\
-bytes of memory\n", (keybuff_size + (my_default_record_cache_size +
- sortbuff_size) * max_connections)/ 1024);
+key_buffer_size + (read_buffer_size + sort_buffer_size)*max_connections = %ld K\n\
+bytes of memory\n", (keybuff_size + (global_system_variables.read_buff_size +
+ thd->variables.sortbuff_size) *
+ max_connections)/ 1024);
fprintf(stderr, "Hope that's ok; if not, decrease some variables in the equation.\n\n");
#if defined(HAVE_LINUXTHREADS)
@@ -1357,7 +1376,7 @@ the thread stack. Please read http://www.mysql.com/doc/L/i/Linux.html\n\n",
#endif /* HAVE_LINUXTHREADS */
#ifdef HAVE_STACKTRACE
- if(!(test_flags & TEST_NO_STACKTRACE))
+ if (!(test_flags & TEST_NO_STACKTRACE))
{
fprintf(stderr,"thd=%p\n",thd);
print_stacktrace(thd ? (gptr) thd->thread_stack : (gptr) 0,
@@ -1421,6 +1440,17 @@ static void init_signals(void)
sigaction(SIGILL, &sa, NULL);
sigaction(SIGFPE, &sa, NULL);
}
+
+#ifdef HAVE_GETRLIMIT
+ if (test_flags & TEST_CORE_ON_SIGNAL)
+ {
+ /* Change limits so that we will get a core file */
+ struct rlimit rl;
+ rl.rlim_cur = rl.rlim_max = RLIM_INFINITY;
+ if (setrlimit(RLIMIT_CORE, &rl))
+ sql_print_error("Warning: setrlimit could not change the size of core files to 'infinity'; We may not be able to generate a core file on signals");
+ }
+#endif
(void) sigemptyset(&set);
#ifdef THREAD_SPECIFIC_SIGPIPE
sigset(SIGPIPE,abort_thread);
@@ -1433,8 +1463,8 @@ static void init_signals(void)
sigaddset(&set,SIGQUIT);
sigaddset(&set,SIGTERM);
sigaddset(&set,SIGHUP);
- signal(SIGTERM,SIG_DFL); // If it's blocked by parent
- signal(SIGHUP,SIG_DFL); // If it's blocked by parent
+ sigset(SIGTERM, print_signal_warning); // If it's blocked by parent
+ sigset(SIGHUP, print_signal_warning); // If it's blocked by parent
#ifdef SIGTSTP
sigaddset(&set,SIGTSTP);
#endif
@@ -1476,9 +1506,7 @@ static void start_signal_handler(void)
}
-/*
-** This threads handles all signals and alarms
-*/
+/* This threads handles all signals and alarms */
/* ARGSUSED */
static void *signal_hand(void *arg __attribute__((unused)))
@@ -1526,17 +1554,24 @@ static void *signal_hand(void *arg __attribute__((unused)))
}
#endif /* HAVE_STACK_TRACE_ON_SEGV */
- // signal to start_signal_handler that we are ready
+ /*
+ signal to start_signal_handler that we are ready
+ This works by waiting for start_signal_handler to free mutex,
+ after which we signal it that we are ready.
+ At this pointer there is no other threads running, so there
+ should not be any other pthread_cond_signal() calls.
+ */
(void) pthread_mutex_lock(&LOCK_thread_count);
- (void) pthread_cond_signal(&COND_thread_count);
(void) pthread_mutex_unlock(&LOCK_thread_count);
+ (void) pthread_cond_broadcast(&COND_thread_count);
+ (void) pthread_sigmask(SIG_BLOCK,&set,NULL);
for (;;)
{
int error; // Used when debugging
if (shutdown_in_progress && !abort_loop)
{
- sig=SIGTERM;
+ sig= SIGTERM;
error=0;
}
else
@@ -1584,7 +1619,7 @@ static void *signal_hand(void *arg __attribute__((unused)))
#endif
default:
#ifdef EXTRA_DEBUG
- sql_print_error("Warning: Got signal: %d, error: %d",sig,error); /* purecov: tested */
+ sql_print_error("Warning: Got signal: %d error: %d",sig,error); /* purecov: tested */
#endif
break; /* purecov: tested */
}
@@ -1596,8 +1631,8 @@ static void *signal_hand(void *arg __attribute__((unused)))
/*
-** All global error messages are sent here where the first one is stored for
-** the client
+ All global error messages are sent here where the first one is stored for
+ the client
*/
@@ -1682,23 +1717,25 @@ pthread_handler_decl(handle_shutdown,arg)
abort_loop = 1;
// unblock select()
- so_cancel( ip_sock);
- so_cancel( unix_sock);
+ so_cancel(ip_sock);
+ so_cancel(unix_sock);
return 0;
}
#endif
+
const char *load_default_groups[]= { "mysqld","server",0 };
#ifdef HAVE_LIBWRAP
char *libwrapName=NULL;
#endif
-void open_log(MYSQL_LOG *log, const char *hostname,
- const char *opt_name, const char *extension,
- enum_log_type type, bool read_append,
- bool no_auto_events)
+bool open_log(MYSQL_LOG *log, const char *hostname,
+ const char *opt_name, const char *extension,
+ const char *index_file_name,
+ enum_log_type type, bool read_append,
+ bool no_auto_events)
{
char tmp[FN_REFLEN];
if (!opt_name || !opt_name[0])
@@ -1722,8 +1759,9 @@ void open_log(MYSQL_LOG *log, const char *hostname,
opt_name=tmp;
}
}
- log->open(opt_name,type,0,(read_append) ? SEQ_READ_APPEND : WRITE_CACHE,
- no_auto_events);
+ return log->open(opt_name, type, 0, index_file_name,
+ (read_append) ? SEQ_READ_APPEND : WRITE_CACHE,
+ no_auto_events);
}
@@ -1739,9 +1777,10 @@ int main(int argc, char **argv)
my_umask=0660; // Default umask for new files
my_umask_dir=0700; // Default umask for new directories
MAIN_THD;
- /* initialize signal_th and shutdown_th to main_th for default value
- as we need to initialize them to something safe. They are used
- when compiled with safemalloc
+ /*
+ Initialize signal_th and shutdown_th to main_th for default value
+ as we need to initialize them to something safe. They are used
+ when compiled with safemalloc.
*/
SIGNAL_THD;
SHUTDOWN_THD;
@@ -1789,17 +1828,19 @@ int main(int argc, char **argv)
exit( 1 );
}
#endif
- load_defaults("my",load_default_groups,&argc,&argv);
+ load_defaults(MYSQL_CONFIG_NAME,load_default_groups,&argc,&argv);
defaults_argv=argv;
- mysql_tmpdir=getenv("TMPDIR"); /* Use this if possible */
+
+ /* Get default temporary directory */
+ opt_mysql_tmpdir=getenv("TMPDIR"); /* Use this if possible */
#if defined( __WIN__) || defined(OS2)
- if (!mysql_tmpdir)
- mysql_tmpdir=getenv("TEMP");
- if (!mysql_tmpdir)
- mysql_tmpdir=getenv("TMP");
+ if (!opt_mysql_tmpdir)
+ opt_mysql_tmpdir=getenv("TEMP");
+ if (!opt_mysql_tmpdir)
+ opt_mysql_tmpdir=getenv("TMP");
#endif
- if (!mysql_tmpdir || !mysql_tmpdir[0])
- mysql_tmpdir=(char*) P_tmpdir; /* purecov: inspected */
+ if (!opt_mysql_tmpdir || !opt_mysql_tmpdir[0])
+ opt_mysql_tmpdir=(char*) P_tmpdir; /* purecov: inspected */
set_options();
get_options(argc,argv);
@@ -1826,10 +1867,10 @@ int main(int argc, char **argv)
(void) pthread_mutex_init(&LOCK_bytes_sent,MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_bytes_received,MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_timezone,MY_MUTEX_INIT_FAST);
- (void) pthread_mutex_init(&LOCK_server_id, MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_user_conn, MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_rpl_status, MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_active_mi, MY_MUTEX_INIT_FAST);
+ (void) pthread_mutex_init(&LOCK_global_system_variables, MY_MUTEX_INIT_FAST);
(void) pthread_cond_init(&COND_thread_count,NULL);
(void) pthread_cond_init(&COND_refresh,NULL);
(void) pthread_cond_init(&COND_thread_cache,NULL);
@@ -1838,20 +1879,23 @@ int main(int argc, char **argv)
(void) pthread_cond_init(&COND_rpl_status, NULL);
init_signals();
- if (set_default_charset_by_name(default_charset, MYF(MY_WME)))
- exit( 1 );
- charsets_list = list_charsets(MYF(MY_CS_COMPILED|MY_CS_CONFIG));
+ if (set_default_charset_by_name(sys_charset.value, MYF(MY_WME)))
+ exit(1);
+ charsets_list= list_charsets(MYF(MY_CS_COMPILED | MY_CS_CONFIG));
#ifdef HAVE_OPENSSL
+ if (opt_ssl_key || opt_ssl_cert || opt_ssl_ca || opt_ssl_capath ||
+ opt_ssl_cipher)
+ opt_use_ssl= 1;
if (opt_use_ssl)
{
- ssl_acceptor_fd = new_VioSSLAcceptorFd(opt_ssl_key, opt_ssl_cert,
- opt_ssl_ca, opt_ssl_capath,
- opt_ssl_cipher);
- DBUG_PRINT("info",("ssl_acceptor_fd: %p",ssl_acceptor_fd));
+ /* having ssl_acceptor_fd != 0 signals the use of SSL */
+ ssl_acceptor_fd= new_VioSSLAcceptorFd(opt_ssl_key, opt_ssl_cert,
+ opt_ssl_ca, opt_ssl_capath,
+ opt_ssl_cipher);
+ DBUG_PRINT("info",("ssl_acceptor_fd: %lx", (long) ssl_acceptor_fd));
if (!ssl_acceptor_fd)
opt_use_ssl = 0;
- /* having ssl_acceptor_fd != 0 signals the use of SSL */
}
if (des_key_file)
load_des_key_file(des_key_file);
@@ -1897,6 +1941,7 @@ int main(int argc, char **argv)
init_errmessage(); /* Read error messages from file */
lex_init();
item_init();
+ set_var_init();
mysys_uses_curses=0;
#ifdef USE_REGEX
regex_init();
@@ -1907,7 +1952,7 @@ int main(int argc, char **argv)
unireg_abort(1);
/*
- ** We have enough space for fiddling with the argv, continue
+ We have enough space for fiddling with the argv, continue
*/
umask(((~my_umask) & 0666));
if (my_setwd(mysql_real_data_home,MYF(MY_WME)))
@@ -1928,17 +1973,18 @@ int main(int argc, char **argv)
/* Setup log files */
if (opt_log)
- open_log(&mysql_log, glob_hostname, opt_logname, ".log", LOG_NORMAL);
+ open_log(&mysql_log, glob_hostname, opt_logname, ".log", NullS,
+ LOG_NORMAL);
if (opt_update_log)
{
open_log(&mysql_update_log, glob_hostname, opt_update_logname, "",
- LOG_NEW);
+ NullS, LOG_NEW);
using_update_log=1;
}
if (opt_slow_log)
open_log(&mysql_slow_log, glob_hostname, opt_slow_logname, "-slow.log",
- LOG_NORMAL);
+ NullS, LOG_NORMAL);
#ifdef __WIN__
#define MYSQL_ERR_FILE "mysql.err"
if (!opt_console)
@@ -1990,6 +2036,7 @@ int main(int argc, char **argv)
start_signal_handler(); // Creates pidfile
if (acl_init(opt_noacl))
{
+ abort_loop=1;
select_thread_in_use=0;
(void) pthread_kill(signal_thread,MYSQL_KILL_SIGNAL);
#ifndef __WIN__
@@ -2040,9 +2087,8 @@ The server will not act as a slave.");
strmov(strcend(tmp,'.'),"-bin");
opt_bin_logname=my_strdup(tmp,MYF(MY_WME));
}
- mysql_bin_log.set_index_file_name(opt_binlog_index_name);
open_log(&mysql_bin_log, glob_hostname, opt_bin_logname, "-bin",
- LOG_BIN);
+ opt_binlog_index_name,LOG_BIN);
using_update_log=1;
}
@@ -2131,9 +2177,7 @@ The server will not act as a slave.");
}
}
while (handler_count > 0)
- {
pthread_cond_wait(&COND_handler_count,&LOCK_thread_count);
- }
}
pthread_mutex_unlock(&LOCK_thread_count);
}
@@ -2155,8 +2199,8 @@ The server will not act as a slave.");
(void) pthread_mutex_lock(&LOCK_thread_count);
DBUG_PRINT("quit", ("Got thread_count mutex"));
select_thread_in_use=0; // For close_connections
- (void) pthread_cond_broadcast(&COND_thread_count);
(void) pthread_mutex_unlock(&LOCK_thread_count);
+ (void) pthread_cond_broadcast(&COND_thread_count);
#ifdef EXTRA_DEBUG2
sql_print_error("After lock_thread_count");
#endif
@@ -2165,9 +2209,7 @@ The server will not act as a slave.");
/* Wait until cleanup is done */
(void) pthread_mutex_lock(&LOCK_thread_count);
while (!ready_to_exit)
- {
pthread_cond_wait(&COND_thread_count,&LOCK_thread_count);
- }
(void) pthread_mutex_unlock(&LOCK_thread_count);
#if defined(__WIN__) && !defined(EMBEDDED_LIBRARY)
@@ -2186,73 +2228,116 @@ The server will not act as a slave.");
}
+/****************************************************************************
+ Main and thread entry function for Win32
+ (all this is needed only to run mysqld as a service on WinNT)
+****************************************************************************/
+
#if defined(__WIN__) && !defined(EMBEDDED_LIBRARY)
-/* ------------------------------------------------------------------------
- main and thread entry function for Win32
- (all this is needed only to run mysqld as a service on WinNT)
- -------------------------------------------------------------------------- */
int mysql_service(void *p)
{
- win_main(Service.my_argc, Service.my_argv);
+ if (use_opt_args)
+ win_main(opt_argc, opt_argv);
+ else
+ win_main(Service.my_argc, Service.my_argv);
return 0;
}
+/*
+ Handle basic handling of services, like installation and removal
+
+ SYNOPSIS
+ default_service_handling()
+ argv Pointer to argument list
+ servicename Internal name of service
+ displayname Display name of service (in taskbar ?)
+ file_path Path to this program
+
+ RETURN VALUES
+ 0 option handled
+ 1 Could not handle option
+ */
+
+bool default_service_handling(char **argv,
+ const char *servicename,
+ const char *displayname,
+ const char *file_path)
+{
+ if (Service.got_service_option(argv, "install"))
+ {
+ Service.Install(1, servicename, displayname, file_path);
+ return 0;
+ }
+ if (Service.got_service_option(argv, "install-manual"))
+ {
+ Service.Install(0, servicename, displayname, file_path);
+ return 0;
+ }
+ if (Service.got_service_option(argv, "remove"))
+ {
+ Service.Remove(servicename);
+ return 0;
+ }
+ return 1;
+}
+
+
int main(int argc, char **argv)
{
if (Service.GetOS()) /* true NT family */
{
char file_path[FN_REFLEN];
- my_path(file_path, argv[0], ""); /* Find name in path */
- fn_format(file_path,argv[0],file_path,"",1+4+16); /* Force use of full path */
+ my_path(file_path, argv[0], ""); /* Find name in path */
+ fn_format(file_path,argv[0],file_path,"",1+4+16); /* Force full path */
if (argc == 2)
{
- if (Service.got_service_option(argv, "install"))
- {
- Service.Install(1, MYSQL_SERVICENAME, MYSQL_SERVICENAME, file_path);
- return 0;
- }
- else if (Service.got_service_option(argv, "install-manual"))
- {
- Service.Install(0, MYSQL_SERVICENAME, MYSQL_SERVICENAME, file_path);
- return 0;
- }
- else if (Service.got_service_option(argv, "remove"))
- {
- Service.Remove(MYSQL_SERVICENAME);
- return 0;
- }
- else if (Service.IsService(argv[1]))
+ if (!default_service_handling(argv,MYSQL_SERVICENAME, MYSQL_SERVICENAME,
+ file_path))
+ return 0;
+ if (Service.IsService(argv[1]))
{
/* start an optional service */
- load_default_groups[0]= argv[1];
- event_name= argv[1];
+ event_name= argv[1];
+ load_default_groups[0]= argv[1];
start_mode= 1;
- Service.Init(event_name, mysql_service );
+ Service.Init(event_name, mysql_service);
return 0;
}
}
else if (argc == 3) /* install or remove any optional service */
{
+ /* Add service name after filename */
uint length=strlen(file_path);
- file_path[sizeof(file_path)-1]=0;
- strxnmov(file_path + length, sizeof(file_path)-2, " ", argv[2], NullS);
- if (Service.got_service_option(argv, "install"))
- {
- Service.Install(1, argv[2], argv[2], file_path);
- return 0;
- }
- else if (Service.got_service_option(argv, "install-manual"))
- {
- Service.Install(0, argv[2], argv[2], file_path);
- return 0;
- }
- else if (Service.got_service_option(argv, "remove"))
+ *strxnmov(file_path + length, sizeof(file_path)-length-2, " ",
+ argv[2], NullS)= '\0';
+
+ if (!default_service_handling(argv, argv[2], argv[2], file_path))
+ return 0;
+ if (Service.IsService(argv[2]))
{
- Service.Remove(argv[2]);
- return 0;
+ /* start an optional service */
+ use_opt_args=1;
+ opt_argc=argc;
+ opt_argv=argv;
+ event_name= argv[2];
+ start_mode= 1;
+ Service.Init(event_name, mysql_service);
+ return 0;
}
}
+ else if (argc == 4)
+ {
+ /*
+ Install an optional service with optional config file
+ mysqld --install-manual mysqldopt --defaults-file=c:\miguel\my.ini
+ */
+ uint length=strlen(file_path);
+ *strxnmov(file_path + length, sizeof(file_path)-length-2, " ",
+ argv[3], " ", argv[2], NullS)= '\0';
+ if (!default_service_handling(argv, argv[2], argv[2], file_path))
+ return 0;
+ }
else if (argc == 1 && Service.IsService(MYSQL_SERVICENAME))
{
/* start the default service */
@@ -2268,18 +2353,24 @@ int main(int argc, char **argv)
mysql_service(NULL);
return 0;
}
-/* ------------------------------------------------------------------------ */
#endif
+/*
+ Execute all commands from a file. Used by the mysql_install_db script to
+ create MySQL privilege tables without having to start a full MySQL server.
+*/
+
static int bootstrap(FILE *file)
{
THD *thd= new THD;
int error;
+ DBUG_ENTER("bootstrap");
+
thd->bootstrap=1;
thd->client_capabilities=0;
my_net_init(&thd->net,(st_vio*) 0);
- thd->max_packet_length=thd->net.max_packet;
+ thd->max_client_packet_length= thd->net.max_packet;
thd->master_access= ~0;
thd->thread_id=thread_id++;
thread_count++;
@@ -2289,7 +2380,7 @@ static int bootstrap(FILE *file)
(void*) thd))
{
sql_print_error("Warning: Can't create thread to handle bootstrap");
- return -1;
+ DBUG_RETURN(-1);
}
/* Wait for thread to die */
(void) pthread_mutex_lock(&LOCK_thread_count);
@@ -2303,7 +2394,7 @@ static int bootstrap(FILE *file)
net_end(&thd->net);
thd->cleanup();
delete thd;
- return error;
+ DBUG_RETURN(error);
}
static bool read_init_file(char *file_name)
@@ -2324,7 +2415,7 @@ static void create_new_thread(THD *thd)
DBUG_ENTER("create_new_thread");
NET *net=&thd->net; // For easy ref
- net->timeout = (uint) connect_timeout; // Timeout for read
+ net->read_timeout = (uint) connect_timeout;
if (protocol_version > 9)
net->return_errno=1;
@@ -2336,20 +2427,22 @@ static void create_new_thread(THD *thd)
delete thd;
DBUG_VOID_RETURN;
}
- if (pthread_mutex_lock(&LOCK_thread_count))
- {
- DBUG_PRINT("error",("Can't lock LOCK_thread_count"));
- close_connection(net,ER_OUT_OF_RESOURCES);
- delete thd;
- DBUG_VOID_RETURN;
- }
+ pthread_mutex_lock(&LOCK_thread_count);
if (thread_count-delayed_insert_threads > max_used_connections)
max_used_connections=thread_count-delayed_insert_threads;
thd->thread_id=thread_id++;
for (uint i=0; i < 8 ; i++) // Generate password teststring
thd->scramble[i]= (char) (rnd(&sql_rand)*94+33);
thd->scramble[8]=0;
- thd->rand=sql_rand;
+ /*
+ We need good random number initialization for new thread
+ Just coping global one will not work
+ */
+ {
+ ulong tmp=(ulong) (rnd(&sql_rand) * 3000000);
+ randominit(&(thd->rand), tmp + (ulong) start_time,
+ tmp + (ulong) thread_id);
+ }
thd->real_id=pthread_self(); // Keep purify happy
/* Start a new thread to handle connection */
@@ -2407,7 +2500,8 @@ static void create_new_thread(THD *thd)
inline void kill_broken_server()
{
/* hack to get around signals ignored in syscalls for problem OS's */
- if (unix_sock == INVALID_SOCKET || (!opt_disable_networking && ip_sock ==INVALID_SOCKET))
+ if (unix_sock == INVALID_SOCKET ||
+ (!opt_disable_networking && ip_sock == INVALID_SOCKET))
{
select_thread_in_use = 0;
kill_server((void*)MYSQL_KILL_SIGNAL); /* never returns */
@@ -2476,10 +2570,8 @@ pthread_handler_decl(handle_connections_sockets,arg __attribute__((unused)))
MAYBE_BROKEN_SYSCALL;
break;
}
- /*
- ** Is this a new connection request
- */
+ /* Is this a new connection request ? */
#ifdef HAVE_SYS_UN_H
if (FD_ISSET(unix_sock,&readFDs))
{
@@ -2656,8 +2748,8 @@ pthread_handler_decl(handle_connections_namedpipes,arg)
PIPE_READMODE_BYTE |
PIPE_WAIT,
PIPE_UNLIMITED_INSTANCES,
- (int) net_buffer_length,
- (int) net_buffer_length,
+ (int) global_system_variables.net_buffer_length,
+ (int) global_systenm_ariables.net_buffer_length,
NMPWAIT_USE_DEFAULT_WAIT,
&saPipeSecurity )) ==
INVALID_HANDLE_VALUE )
@@ -2674,8 +2766,8 @@ pthread_handler_decl(handle_connections_namedpipes,arg)
PIPE_READMODE_BYTE |
PIPE_WAIT,
PIPE_UNLIMITED_INSTANCES,
- (int) net_buffer_length,
- (int) net_buffer_length,
+ (int) global_system_variables.net_buffer_length,
+ (int) global_system_variables.net_buffer_length,
NMPWAIT_USE_DEFAULT_WAIT,
&saPipeSecurity)) ==
INVALID_HANDLE_VALUE)
@@ -2705,8 +2797,8 @@ pthread_handler_decl(handle_connections_namedpipes,arg)
pthread_mutex_lock(&LOCK_thread_count);
handler_count--;
- pthread_cond_signal(&COND_handler_count);
pthread_mutex_unlock(&LOCK_thread_count);
+ pthread_cond_signal(&COND_handler_count);
DBUG_RETURN(0);
}
#endif /* __NT__ */
@@ -2717,115 +2809,115 @@ pthread_handler_decl(handle_connections_namedpipes,arg)
******************************************************************************/
enum options {
- OPT_ISAM_LOG=256, OPT_SKIP_NEW,
- OPT_SKIP_GRANT, OPT_SKIP_LOCK,
- OPT_ENABLE_LOCK, OPT_USE_LOCKING,
- OPT_SOCKET, OPT_UPDATE_LOG,
- OPT_BIN_LOG, OPT_SKIP_RESOLVE,
- OPT_SKIP_NETWORKING, OPT_BIN_LOG_INDEX,
- OPT_BIND_ADDRESS, OPT_PID_FILE,
- OPT_SKIP_PRIOR, OPT_BIG_TABLES,
- OPT_STANDALONE, OPT_ONE_THREAD,
- OPT_CONSOLE, OPT_LOW_PRIORITY_UPDATES,
- OPT_SKIP_HOST_CACHE, OPT_LONG_FORMAT,
- OPT_FLUSH, OPT_SAFE,
- OPT_BOOTSTRAP, OPT_SKIP_SHOW_DB,
- OPT_TABLE_TYPE, OPT_INIT_FILE,
- OPT_DELAY_KEY_WRITE, OPT_SLOW_QUERY_LOG,
- OPT_USE_DELAY_KEY_WRITE, OPT_CHARSETS_DIR,
- OPT_BDB_HOME, OPT_BDB_LOG,
- OPT_BDB_TMP, OPT_BDB_NOSYNC,
- OPT_BDB_LOCK, OPT_BDB_SKIP,
- OPT_BDB_NO_RECOVER, OPT_BDB_SHARED,
- OPT_MASTER_HOST, OPT_MASTER_USER,
- 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_SQL_BIN_UPDATE_SAME, OPT_REPLICATE_DO_DB,
- OPT_REPLICATE_IGNORE_DB, OPT_LOG_SLAVE_UPDATES,
- OPT_BINLOG_DO_DB, OPT_BINLOG_IGNORE_DB,
- OPT_WANT_CORE, OPT_CONCURRENT_INSERT,
- OPT_MEMLOCK, OPT_MYISAM_RECOVER,
- OPT_REPLICATE_REWRITE_DB, OPT_SERVER_ID,
- OPT_SKIP_SLAVE_START, OPT_SKIP_INNOBASE,
- OPT_SAFEMALLOC_MEM_LIMIT, OPT_REPLICATE_DO_TABLE,
- OPT_REPLICATE_IGNORE_TABLE, OPT_REPLICATE_WILD_DO_TABLE,
- OPT_REPLICATE_WILD_IGNORE_TABLE,
- OPT_DISCONNECT_SLAVE_EVENT_COUNT,
- OPT_ABORT_SLAVE_EVENT_COUNT,
- OPT_INNODB_DATA_HOME_DIR,
- OPT_INNODB_DATA_FILE_PATH,
- OPT_INNODB_LOG_GROUP_HOME_DIR,
- OPT_INNODB_LOG_ARCH_DIR,
- OPT_INNODB_LOG_ARCHIVE,
- OPT_INNODB_FLUSH_LOG_AT_TRX_COMMIT,
- OPT_INNODB_FLUSH_METHOD,
- OPT_INNODB_FAST_SHUTDOWN,
- OPT_SAFE_SHOW_DB,
- OPT_INNODB_SKIP, OPT_SKIP_SAFEMALLOC,
- OPT_TEMP_POOL, OPT_TX_ISOLATION,
- OPT_SKIP_STACK_TRACE, OPT_SKIP_SYMLINKS,
- OPT_MAX_BINLOG_DUMP_EVENTS, OPT_SPORADIC_BINLOG_DUMP_FAIL,
- OPT_SAFE_USER_CREATE, OPT_SQL_MODE,
- OPT_HAVE_NAMED_PIPE,
- OPT_DO_PSTACK, OPT_REPORT_HOST,
- OPT_REPORT_USER, OPT_REPORT_PASSWORD, OPT_REPORT_PORT,
- OPT_SHOW_SLAVE_AUTH_INFO, OPT_OLD_RPL_COMPAT,
- OPT_SLAVE_LOAD_TMPDIR, OPT_NO_MIX_TYPE,
- OPT_RPL_RECOVERY_RANK,OPT_INIT_RPL_ROLE,
- OPT_RELAY_LOG, OPT_RELAY_LOG_INDEX, OPT_RELAY_LOG_INFO_FILE,
- OPT_SLAVE_SKIP_ERRORS, OPT_DES_KEY_FILE, OPT_LOCAL_INFILE,
- OPT_RECKLESS_SLAVE,
- OPT_SSL_SSL, OPT_SSL_KEY, OPT_SSL_CERT, OPT_SSL_CA,
- OPT_SSL_CAPATH, OPT_SSL_CIPHER,
- OPT_BACK_LOG, OPT_BINLOG_CACHE_SIZE,
- OPT_CONNECT_TIMEOUT, OPT_DELAYED_INSERT_TIMEOUT,
- OPT_DELAYED_INSERT_LIMIT, OPT_DELAYED_QUEUE_SIZE,
- OPT_FLUSH_TIME, OPT_FT_MIN_WORD_LEN,
- OPT_FT_MAX_WORD_LEN, OPT_FT_MAX_WORD_LEN_FOR_SORT,
- OPT_INTERACTIVE_TIMEOUT, OPT_JOIN_BUFF_SIZE,
- OPT_KEY_BUFFER_SIZE, OPT_LONG_QUERY_TIME,
- OPT_LOWER_CASE_TABLE_NAMES, OPT_MAX_ALLOWED_PACKET,
- OPT_MAX_BINLOG_CACHE_SIZE, OPT_MAX_BINLOG_SIZE,
- OPT_MAX_CONNECTIONS, OPT_MAX_CONNECT_ERRORS,
- OPT_MAX_DELAYED_THREADS, OPT_MAX_HEP_TABLE_SIZE,
- OPT_MAX_JOIN_SIZE, OPT_MAX_SORT_LENGTH,
- OPT_MAX_TMP_TABLES, OPT_MAX_USER_CONNECTIONS,
- OPT_MAX_WRITE_LOCK_COUNT, OPT_MYISAM_BULK_INSERT_TREE_SIZE,
- OPT_MYISAM_BLOCK_SIZE, OPT_MYISAM_MAX_EXTRA_SORT_FILE_SIZE,
- OPT_MYISAM_MAX_SORT_FILE_SIZE, OPT_MYISAM_SORT_BUFFER_SIZE,
- OPT_NET_BUFFER_LENGTH, OPT_NET_RETRY_COUNT,
- OPT_NET_READ_TIMEOUT, OPT_NET_WRITE_TIMEOUT,
- OPT_OPEN_FILES_LIMIT, OPT_QUERY_BUFFER_SIZE,
- OPT_QUERY_CACHE_LIMIT, OPT_QUERY_CACHE_SIZE,
- OPT_QUERY_CACHE_STARTUP_TYPE, OPT_RECORD_BUFFER,
- OPT_RECORD_RND_BUFFER, OPT_RELAY_LOG_SPACE_LIMIT,
- OPT_SLAVE_NET_TIMEOUT, OPT_SLOW_LAUNCH_TIME,
- OPT_SORT_BUFFER, OPT_TABLE_CACHE,
- OPT_THREAD_CONCURRENCY, OPT_THREAD_CACHE_SIZE,
- OPT_TMP_TABLE_SIZE, OPT_THREAD_STACK,
- OPT_WAIT_TIMEOUT,
- OPT_INNODB_MIRRORED_LOG_GROUPS,
- OPT_INNODB_LOG_FILES_IN_GROUP,
- OPT_INNODB_LOG_FILE_SIZE,
- OPT_INNODB_LOG_BUFFER_SIZE,
- OPT_INNODB_BUFFER_POOL_SIZE,
- OPT_INNODB_ADDITIONAL_MEM_POOL_SIZE,
- OPT_INNODB_FILE_IO_THREADS,
- OPT_INNODB_LOCK_WAIT_TIMEOUT,
- OPT_INNODB_THREAD_CONCURRENCY,
- OPT_INNODB_FORCE_RECOVERY,
- OPT_BDB_CACHE_SIZE,
- OPT_BDB_LOG_BUFFER_SIZE,
- OPT_BDB_MAX_LOCK
+ OPT_ISAM_LOG=256, OPT_SKIP_NEW,
+ OPT_SKIP_GRANT, OPT_SKIP_LOCK,
+ OPT_ENABLE_LOCK, OPT_USE_LOCKING,
+ OPT_SOCKET, OPT_UPDATE_LOG,
+ OPT_BIN_LOG, OPT_SKIP_RESOLVE,
+ OPT_SKIP_NETWORKING, OPT_BIN_LOG_INDEX,
+ OPT_BIND_ADDRESS, OPT_PID_FILE,
+ OPT_SKIP_PRIOR, OPT_BIG_TABLES,
+ OPT_STANDALONE, OPT_ONE_THREAD,
+ OPT_CONSOLE, OPT_LOW_PRIORITY_UPDATES,
+ OPT_SKIP_HOST_CACHE, OPT_LONG_FORMAT,
+ OPT_FLUSH, OPT_SAFE,
+ OPT_BOOTSTRAP, OPT_SKIP_SHOW_DB,
+ OPT_TABLE_TYPE, OPT_INIT_FILE,
+ OPT_DELAY_KEY_WRITE_ALL, OPT_SLOW_QUERY_LOG,
+ OPT_DELAY_KEY_WRITE, OPT_CHARSETS_DIR,
+ OPT_BDB_HOME, OPT_BDB_LOG,
+ OPT_BDB_TMP, OPT_BDB_NOSYNC,
+ OPT_BDB_LOCK, OPT_BDB_SKIP,
+ OPT_BDB_NO_RECOVER, OPT_BDB_SHARED,
+ OPT_MASTER_HOST, OPT_MASTER_USER,
+ 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_SQL_BIN_UPDATE_SAME, OPT_REPLICATE_DO_DB,
+ OPT_REPLICATE_IGNORE_DB, OPT_LOG_SLAVE_UPDATES,
+ OPT_BINLOG_DO_DB, OPT_BINLOG_IGNORE_DB,
+ OPT_WANT_CORE, OPT_CONCURRENT_INSERT,
+ OPT_MEMLOCK, OPT_MYISAM_RECOVER,
+ OPT_REPLICATE_REWRITE_DB, OPT_SERVER_ID,
+ OPT_SKIP_SLAVE_START, OPT_SKIP_INNOBASE,
+ OPT_SAFEMALLOC_MEM_LIMIT, OPT_REPLICATE_DO_TABLE,
+ OPT_REPLICATE_IGNORE_TABLE, OPT_REPLICATE_WILD_DO_TABLE,
+ OPT_REPLICATE_WILD_IGNORE_TABLE,
+ OPT_DISCONNECT_SLAVE_EVENT_COUNT,
+ OPT_ABORT_SLAVE_EVENT_COUNT,
+ OPT_INNODB_DATA_HOME_DIR,
+ OPT_INNODB_DATA_FILE_PATH,
+ OPT_INNODB_LOG_GROUP_HOME_DIR,
+ OPT_INNODB_LOG_ARCH_DIR,
+ OPT_INNODB_LOG_ARCHIVE,
+ OPT_INNODB_FLUSH_LOG_AT_TRX_COMMIT,
+ OPT_INNODB_FLUSH_METHOD,
+ OPT_INNODB_FAST_SHUTDOWN,
+ OPT_SAFE_SHOW_DB,
+ OPT_INNODB_SKIP, OPT_SKIP_SAFEMALLOC,
+ OPT_TEMP_POOL, OPT_TX_ISOLATION,
+ OPT_SKIP_STACK_TRACE, OPT_SKIP_SYMLINKS,
+ OPT_MAX_BINLOG_DUMP_EVENTS, OPT_SPORADIC_BINLOG_DUMP_FAIL,
+ OPT_SAFE_USER_CREATE, OPT_SQL_MODE,
+ OPT_HAVE_NAMED_PIPE,
+ OPT_DO_PSTACK, OPT_REPORT_HOST,
+ OPT_REPORT_USER, OPT_REPORT_PASSWORD, OPT_REPORT_PORT,
+ OPT_SHOW_SLAVE_AUTH_INFO, OPT_OLD_RPL_COMPAT,
+ OPT_SLAVE_LOAD_TMPDIR, OPT_NO_MIX_TYPE,
+ OPT_RPL_RECOVERY_RANK,OPT_INIT_RPL_ROLE,
+ OPT_RELAY_LOG, OPT_RELAY_LOG_INDEX, OPT_RELAY_LOG_INFO_FILE,
+ OPT_SLAVE_SKIP_ERRORS, OPT_DES_KEY_FILE, OPT_LOCAL_INFILE,
+ OPT_RECKLESS_SLAVE,
+ OPT_SSL_SSL, OPT_SSL_KEY, OPT_SSL_CERT, OPT_SSL_CA,
+ OPT_SSL_CAPATH, OPT_SSL_CIPHER,
+ OPT_BACK_LOG, OPT_BINLOG_CACHE_SIZE,
+ OPT_CONNECT_TIMEOUT, OPT_DELAYED_INSERT_TIMEOUT,
+ OPT_DELAYED_INSERT_LIMIT, OPT_DELAYED_QUEUE_SIZE,
+ OPT_FLUSH_TIME, OPT_FT_MIN_WORD_LEN,
+ OPT_FT_MAX_WORD_LEN, OPT_FT_MAX_WORD_LEN_FOR_SORT,
+ OPT_INTERACTIVE_TIMEOUT, OPT_JOIN_BUFF_SIZE,
+ OPT_KEY_BUFFER_SIZE, OPT_LONG_QUERY_TIME,
+ OPT_LOWER_CASE_TABLE_NAMES, OPT_MAX_ALLOWED_PACKET,
+ OPT_MAX_BINLOG_CACHE_SIZE, OPT_MAX_BINLOG_SIZE,
+ OPT_MAX_CONNECTIONS, OPT_MAX_CONNECT_ERRORS,
+ OPT_MAX_DELAYED_THREADS, OPT_MAX_HEP_TABLE_SIZE,
+ OPT_MAX_JOIN_SIZE, OPT_MAX_SORT_LENGTH,
+ OPT_MAX_TMP_TABLES, OPT_MAX_USER_CONNECTIONS,
+ OPT_MAX_WRITE_LOCK_COUNT, OPT_BULK_INSERT_BUFFER_SIZE,
+ OPT_MYISAM_BLOCK_SIZE, OPT_MYISAM_MAX_EXTRA_SORT_FILE_SIZE,
+ OPT_MYISAM_MAX_SORT_FILE_SIZE, OPT_MYISAM_SORT_BUFFER_SIZE,
+ OPT_NET_BUFFER_LENGTH, OPT_NET_RETRY_COUNT,
+ OPT_NET_READ_TIMEOUT, OPT_NET_WRITE_TIMEOUT,
+ OPT_OPEN_FILES_LIMIT,
+ OPT_QUERY_CACHE_LIMIT, OPT_QUERY_CACHE_SIZE,
+ OPT_QUERY_CACHE_TYPE, OPT_RECORD_BUFFER,
+ OPT_RECORD_RND_BUFFER, OPT_RELAY_LOG_SPACE_LIMIT,
+ OPT_SLAVE_NET_TIMEOUT, OPT_SLAVE_COMPRESSED_PROTOCOL, OPT_SLOW_LAUNCH_TIME,
+ OPT_SORT_BUFFER, OPT_TABLE_CACHE,
+ OPT_THREAD_CONCURRENCY, OPT_THREAD_CACHE_SIZE,
+ OPT_TMP_TABLE_SIZE, OPT_THREAD_STACK,
+ OPT_WAIT_TIMEOUT,
+ OPT_INNODB_MIRRORED_LOG_GROUPS,
+ OPT_INNODB_LOG_FILES_IN_GROUP,
+ OPT_INNODB_LOG_FILE_SIZE,
+ OPT_INNODB_LOG_BUFFER_SIZE,
+ OPT_INNODB_BUFFER_POOL_SIZE,
+ OPT_INNODB_ADDITIONAL_MEM_POOL_SIZE,
+ OPT_INNODB_FILE_IO_THREADS,
+ OPT_INNODB_LOCK_WAIT_TIMEOUT,
+ OPT_INNODB_THREAD_CONCURRENCY,
+ OPT_INNODB_FORCE_RECOVERY,
+ OPT_BDB_CACHE_SIZE,
+ OPT_BDB_LOG_BUFFER_SIZE,
+ OPT_BDB_MAX_LOCK
};
#define LONG_TIMEOUT ((ulong) 3600L*24L*365L)
-static struct my_option my_long_options[] =
+struct my_option my_long_options[] =
{
{"ansi", 'a', "Use ANSI SQL syntax instead of MySQL syntax", 0, 0, 0,
GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
@@ -2866,7 +2958,7 @@ static struct my_option my_long_options[] =
"Tells the master that updates to the given database should not be logged tothe binary log",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"bind-address", OPT_BIND_ADDRESS, "Ip address to bind to",
- (gptr*) &my_bind_addr, (gptr*) &my_bind_addr, 0, GET_ULONG, REQUIRED_ARG, 0,
+ (gptr*) &my_bind_addr, (gptr*) &my_bind_addr, 0, GET_STR, REQUIRED_ARG, 0,
0, 0, 0, 0, 0},
{"bootstrap", OPT_BOOTSTRAP, "Used by mysql installation scripts", 0, 0, 0,
GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
@@ -2904,17 +2996,20 @@ static struct my_option my_long_options[] =
0, 0, 0, 0, 0, 0},
#endif /* HAVE_OPENSSL */
{"default-character-set", 'C', "Set the default character set",
- (gptr*) &default_charset_ptr, (gptr*) &default_charset_ptr, 0, GET_STR,
- REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ (gptr*) &sys_charset.value, (gptr*) &sys_charset.value, 0, GET_STR,
+ REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
{"default-table-type", OPT_TABLE_TYPE,
- "Set the default table type for tables", (gptr*) &default_table_type_name,
- (gptr*) &default_table_type_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0,
- 0},
- {"delay-key-write-for-all-tables", OPT_DELAY_KEY_WRITE,
- "Don't flush key buffers between writes for any MyISAM table", 0, 0, 0,
- GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"enable-locking", OPT_ENABLE_LOCK, "Enable system locking", 0, 0, 0,
- GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
+ "Set the default table type for tables", 0, 0,
+ 0, GET_NO_ARG, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"delay-key-write", OPT_DELAY_KEY_WRITE, "Type of DELAY_KEY_WRITE",
+ 0,0,0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
+ {"delay-key-write-for-all-tables", OPT_DELAY_KEY_WRITE_ALL,
+ "Don't flush key buffers between writes for any MyISAM table (Depricated option, use --delay-key-write=all instead)",
+ 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"enable-locking", OPT_ENABLE_LOCK,
+ "Depricated option, use --external-locking instead",
+ (gptr*) &opt_external_locking, (gptr*) &opt_external_locking,
+ 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
#ifdef __NT__
{"enable-named-pipe", OPT_HAVE_NAMED_PIPE, "Enable the named pipe (NT)",
(gptr*) &opt_enable_named_pipe, (gptr*) &opt_enable_named_pipe, 0, GET_BOOL,
@@ -2950,8 +3045,10 @@ static struct my_option my_long_options[] =
"Set to 1 if you want to have logs archived", 0, 0, 0, GET_LONG, OPT_ARG,
0, 0, 0, 0, 0, 0},
{"innodb_flush_log_at_trx_commit", OPT_INNODB_FLUSH_LOG_AT_TRX_COMMIT,
- "Set to 0 if you don't want to flush logs", 0, 0, 0, GET_LONG, OPT_ARG,
- 0, 0, 0, 0, 0, 0},
+ "Set to 0 if you don't want to flush logs",
+ (gptr*) &innobase_flush_log_at_trx_commit,
+ (gptr*) &innobase_flush_log_at_trx_commit,
+ 0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0},
{"innodb_flush_method", OPT_INNODB_FLUSH_METHOD,
"With which method to flush data", (gptr*) &innobase_unix_file_flush_method,
(gptr*) &innobase_unix_file_flush_method, 0, GET_STR, REQUIRED_ARG, 0, 0, 0,
@@ -2973,7 +3070,8 @@ static struct my_option my_long_options[] =
0, 0, 0, 0, 0, 0},
{"local-infile", OPT_LOCAL_INFILE,
"Enable/disable LOAD DATA LOCAL INFILE (takes values 1|0)",
- (gptr*) &opt_local_infile, (gptr*) &opt_local_infile, 0, GET_BOOL, OPT_ARG,
+ (gptr*) &opt_local_infile,
+ (gptr*) &opt_local_infile, 0, GET_BOOL, OPT_ARG,
1, 0, 0, 0, 0, 0},
{"log-bin", OPT_BIN_LOG,
"Log queries in new binary format (for replication)",
@@ -2998,12 +3096,14 @@ static struct my_option my_long_options[] =
"Log some extra information to update log", 0, 0, 0, GET_NO_ARG, NO_ARG,
0, 0, 0, 0, 0, 0},
{"log-slave-updates", OPT_LOG_SLAVE_UPDATES,
- "Tells the slave to log the updates from the slave thread to the binary log. Off by default. You will need to turn it on if you plan to daisy-chain the slaves.",
+ "Tells the slave to log the updates from the slave thread to the binary log. You will need to turn it on if you plan to daisy-chain the slaves.",
(gptr*) &opt_log_slave_updates, (gptr*) &opt_log_slave_updates, 0, GET_BOOL,
NO_ARG, 0, 0, 0, 0, 0, 0},
{"low-priority-updates", OPT_LOW_PRIORITY_UPDATES,
- "INSERT/DELETE/UPDATE has lower priority than selects", 0, 0, 0, GET_NO_ARG,
- NO_ARG, 0, 0, 0, 0, 0, 0},
+ "INSERT/DELETE/UPDATE has lower priority than selects",
+ (gptr*) &global_system_variables.low_priority_updates,
+ (gptr*) &max_system_variables.low_priority_updates,
+ 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"master-host", OPT_MASTER_HOST,
"Master hostname or IP address for replication. If not set, the slave thread will not be started. Note that the setting of master-host will be ignored if there exists a valid master.info file.",
(gptr*) &master_host, (gptr*) &master_host, 0, GET_STR, REQUIRED_ARG, 0, 0,
@@ -3026,7 +3126,7 @@ static struct my_option my_long_options[] =
{"master-retry-count", OPT_MASTER_RETRY_COUNT,
"The number of tries the slave will make to connect to the master before giving up.",
(gptr*) &master_retry_count, (gptr*) &master_retry_count, 0, GET_ULONG,
- REQUIRED_ARG, 60, 0, 0, 0, 0, 0},
+ REQUIRED_ARG, 3600*24, 0, 0, 0, 0, 0},
{"master-info-file", OPT_MASTER_INFO_FILE,
"The location of the file that remembers where we left off on the master during the replication process. The default is `master.info' in the data directory. You should not need to change this.",
(gptr*) &master_info_file, (gptr*) &master_info_file, 0, GET_STR,
@@ -3047,25 +3147,23 @@ static struct my_option my_long_options[] =
"Syntax: myisam-recover[=option[,option...]], where option can be DEFAULT, BACKUP or FORCE.",
(gptr*) &myisam_recover_options_str, (gptr*) &myisam_recover_options_str, 0,
GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
- /*
- Option needs to be available for the test case to pass in non-debugging
- mode. is a no-op.
- */
{"memlock", OPT_MEMLOCK, "Lock mysqld in memory", (gptr*) &locked_in_memory,
(gptr*) &locked_in_memory, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"disconnect-slave-event-count", OPT_DISCONNECT_SLAVE_EVENT_COUNT,
- "Undocumented: Meant for debugging and testing of replication",
+ "Option used by mysql-test for debugging and testing of replication",
(gptr*) &disconnect_slave_event_count,
(gptr*) &disconnect_slave_event_count, 0, GET_INT, REQUIRED_ARG, 0, 0, 0,
0, 0, 0},
{"abort-slave-event-count", OPT_ABORT_SLAVE_EVENT_COUNT,
- "Undocumented: Meant for debugging and testing of replication",
+ "Option used by mysql-test for debugging and testing of replication",
(gptr*) &abort_slave_event_count, (gptr*) &abort_slave_event_count,
0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"max-binlog-dump-events", OPT_MAX_BINLOG_DUMP_EVENTS, "Undocumented",
+ {"max-binlog-dump-events", OPT_MAX_BINLOG_DUMP_EVENTS,
+ "Option used by mysql-test for debugging and testing of replication",
(gptr*) &max_binlog_dump_events, (gptr*) &max_binlog_dump_events, 0,
GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"sporadic-binlog-dump-fail", OPT_SPORADIC_BINLOG_DUMP_FAIL, "Undocumented",
+ {"sporadic-binlog-dump-fail", OPT_SPORADIC_BINLOG_DUMP_FAIL,
+ "Option used by mysql-test for debugging and testing of replication",
(gptr*) &opt_sporadic_binlog_dump_fail,
(gptr*) &opt_sporadic_binlog_dump_fail, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0,
0},
@@ -3075,14 +3173,15 @@ static struct my_option my_long_options[] =
{"new", 'n', "Use very new possible 'unsafe' functions", 0, 0, 0, GET_NO_ARG,
NO_ARG, 0, 0, 0, 0, 0, 0},
#ifdef NOT_YET
- {"no-mix-table-types", OPT_NO_MIX_TYPE, "Undocumented",
+ {"no-mix-table-types", OPT_NO_MIX_TYPE, "Don't allow commands with uses two different table types",
(gptr*) &opt_no_mix_types, (gptr*) &opt_no_mix_types, 0, GET_BOOL, NO_ARG,
0, 0, 0, 0, 0, 0},
#endif
- {"old-protocol", 'o', "Use the old (3.20) protocol",
+ {"old-protocol", 'o', "Use the old (3.20) protocol client/server protocol",
(gptr*) &protocol_version, (gptr*) &protocol_version, 0, GET_UINT, NO_ARG,
PROTOCOL_VERSION, 0, 0, 0, 0, 0},
- {"old-rpl-compat", OPT_OLD_RPL_COMPAT, "Undocumented",
+ {"old-rpl-compat", OPT_OLD_RPL_COMPAT,
+ "Use old LOAD DATA format in the binary log (don't save data in file)",
(gptr*) &opt_old_rpl_compat, (gptr*) &opt_old_rpl_compat, 0, GET_BOOL,
NO_ARG, 0, 0, 0, 0, 0, 0},
#ifdef ONE_THREAD
@@ -3095,7 +3194,7 @@ static struct my_option my_long_options[] =
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"port", 'P', "Port number to use for connection.", (gptr*) &mysql_port,
(gptr*) &mysql_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"reckless-slave", OPT_RECKLESS_SLAVE, "Undocumented", 0, 0, 0, GET_NO_ARG,
+ {"reckless-slave", OPT_RECKLESS_SLAVE, "For debugging", 0, 0, 0, GET_NO_ARG,
NO_ARG, 0, 0, 0, 0, 0, 0},
{"replicate-do-db", OPT_REPLICATE_DO_DB,
"Tells the slave thread to restrict replication to the specified database. To specify more than one database, use the directive multiple times, once for each database. Note that this will only work if you do not use cross-database queries such as UPDATE some_db.some_table SET foo='bar' while having selected a different or no database. If you need cross database updates to work, make sure you have 3.23.28 or later, and use replicate-wild-do-table=db_name.%.",
@@ -3143,32 +3242,31 @@ static struct my_option my_long_options[] =
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"safe-mode", OPT_SAFE, "Skip some optimize stages (for testing).",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
+#ifndef TO_BE_DELETED
{"safe-show-database", OPT_SAFE_SHOW_DB,
- "Don't show databases for which the user has no privileges",
+ "Depricated 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},
+#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",
(gptr*) &opt_safe_user_create, (gptr*) &opt_safe_user_create, 0, GET_BOOL,
NO_ARG, 0, 0, 0, 0, 0, 0},
{"server-id", OPT_SERVER_ID,
"Uniquely identifies the server instance in the community of replication partners",
- (gptr*) &server_id, (gptr*) &server_id, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0,
+ (gptr*) &server_id, (gptr*) &server_id, 0, GET_ULONG, REQUIRED_ARG, 0, 0, 0,
0, 0, 0},
{"set-variable", 'O',
"Change the value of a variable. Please note that this option is deprecated;you can set variables directly with --variable-name=value.",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"show-slave-auth-info", OPT_SHOW_SLAVE_AUTH_INFO, "Undocumented",
+ {"show-slave-auth-info", OPT_SHOW_SLAVE_AUTH_INFO,
+ "Show user and password in SHOW SLAVE STATUS",
(gptr*) &opt_show_slave_auth_info, (gptr*) &opt_show_slave_auth_info, 0,
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"concurrent-insert", OPT_CONCURRENT_INSERT,
"Use concurrent insert with MyISAM. Disable with prefix --skip-",
(gptr*) &myisam_concurrent_insert, (gptr*) &myisam_concurrent_insert,
- 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"delay-key-write", OPT_USE_DELAY_KEY_WRITE,
- "Use delay_key_write option for all tables. Disable with prefix --skip-",
- (gptr*) &myisam_delay_key_write, (gptr*) &myisam_delay_key_write, 0,
- GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+ 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
{"skip-grant-tables", OPT_SKIP_GRANT,
"Start without grant tables. This gives all users FULL ACCESS to all tables!",
(gptr*) &opt_noacl, (gptr*) &opt_noacl, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0,
@@ -3176,7 +3274,7 @@ static struct my_option my_long_options[] =
{"skip-innodb", OPT_INNODB_SKIP, "Don't use Innodb (will save memory)",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"skip-locking", OPT_SKIP_LOCK,
- "Don't use system locking. To use isamchk one has to shut down the server.",
+ "Depricated option, use --skip-external-locking instead",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"skip-host-cache", OPT_SKIP_HOST_CACHE, "Don't cache host names", 0, 0, 0,
GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
@@ -3227,20 +3325,21 @@ static struct my_option my_long_options[] =
#endif
{"temp-pool", OPT_TEMP_POOL,
"Using this option will cause most temporary files created to use a small set of names, rather than a unique name for each new file.",
- (gptr*) &use_temp_pool, (gptr*) &use_temp_pool, 0, GET_BOOL, NO_ARG, 0, 0,
- 0, 0, 0, 0},
- {"tmpdir", 't', "Path for temporary files", (gptr*) &mysql_tmpdir,
- (gptr*) &mysql_tmpdir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ (gptr*) &use_temp_pool, (gptr*) &use_temp_pool, 0, GET_BOOL, NO_ARG, 1,
+ 0, 0, 0, 0, 0},
+ {"tmpdir", 't', "Path for temporary files", (gptr*) &opt_mysql_tmpdir,
+ (gptr*) &opt_mysql_tmpdir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"transaction-isolation", OPT_TX_ISOLATION,
- "Default transaction isolation level", (gptr*) &default_tx_isolation_name,
- (gptr*) &default_tx_isolation_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0,
+ "Default transaction isolation level", 0, 0, 0, GET_NO_ARG, REQUIRED_ARG, 0,
+ 0, 0, 0,
0, 0},
- {"use-locking", OPT_USE_LOCKING, "Use system (external) locking",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"external-locking", OPT_USE_LOCKING, "Use system (external) locking. With this option enabled you can run myisamchk to test (not repair) tables while the MySQL server is running",
+ (gptr*) &opt_external_locking, (gptr*) &opt_external_locking,
+ 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
#ifdef USE_SYMDIR
{"use-symbolic-links", 's', "Enable symbolic link support",
- (gptr*) &my_use_symdir, (gptr*) &my_use_symdir, 0, GET_BOOL, NO_ARG, 0, 0,
- 0, 0, 0, 0},
+ (gptr*) &my_use_symdir, (gptr*) &my_use_symdir, 0, GET_BOOL, NO_ARG,
+ USE_PURIFY(0,1), 0, 0, 0, 0, 0},
#endif
{"user", 'u', "Run mysqld daemon as user", (gptr*) &mysqld_user,
(gptr*) &mysqld_user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
@@ -3248,8 +3347,13 @@ static struct my_option my_long_options[] =
NO_ARG, 0, 0, 0, 0, 0, 0},
{"version", 'v', "Synonym for option -v", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0,
0, 0, 0, 0},
- {"warnings", 'W', "Log some not critical warnings to the log file",
- (gptr*) &opt_warnings, (gptr*) &opt_warnings, 0, GET_BOOL, NO_ARG, 0, 0, 0,
+ {"log-warnings", 'W', "Log some not critical warnings to the log file",
+ (gptr*) &global_system_variables.log_warnings,
+ (gptr*) &max_system_variables.log_warnings, 0, GET_BOOL, NO_ARG, 0, 0, 0,
+ 0, 0, 0},
+ {"warnings", 'W', "Deprecated ; Use --log-warnings instead",
+ (gptr*) &global_system_variables.log_warnings,
+ (gptr*) &max_system_variables.log_warnings, 0, GET_BOOL, NO_ARG, 0, 0, 0,
0, 0, 0},
{ "back_log", OPT_BACK_LOG,
"The number of outstanding connection requests MySQL can have. This comes into play when the main MySQL thread gets very many connection requests in a very short time.", (gptr*) &back_log, (gptr*) &back_log, 0, GET_ULONG,
@@ -3278,10 +3382,10 @@ static struct my_option my_long_options[] =
REQUIRED_ARG, 32*1024L, IO_SIZE, ~0L, 0, IO_SIZE, 0},
{"connect_timeout", OPT_CONNECT_TIMEOUT,
"The number of seconds the mysqld server is waiting for a connect packet before responding with Bad handshake",
- (gptr*) &connect_timeout, (gptr*) &connect_timeout, 0, GET_ULONG,
- REQUIRED_ARG, CONNECT_TIMEOUT, 2, LONG_TIMEOUT, 0, 1, 0 },
+ (gptr*) &connect_timeout, (gptr*) &connect_timeout,
+ 0, GET_ULONG, REQUIRED_ARG, CONNECT_TIMEOUT, 2, LONG_TIMEOUT, 0, 1, 0 },
{"delayed_insert_timeout", OPT_DELAYED_INSERT_TIMEOUT,
- "How long a INSERT DELAYED thread should wait for INSERT statements before terminating.",
+ "Ho wlong a INSERT DELAYED thread should wait for INSERT statements before terminating.",
(gptr*) &delayed_insert_timeout, (gptr*) &delayed_insert_timeout, 0,
GET_ULONG, REQUIRED_ARG, DELAYED_WAIT_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0},
{"delayed_insert_limit", OPT_DELAYED_INSERT_LIMIT,
@@ -3299,7 +3403,7 @@ static struct my_option my_long_options[] =
{ "ft_min_word_len", OPT_FT_MIN_WORD_LEN,
"The minimum length of the word to be included in a FULLTEXT index. Note: FULLTEXT indexes must be rebuilt after changing this variable.",
(gptr*) &ft_min_word_len, (gptr*) &ft_min_word_len, 0, GET_ULONG,
- REQUIRED_ARG, 4, 1, HA_FT_MAXLEN, 0, 1, 0},
+ REQUIRED_ARG, 4, 2, HA_FT_MAXLEN, 0, 1, 0},
{ "ft_max_word_len", OPT_FT_MAX_WORD_LEN,
"The maximum length of the word to be included in a FULLTEXT index. Note: FULLTEXT indexes must be rebuilt after changing this variable.",
(gptr*) &ft_max_word_len, (gptr*) &ft_max_word_len, 0, GET_ULONG,
@@ -3354,11 +3458,13 @@ static struct my_option my_long_options[] =
#endif /* HAVE_INNOBASE_DB */
{"interactive_timeout", OPT_INTERACTIVE_TIMEOUT,
"The number of seconds the server waits for activity on an interactive connection before closing it.",
- (gptr*) &net_interactive_timeout, (gptr*) &net_interactive_timeout, 0,
+ (gptr*) &global_system_variables.net_interactive_timeout,
+ (gptr*) &max_system_variables.net_interactive_timeout, 0,
GET_ULONG, REQUIRED_ARG, NET_WAIT_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0},
{"join_buffer_size", OPT_JOIN_BUFF_SIZE,
"The size of the buffer that is used for full joins.",
- (gptr*) &join_buff_size, (gptr*) &join_buff_size, 0, GET_ULONG,
+ (gptr*) &global_system_variables.join_buff_size,
+ (gptr*) &max_system_variables.join_buff_size, 0, GET_ULONG,
REQUIRED_ARG, 128*1024L, IO_SIZE*2+MALLOC_OVERHEAD, ~0L, MALLOC_OVERHEAD,
IO_SIZE, 0},
{"key_buffer_size", OPT_KEY_BUFFER_SIZE,
@@ -3367,15 +3473,18 @@ static struct my_option my_long_options[] =
KEY_CACHE_SIZE, MALLOC_OVERHEAD, (long) ~0, MALLOC_OVERHEAD, IO_SIZE, 0},
{"long_query_time", OPT_LONG_QUERY_TIME,
"Log all queries that have taken more than long_query_time seconds to execute to file.",
- (gptr*) &long_query_time, (gptr*) &long_query_time, 0, GET_ULONG,
+ (gptr*) &global_system_variables.long_query_time,
+ (gptr*) &max_system_variables.long_query_time, 0, GET_ULONG,
REQUIRED_ARG, 10, 1, LONG_TIMEOUT, 0, 1, 0},
{"lower_case_table_names", OPT_LOWER_CASE_TABLE_NAMES,
"If set to 1 table names are stored in lowercase on disk and table names will be case-insensitive.",
- (gptr*) &lower_case_table_names, (gptr*) &lower_case_table_names, 0,
- GET_ULONG, REQUIRED_ARG, IF_WIN(1,0), 0, 1, 0, 1, 0},
+ (gptr*) &lower_case_table_names,
+ (gptr*) &lower_case_table_names, 0,
+ GET_BOOL, NO_ARG, IF_WIN(1,0), 0, 1, 0, 1, 0},
{"max_allowed_packet", OPT_MAX_ALLOWED_PACKET,
"Max packetlength to send/receive from to server.",
- (gptr*) &max_allowed_packet, (gptr*) &max_allowed_packet, 0, GET_ULONG,
+ (gptr*) &global_system_variables.max_allowed_packet,
+ (gptr*) &max_system_variables.max_allowed_packet, 0, GET_ULONG,
REQUIRED_ARG, 1024*1024L, 80, 64*1024*1024L, MALLOC_OVERHEAD, 1024, 0},
{"max_binlog_cache_size", OPT_MAX_BINLOG_CACHE_SIZE,
"Can be used to restrict the total size used to cache a multi-transaction query.",
@@ -3399,19 +3508,23 @@ static struct my_option my_long_options[] =
0, GET_ULONG, REQUIRED_ARG, 20, 1, 16384, 0, 1, 0},
{"max_heap_table_size", OPT_MAX_HEP_TABLE_SIZE,
"Don't allow creation of heap tables bigger than this.",
- (gptr*) &max_heap_table_size, (gptr*) &max_heap_table_size, 0, GET_ULONG,
+ (gptr*) &global_system_variables.max_heap_table_size,
+ (gptr*) &max_system_variables.max_heap_table_size, 0, GET_ULONG,
REQUIRED_ARG, 16*1024*1024L, 16384, ~0L, MALLOC_OVERHEAD, 1024, 0},
{"max_join_size", OPT_MAX_JOIN_SIZE,
"Joins that are probably going to read more than max_join_size records return an error.",
- (gptr*) &max_join_size, (gptr*) &max_join_size, 0, GET_ULONG, REQUIRED_ARG,
+ (gptr*) &global_system_variables.max_join_size,
+ (gptr*) &max_system_variables.max_join_size, 0, GET_ULONG, REQUIRED_ARG,
~0L, 1, ~0L, 0, 1, 0},
{"max_sort_length", OPT_MAX_SORT_LENGTH,
"The number of bytes to use when sorting BLOB or TEXT values (only the first max_sort_length bytes of each value are used; the rest are ignored).",
- (gptr*) &max_item_sort_length, (gptr*) &max_item_sort_length, 0, GET_ULONG,
+ (gptr*) &global_system_variables.max_sort_length,
+ (gptr*) &max_system_variables.max_sort_length, 0, GET_ULONG,
REQUIRED_ARG, 1024, 4, 8192*1024L, 0, 1, 0},
{"max_tmp_tables", OPT_MAX_TMP_TABLES,
"Maximum number of temporary tables a client can keep open at a time.",
- (gptr*) &max_tmp_tables, (gptr*) &max_tmp_tables, 0, GET_ULONG,
+ (gptr*) &global_system_variables.max_tmp_tables,
+ (gptr*) &max_system_variables.max_tmp_tables, 0, GET_ULONG,
REQUIRED_ARG, 32, 1, ~0L, 0, 1, 0},
{"max_user_connections", OPT_MAX_USER_CONNECTIONS,
"The maximum number of active connections for a single user (0 = no limit).",
@@ -3421,83 +3534,100 @@ static struct my_option my_long_options[] =
"After this many write locks, allow some read locks to run in between.",
(gptr*) &max_write_lock_count, (gptr*) &max_write_lock_count, 0, GET_ULONG,
REQUIRED_ARG, ~0L, 1, ~0L, 0, 1, 0},
- {"myisam_bulk_insert_tree_size", OPT_MYISAM_BULK_INSERT_TREE_SIZE,
+ {"bulk_insert_buffer_size", OPT_BULK_INSERT_BUFFER_SIZE,
"Size of tree cache used in bulk insert optimisation. Note that this is a limit per thread!",
- (gptr*) &myisam_bulk_insert_tree_size,
- (gptr*) &myisam_bulk_insert_tree_size, 0, GET_ULONG, REQUIRED_ARG,
- 8192*1024, 0, ~0L, 0, 1, 0},
+ (gptr*) &global_system_variables.bulk_insert_buff_size,
+ (gptr*) &max_system_variables.bulk_insert_buff_size,
+ 0, GET_ULONG, REQUIRED_ARG, 8192*1024, 0, ~0L, 0, 1, 0},
{"myisam_block_size", OPT_MYISAM_BLOCK_SIZE,
- "Undocumented", (gptr*) &opt_myisam_block_size,
+ "Block size to be used for MyISAM index pages",
+ (gptr*) &opt_myisam_block_size,
(gptr*) &opt_myisam_block_size, 0, GET_ULONG, REQUIRED_ARG,
MI_KEY_BLOCK_LENGTH, MI_MIN_KEY_BLOCK_LENGTH, MI_MAX_KEY_BLOCK_LENGTH,
0, MI_MIN_KEY_BLOCK_LENGTH, 0},
{"myisam_max_extra_sort_file_size", OPT_MYISAM_MAX_EXTRA_SORT_FILE_SIZE,
- "Used to help MySQL to decide when to use the slow but safe key cache index create method. Note that this parameter is given in megabytes!",
- (gptr*) &myisam_max_extra_sort_file_size,
- (gptr*) &myisam_max_extra_sort_file_size, 0, GET_ULONG, REQUIRED_ARG,
- (long) (MI_MAX_TEMP_LENGTH/(1024L*1024L)), 0, ~0L, 0, 1, 0},
+ "Used to help MySQL to decide when to use the slow but safe key cache index create method",
+ (gptr*) &global_system_variables.myisam_max_extra_sort_file_size,
+ (gptr*) &max_system_variables.myisam_max_extra_sort_file_size,
+ 0, GET_ULL, REQUIRED_ARG, (ulonglong) MI_MAX_TEMP_LENGTH,
+ 0, ~0L, 0, 1, 0},
{"myisam_max_sort_file_size", OPT_MYISAM_MAX_SORT_FILE_SIZE,
- "Don't use the fast sort index method to created index if the temporary file would get bigger than this. Note that this paramter is given in megabytes!",
- (gptr*) &myisam_max_sort_file_size, (gptr*) &myisam_max_sort_file_size, 0,
- GET_ULONG, REQUIRED_ARG, (long) (LONG_MAX/(1024L*1024L)), 0, ~0L, 0, 1, 0},
+ "Don't use the fast sort index method to created index if the temporary file would get bigger than this!",
+ (gptr*) &global_system_variables.myisam_max_sort_file_size,
+ (gptr*) &max_system_variables.myisam_max_sort_file_size, 0,
+ GET_ULL, REQUIRED_ARG, (longlong) LONG_MAX, 0, ~0L, 0, 1024*1024, 0},
{"myisam_sort_buffer_size", OPT_MYISAM_SORT_BUFFER_SIZE,
"The buffer that is allocated when sorting the index when doing a REPAIR or when creating indexes with CREATE INDEX or ALTER TABLE.",
- (gptr*) &myisam_sort_buffer_size, (gptr*) &myisam_sort_buffer_size, 0,
+ (gptr*) &global_system_variables.myisam_sort_buff_size,
+ (gptr*) &max_system_variables.myisam_sort_buff_size, 0,
GET_ULONG, REQUIRED_ARG, 8192*1024, 4, ~0L, 0, 1, 0},
{"net_buffer_length", OPT_NET_BUFFER_LENGTH,
- "Buffer for TCP/IP and socket communication.", (gptr*) &net_buffer_length,
- (gptr*) &net_buffer_length, 0, GET_ULONG, REQUIRED_ARG, 16384, 1024,
- 1024*1024L, MALLOC_OVERHEAD, 1024, 0},
+ "Buffer length for TCP/IP and socket communication.",
+ (gptr*) &global_system_variables.net_buffer_length,
+ (gptr*) &max_system_variables.net_buffer_length, 0, GET_ULONG,
+ REQUIRED_ARG, 16384, 1024, 1024*1024L, 0, 1024, 0},
{"net_retry_count", OPT_NET_RETRY_COUNT,
"If a read on a communication port is interrupted, retry this many times before giving up.",
- (gptr*) &mysqld_net_retry_count, (gptr*) &mysqld_net_retry_count, 0,
+ (gptr*) &global_system_variables.net_retry_count,
+ (gptr*) &max_system_variables.net_retry_count,0,
GET_ULONG, REQUIRED_ARG, MYSQLD_NET_RETRY_COUNT, 1, ~0L, 0, 1, 0},
{"net_read_timeout", OPT_NET_READ_TIMEOUT,
"Number of seconds to wait for more data from a connection before aborting the read.",
- (gptr*) &net_read_timeout, (gptr*) &net_read_timeout, 0, GET_ULONG,
+ (gptr*) &global_system_variables.net_read_timeout,
+ (gptr*) &max_system_variables.net_read_timeout, 0, GET_ULONG,
REQUIRED_ARG, NET_READ_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0},
{"net_write_timeout", OPT_NET_WRITE_TIMEOUT,
"Number of seconds to wait for a block to be written to a connection before aborting the write.",
- (gptr*) &net_write_timeout, (gptr*) &net_write_timeout, 0, GET_ULONG,
+ (gptr*) &global_system_variables.net_write_timeout,
+ (gptr*) &max_system_variables.net_write_timeout, 0, GET_ULONG,
REQUIRED_ARG, NET_WRITE_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0},
{"open_files_limit", OPT_OPEN_FILES_LIMIT,
"If this is not 0, then mysqld will use this value to reserve file descriptors to use with setrlimit(). If this value is 0 then mysqld will reserve max_connections*5 or max_connections + table_cache*2 (whichever is larger) number of files.",
(gptr*) &open_files_limit, (gptr*) &open_files_limit, 0, GET_ULONG,
REQUIRED_ARG, 0, 0, 65535, 0, 1, 0},
- {"query_buffer_size", OPT_QUERY_BUFFER_SIZE,
- "The initial allocation of the query buffer.", (gptr*) &query_buff_size,
- (gptr*) &query_buff_size, 0, GET_ULONG, REQUIRED_ARG, 0, MALLOC_OVERHEAD,
- (long) ~0, MALLOC_OVERHEAD, IO_SIZE, 0},
#ifdef HAVE_QUERY_CACHE
{"query_cache_limit", OPT_QUERY_CACHE_LIMIT,
"Don't cache results that are bigger than this.",
(gptr*) &query_cache_limit, (gptr*) &query_cache_limit, 0, GET_ULONG,
- REQUIRED_ARG, 1024*1024L, 0, ULONG_MAX, 0, 1, 0},
+ REQUIRED_ARG, 1024*1024L, 0, (longlong) ULONG_MAX, 0, 1, 0},
#endif /*HAVE_QUERY_CACHE*/
{"query_cache_size", OPT_QUERY_CACHE_SIZE,
"The memory allocated to store results from old queries.",
(gptr*) &query_cache_size, (gptr*) &query_cache_size, 0, GET_ULONG,
- REQUIRED_ARG, 0, 0, ULONG_MAX, 0, 1, 0},
+ REQUIRED_ARG, 0, 0, (longlong) ULONG_MAX, 0, 1024, 0},
#ifdef HAVE_QUERY_CACHE
- {"query_cache_startup_type", OPT_QUERY_CACHE_STARTUP_TYPE,
+ {"query_cache_type", OPT_QUERY_CACHE_TYPE,
"0 = OFF = Don't cache or retrieve results. 1 = ON = Cache all results except SELECT SQL_NO_CACHE ... queries. 2 = DEMAND = Cache only SELECT SQL_CACHE ... queries.",
- (gptr*) &query_cache_startup_type, (gptr*) &query_cache_startup_type, 0,
- GET_ULONG, REQUIRED_ARG, 1, 0, 2, 0, 1, 0},
+ (gptr*) &global_system_variables.query_cache_type,
+ (gptr*) &max_system_variables.query_cache_type,
+ 0, GET_ULONG, REQUIRED_ARG, 1, 0, 2, 0, 1, 0},
#endif /*HAVE_QUERY_CACHE*/
- {"record_buffer", OPT_RECORD_BUFFER,
+ {"read_buffer_size", OPT_RECORD_BUFFER,
"Each thread that does a sequential scan allocates a buffer of this size for each table it scans. If you do many sequential scans, you may want to increase this value.",
- (gptr*) &my_default_record_cache_size,
- (gptr*) &my_default_record_cache_size, 0, GET_ULONG, REQUIRED_ARG,
+ (gptr*) &global_system_variables.read_buff_size,
+ (gptr*) &max_system_variables.read_buff_size,0, GET_ULONG, REQUIRED_ARG,
128*1024L, IO_SIZE*2+MALLOC_OVERHEAD, ~0L, MALLOC_OVERHEAD, IO_SIZE, 0},
- {"record_rnd_buffer", OPT_RECORD_RND_BUFFER,
+ {"read_rnd_buffer_size", OPT_RECORD_RND_BUFFER,
"When reading rows in sorted order after a sort, the rows are read through this buffer to avoid a disk seeks. If not set, then it's set to the value of record_buffer.",
- (gptr*) &record_rnd_cache_size, (gptr*) &record_rnd_cache_size, 0,
- GET_ULONG, REQUIRED_ARG, 0, IO_SIZE*2+MALLOC_OVERHEAD,
+ (gptr*) &global_system_variables.read_rnd_buff_size,
+ (gptr*) &max_system_variables.read_rnd_buff_size, 0,
+ GET_ULONG, REQUIRED_ARG, 256*1024L, IO_SIZE*2+MALLOC_OVERHEAD,
~0L, MALLOC_OVERHEAD, IO_SIZE, 0},
+ {"record_buffer", OPT_RECORD_BUFFER,
+ "Alias for read_buffer_size",
+ (gptr*) &global_system_variables.read_buff_size,
+ (gptr*) &max_system_variables.read_buff_size,0, GET_ULONG, REQUIRED_ARG,
+ 128*1024L, IO_SIZE*2+MALLOC_OVERHEAD, ~0L, MALLOC_OVERHEAD, IO_SIZE, 0},
{"relay_log_space_limit", OPT_RELAY_LOG_SPACE_LIMIT,
- "Undocumented", (gptr*) &relay_log_space_limit,
- (gptr*) &relay_log_space_limit, 0, GET_ULONG, REQUIRED_ARG, 0L, 0L,
- ULONG_MAX, 0, 1, 0},
+ "Max space to use for all relay logs",
+ (gptr*) &relay_log_space_limit,
+ (gptr*) &relay_log_space_limit, 0, GET_ULL, REQUIRED_ARG, 0L, 0L,
+ (longlong) ULONG_MAX, 0, 1, 0},
+ {"slave_compressed_protocol", OPT_SLAVE_COMPRESSED_PROTOCOL,
+ "Use compression on master/slave protocol",
+ (gptr*) &opt_slave_compressed_protocol,
+ (gptr*) &opt_slave_compressed_protocol,
+ 0, GET_BOOL, REQUIRED_ARG, 0, 0, 1, 0, 1, 0},
{"slave_net_timeout", OPT_SLAVE_NET_TIMEOUT,
"Number of seconds to wait for more data from a master/slave connection before aborting the read.",
(gptr*) &slave_net_timeout, (gptr*) &slave_net_timeout, 0,
@@ -3506,9 +3636,10 @@ static struct my_option my_long_options[] =
"If creating the thread takes longer than this value (in seconds), the Slow_launch_threads counter will be incremented.",
(gptr*) &slow_launch_time, (gptr*) &slow_launch_time, 0, GET_ULONG,
REQUIRED_ARG, 2L, 0L, LONG_TIMEOUT, 0, 1, 0},
- {"sort_buffer", OPT_SORT_BUFFER,
+ {"sort_buffer_size", OPT_SORT_BUFFER,
"Each thread that needs to do a sort allocates a buffer of this size.",
- (gptr*) &sortbuff_size, (gptr*) &sortbuff_size, 0, GET_ULONG, REQUIRED_ARG,
+ (gptr*) &global_system_variables.sortbuff_size,
+ (gptr*) &max_system_variables.sortbuff_size, 0, GET_ULONG, REQUIRED_ARG,
MAX_SORT_MEMORY, MIN_SORT_MEMORY+MALLOC_OVERHEAD*2, ~0L, MALLOC_OVERHEAD,
1, 0},
{"table_cache", OPT_TABLE_CACHE,
@@ -3525,7 +3656,8 @@ static struct my_option my_long_options[] =
REQUIRED_ARG, 0, 0, 16384, 0, 1, 0},
{"tmp_table_size", OPT_TMP_TABLE_SIZE,
"If an in-memory temporary table exceeds this size, MySQL will automatically convert it to an on-disk MyISAM table.",
- (gptr*) &tmp_table_size, (gptr*) &tmp_table_size, 0, GET_ULONG,
+ (gptr*) &global_system_variables.tmp_table_size,
+ (gptr*) &max_system_variables.tmp_table_size, 0, GET_ULONG,
REQUIRED_ARG, 32*1024*1024L, 1024, ~0L, 0, 1, 0},
{"thread_stack", OPT_THREAD_STACK,
"The stack size for each thread.", (gptr*) &thread_stack,
@@ -3533,149 +3665,12 @@ static struct my_option my_long_options[] =
1024*32, ~0L, 0, 1024, 0},
{"wait_timeout", OPT_WAIT_TIMEOUT,
"The number of seconds the server waits for activity on a connection before closing it",
- (gptr*) &net_wait_timeout, (gptr*) &net_wait_timeout, 0, GET_ULONG,
+ (gptr*) &global_system_variables.net_wait_timeout,
+ (gptr*) &max_system_variables.net_wait_timeout, 0, GET_ULONG,
REQUIRED_ARG, NET_WAIT_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0},
{0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};
-struct show_var_st init_vars[]= {
- {"back_log", (char*) &back_log, SHOW_LONG},
- {"basedir", mysql_home, SHOW_CHAR},
-#ifdef HAVE_BERKELEY_DB
- {"bdb_cache_size", (char*) &berkeley_cache_size, SHOW_LONG},
- {"bdb_log_buffer_size", (char*) &berkeley_log_buffer_size, SHOW_LONG},
- {"bdb_home", (char*) &berkeley_home, SHOW_CHAR_PTR},
- {"bdb_max_lock", (char*) &berkeley_max_lock, SHOW_LONG},
- {"bdb_logdir", (char*) &berkeley_logdir, SHOW_CHAR_PTR},
- {"bdb_shared_data", (char*) &berkeley_shared_data, SHOW_BOOL},
- {"bdb_tmpdir", (char*) &berkeley_tmpdir, SHOW_CHAR_PTR},
- {"bdb_version", (char*) DB_VERSION_STRING, SHOW_CHAR},
-#endif
- {"binlog_cache_size", (char*) &binlog_cache_size, SHOW_LONG},
- {"character_set", default_charset, SHOW_CHAR},
- {"character_sets", (char*) &charsets_list, SHOW_CHAR_PTR},
- {"concurrent_insert", (char*) &myisam_concurrent_insert, SHOW_MY_BOOL},
- {"connect_timeout", (char*) &connect_timeout, SHOW_LONG},
- {"datadir", mysql_real_data_home, SHOW_CHAR},
- {"delay_key_write", (char*) &myisam_delay_key_write, SHOW_MY_BOOL},
- {"delayed_insert_limit", (char*) &delayed_insert_limit, SHOW_LONG},
- {"delayed_insert_timeout", (char*) &delayed_insert_timeout, SHOW_LONG},
- {"delayed_queue_size", (char*) &delayed_queue_size, SHOW_LONG},
- {"flush", (char*) &myisam_flush, SHOW_MY_BOOL},
- {"flush_time", (char*) &flush_time, SHOW_LONG},
- {"ft_min_word_len", (char*) &ft_min_word_len, SHOW_LONG},
- {"ft_max_word_len", (char*) &ft_max_word_len, SHOW_LONG},
- {"ft_max_word_len_for_sort",(char*) &ft_max_word_len_for_sort, SHOW_LONG},
- {"ft_boolean_syntax", (char*) ft_boolean_syntax, SHOW_CHAR},
- {"have_bdb", (char*) &have_berkeley_db, SHOW_HAVE},
- {"have_innodb", (char*) &have_innodb, SHOW_HAVE},
- {"have_isam", (char*) &have_isam, SHOW_HAVE},
- {"have_raid", (char*) &have_raid, SHOW_HAVE},
- {"have_symlink", (char*) &have_symlink, SHOW_HAVE},
- {"have_openssl", (char*) &have_openssl, SHOW_HAVE},
- {"have_query_cache", (char*) &have_query_cache, SHOW_HAVE},
- {"init_file", (char*) &opt_init_file, SHOW_CHAR_PTR},
-#ifdef HAVE_INNOBASE_DB
- {"innodb_additional_mem_pool_size", (char*) &innobase_additional_mem_pool_size, SHOW_LONG },
- {"innodb_buffer_pool_size", (char*) &innobase_buffer_pool_size, SHOW_LONG },
- {"innodb_data_file_path", (char*) &innobase_data_file_path, SHOW_CHAR_PTR},
- {"innodb_data_home_dir", (char*) &innobase_data_home_dir, SHOW_CHAR_PTR},
- {"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_MY_BOOL},
- {"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 },
- {"innodb_log_arch_dir", (char*) &innobase_log_arch_dir, SHOW_CHAR_PTR},
- {"innodb_log_archive", (char*) &innobase_log_archive, SHOW_MY_BOOL},
- {"innodb_log_buffer_size", (char*) &innobase_log_buffer_size, SHOW_LONG },
- {"innodb_log_file_size", (char*) &innobase_log_file_size, SHOW_LONG},
- {"innodb_log_files_in_group", (char*) &innobase_log_files_in_group, SHOW_LONG},
- {"innodb_log_group_home_dir", (char*) &innobase_log_group_home_dir, SHOW_CHAR_PTR},
- {"innodb_mirrored_log_groups", (char*) &innobase_mirrored_log_groups, SHOW_LONG},
-#endif
- {"interactive_timeout", (char*) &net_interactive_timeout, SHOW_LONG},
- {"join_buffer_size", (char*) &join_buff_size, SHOW_LONG},
- {"key_buffer_size", (char*) &keybuff_size, SHOW_LONG},
- {"language", language, SHOW_CHAR},
- {"large_files_support", (char*) &opt_large_files, SHOW_BOOL},
-#ifdef HAVE_MLOCKALL
- {"locked_in_memory", (char*) &locked_in_memory, SHOW_BOOL},
-#endif
- {"log", (char*) &opt_log, SHOW_BOOL},
- {"log_update", (char*) &opt_update_log, SHOW_BOOL},
- {"log_bin", (char*) &opt_bin_log, SHOW_BOOL},
- {"log_slave_updates", (char*) &opt_log_slave_updates, SHOW_BOOL},
- {"log_slow_queries", (char*) &opt_slow_log, SHOW_BOOL},
- {"long_query_time", (char*) &long_query_time, SHOW_LONG},
- {"low_priority_updates", (char*) &low_priority_updates, SHOW_BOOL},
- {"lower_case_table_names", (char*) &lower_case_table_names, SHOW_LONG},
- {"max_allowed_packet", (char*) &max_allowed_packet, SHOW_LONG},
- {"max_binlog_cache_size", (char*) &max_binlog_cache_size, SHOW_LONG},
- {"max_binlog_size", (char*) &max_binlog_size, SHOW_LONG},
- {"max_connections", (char*) &max_connections, SHOW_LONG},
- {"max_connect_errors", (char*) &max_connect_errors, SHOW_LONG},
- {"max_delayed_threads", (char*) &max_insert_delayed_threads, SHOW_LONG},
- {"max_heap_table_size", (char*) &max_heap_table_size, SHOW_LONG},
- {"max_join_size", (char*) &max_join_size, SHOW_LONG},
- {"max_sort_length", (char*) &max_item_sort_length, SHOW_LONG},
- {"max_user_connections", (char*) &max_user_connections, SHOW_LONG},
- {"max_tmp_tables", (char*) &max_tmp_tables, SHOW_LONG},
- {"max_write_lock_count", (char*) &max_write_lock_count, SHOW_LONG},
- {"myisam_bulk_insert_tree_size", (char*) &myisam_bulk_insert_tree_size, SHOW_INT},
- {"myisam_max_extra_sort_file_size", (char*) &myisam_max_extra_sort_file_size,
- SHOW_LONG},
- {"myisam_max_sort_file_size",(char*) &myisam_max_sort_file_size, SHOW_LONG},
- {"myisam_recover_options", (char*) &myisam_recover_options_str, SHOW_CHAR_PTR},
- {"myisam_sort_buffer_size", (char*) &myisam_sort_buffer_size, SHOW_LONG},
-#ifdef __NT__
- {"named_pipe", (char*) &opt_enable_named_pipe, SHOW_BOOL},
-#endif
- {"net_buffer_length", (char*) &net_buffer_length, SHOW_LONG},
- {"net_read_timeout", (char*) &net_read_timeout, SHOW_LONG},
- {"net_retry_count", (char*) &mysqld_net_retry_count, SHOW_LONG},
- {"net_write_timeout", (char*) &net_write_timeout, SHOW_LONG},
- {"open_files_limit", (char*) &open_files_limit, SHOW_LONG},
- {"pid_file", (char*) pidfile_name, SHOW_CHAR},
- {"port", (char*) &mysql_port, SHOW_INT},
- {"protocol_version", (char*) &protocol_version, SHOW_INT},
- {"record_buffer", (char*) &my_default_record_cache_size,SHOW_LONG},
- {"record_rnd_buffer", (char*) &record_rnd_cache_size, SHOW_LONG},
- {"rpl_recovery_rank", (char*) &rpl_recovery_rank, SHOW_LONG},
- {"query_buffer_size", (char*) &query_buff_size, SHOW_LONG},
-#ifdef HAVE_QUERY_CACHE
- {"query_cache_limit", (char*) &query_cache.query_cache_limit, SHOW_LONG},
- {"query_cache_size", (char*) &query_cache.query_cache_size, SHOW_LONG},
- {"query_cache_startup_type",(char*) &query_cache_startup_type, SHOW_LONG},
-#endif /*HAVE_QUERY_CACHE*/
- {"safe_show_database", (char*) &opt_safe_show_db, SHOW_BOOL},
- {"server_id", (char*) &server_id, SHOW_LONG},
- {"slave_net_timeout", (char*) &slave_net_timeout, SHOW_LONG},
- {"skip_locking", (char*) &my_disable_locking, SHOW_MY_BOOL},
- {"skip_networking", (char*) &opt_disable_networking, SHOW_BOOL},
- {"skip_show_database", (char*) &opt_skip_show_db, SHOW_BOOL},
- {"slow_launch_time", (char*) &slow_launch_time, SHOW_LONG},
- {"socket", (char*) &mysql_unix_port, SHOW_CHAR_PTR},
- {"sort_buffer", (char*) &sortbuff_size, SHOW_LONG},
- {"sql_mode", (char*) &opt_sql_mode, SHOW_LONG},
- {"table_cache", (char*) &table_cache_size, SHOW_LONG},
- {"table_type", (char*) &default_table_type_name, SHOW_CHAR_PTR},
- {"thread_cache_size", (char*) &thread_cache_size, SHOW_LONG},
-#ifdef HAVE_THR_SETCONCURRENCY
- {"thread_concurrency", (char*) &concurrency, SHOW_LONG},
-#endif
- {"thread_stack", (char*) &thread_stack, SHOW_LONG},
- {"transaction_isolation", (char*) &default_tx_isolation_name, SHOW_CHAR_PTR},
-#ifdef HAVE_TZNAME
- {"timezone", time_zone, SHOW_CHAR},
-#endif
- {"tmp_table_size", (char*) &tmp_table_size, SHOW_LONG},
- {"tmpdir", (char*) &mysql_tmpdir, SHOW_CHAR_PTR},
- {"version", server_version, SHOW_CHAR},
- {"wait_timeout", (char*) &net_wait_timeout, SHOW_LONG},
- {NullS, NullS, SHOW_LONG}
-};
struct show_var_st status_vars[]= {
{"Aborted_clients", (char*) &aborted_threads, SHOW_LONG},
@@ -3740,6 +3735,7 @@ struct show_var_st status_vars[]= {
{"Com_show_slave_hosts", (char*) (com_stat+(uint) SQLCOM_SHOW_SLAVE_HOSTS),SHOW_LONG},
{"Com_show_slave_status", (char*) (com_stat+(uint) SQLCOM_SHOW_SLAVE_STAT),SHOW_LONG},
{"Com_show_status", (char*) (com_stat+(uint) SQLCOM_SHOW_STATUS),SHOW_LONG},
+ {"Com_show_innodb_status", (char*) (com_stat+(uint) SQLCOM_SHOW_INNODB_STATUS),SHOW_LONG},
{"Com_show_tables", (char*) (com_stat+(uint) SQLCOM_SHOW_TABLES),SHOW_LONG},
{"Com_show_variables", (char*) (com_stat+(uint) SQLCOM_SHOW_VARIABLES),SHOW_LONG},
{"Com_slave_start", (char*) (com_stat+(uint) SQLCOM_SLAVE_START),SHOW_LONG},
@@ -3876,7 +3872,7 @@ Starts the MySQL server\n");
");
puts("");
#endif
- print_defaults("my",load_default_groups);
+ print_defaults(MYSQL_CONFIG_NAME,load_default_groups);
puts("");
fix_paths();
set_ports();
@@ -3884,38 +3880,9 @@ Starts the MySQL server\n");
my_print_help(my_long_options);
my_print_variables(my_long_options);
- printf("\
+ puts("\n\
To see what values a running MySQL server is using, type\n\
-'mysqladmin variables' instead of 'mysqld --help'.\n\
-The default values (after parsing the command line arguments) are:\n\n");
-
- printf("basedir: %s\n",mysql_home);
- printf("datadir: %s\n",mysql_real_data_home);
- printf("tmpdir: %s\n",mysql_tmpdir);
- printf("language: %s\n",language);
-#ifndef __WIN__
- printf("pid file: %s\n",pidfile_name);
-#endif
- if (opt_logname)
- printf("logfile: %s\n",opt_logname);
- if (opt_update_logname)
- printf("update log: %s\n",opt_update_logname);
- if (opt_bin_log)
- {
- printf("binary log: %s\n",opt_bin_logname ? opt_bin_logname : "");
- printf("binary log index: %s\n",
- opt_binlog_index_name ? opt_binlog_index_name : "");
- }
- if (opt_slow_logname)
- printf("update log: %s\n",opt_slow_logname);
- printf("TCP port: %d\n",mysql_port);
-#if defined(HAVE_SYS_UN_H)
- printf("Unix socket: %s\n",mysql_unix_port);
-#endif
- if (my_disable_locking)
- puts("\nsystem locking is not in use");
- if (opt_noacl)
- puts("\nGrant tables are not used. All users have full access rights");
+'mysqladmin variables' instead of 'mysqld --help'.");
}
@@ -3925,10 +3892,19 @@ static void set_options(void)
opt_specialflag |= SPECIAL_NO_PRIOR;
#endif
- (void) strmake(default_charset, MYSQL_CHARSET, sizeof(default_charset)-1);
+ sys_charset.value= (char*) MYSQL_CHARSET;
(void) strmake(language, LANGUAGE, sizeof(language)-1);
(void) strmake(mysql_real_data_home, get_relative_path(DATADIR),
- sizeof(mysql_real_data_home-1));
+ sizeof(mysql_real_data_home)-1);
+
+ /* 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.select_limit= (ulong) HA_POS_ERROR;
+ max_system_variables.select_limit= (ulong) HA_POS_ERROR;
+ global_system_variables.max_join_size= (ulong) HA_POS_ERROR;
+ max_system_variables.max_join_size= (ulong) HA_POS_ERROR;
+
#ifdef __WIN__
/* Allow Win32 users to move MySQL anywhere */
{
@@ -3944,9 +3920,8 @@ static void set_options(void)
(void) strmake(mysql_home, tmpenv, sizeof(mysql_home)-1);
#endif
-#if defined( HAVE_mit_thread ) || defined( __WIN__ ) || defined( HAVE_LINUXTHREADS )
my_disable_locking=myisam_single_user= 1;
-#endif
+ opt_external_locking=0;
my_bind_addr = htonl( INADDR_ANY );
}
@@ -3966,7 +3941,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
opt_sql_mode = (MODE_REAL_AS_FLOAT | MODE_PIPES_AS_CONCAT |
MODE_ANSI_QUOTES | MODE_IGNORE_SPACE | MODE_SERIALIZABLE
| MODE_ONLY_FULL_GROUP_BY);
- default_tx_isolation= ISO_SERIALIZABLE;
+ global_system_variables.tx_isolation= ISO_SERIALIZABLE;
break;
case 'b':
strmake(mysql_home,argument,sizeof(mysql_home)-1);
@@ -3994,6 +3969,14 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
safemalloc_mem_limit = atoi(argument);
#endif
break;
+#ifdef EMBEDDED_LIBRARY
+ case OPT_MAX_ALLOWED_PACKET:
+ max_allowed_packet= atoi(argument);
+ break;
+ case OPT_NET_BUFFER_LENGTH:
+ net_buffer_length= atoi(argument);
+ break;
+#endif
case 'v':
case 'V':
print_version();
@@ -4020,124 +4003,125 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
opt_bin_log=1;
break;
case (int) OPT_INIT_RPL_ROLE:
+ {
+ int role;
+ if ((role=find_type(argument, &rpl_role_typelib, 2)) <= 0)
{
- int role;
- if ((role=find_type(argument, &rpl_role_typelib, 2)) <= 0)
- {
- fprintf(stderr, "Unknown replication role: %s\n", argument);
- exit(1);
- }
- rpl_status = (role == 1) ? RPL_AUTH_MASTER : RPL_IDLE_SLAVE;
- break;
+ fprintf(stderr, "Unknown replication role: %s\n", argument);
+ exit(1);
}
+ rpl_status = (role == 1) ? RPL_AUTH_MASTER : RPL_IDLE_SLAVE;
+ break;
+ }
case (int)OPT_REPLICATE_IGNORE_DB:
+ {
+ i_string *db = new i_string(argument);
+ replicate_ignore_db.push_back(db);
+ break;
+ }
+ case (int)OPT_REPLICATE_DO_DB:
+ {
+ i_string *db = new i_string(argument);
+ replicate_do_db.push_back(db);
+ break;
+ }
+ case (int)OPT_REPLICATE_REWRITE_DB:
+ {
+ char* key = argument,*p, *val;
+
+ if (!(p= strstr(argument, "->")))
{
- i_string *db = new i_string(argument);
- replicate_ignore_db.push_back(db);
- break;
+ fprintf(stderr,
+ "Bad syntax in replicate-rewrite-db - missing '->'!\n");
+ exit(1);
}
- case (int)OPT_REPLICATE_DO_DB:
+ val= p--;
+ while (my_isspace(system_charset_info, *p) && p > argument)
+ *p-- = 0;
+ if (p == argument)
{
- i_string *db = new i_string(argument);
- replicate_do_db.push_back(db);
- break;
+ fprintf(stderr,
+ "Bad syntax in replicate-rewrite-db - empty FROM db!\n");
+ exit(1);
}
- case (int)OPT_REPLICATE_REWRITE_DB:
+ *val= 0;
+ val+= 2;
+ while (*val && my_isspace(system_charset_info, *val))
+ *val++;
+ if (!*val)
{
- char* key = argument,*p, *val;
- p = strstr(argument, "->");
- if (!p)
- {
- fprintf(stderr,
- "Bad syntax in replicate-rewrite-db - missing '->'!\n");
- exit(1);
- }
- val = p--;
- while (my_isspace(system_charset_info, *p) && p > argument) *p-- = 0;
- if (p == argument)
- {
- fprintf(stderr,
- "Bad syntax in replicate-rewrite-db - empty FROM db!\n");
- exit(1);
- }
- *val = 0;
- val += 2;
- while (*val && my_isspace(system_charset_info, *val))
- *val++;
- if (!*val)
- {
- fprintf(stderr,
- "Bad syntax in replicate-rewrite-db - empty TO db!\n");
- exit(1);
- }
-
- i_string_pair* db_pair = new i_string_pair(key, val);
- replicate_rewrite_db.push_back(db_pair);
- break;
+ fprintf(stderr,
+ "Bad syntax in replicate-rewrite-db - empty TO db!\n");
+ exit(1);
}
+ i_string_pair *db_pair = new i_string_pair(key, val);
+ replicate_rewrite_db.push_back(db_pair);
+ break;
+ }
+
case (int)OPT_BINLOG_IGNORE_DB:
- {
- i_string *db = new i_string(argument);
- binlog_ignore_db.push_back(db);
- break;
- }
+ {
+ i_string *db = new i_string(argument);
+ binlog_ignore_db.push_back(db);
+ break;
+ }
case (int)OPT_BINLOG_DO_DB:
- {
- i_string *db = new i_string(argument);
- binlog_do_db.push_back(db);
- break;
- }
+ {
+ i_string *db = new i_string(argument);
+ binlog_do_db.push_back(db);
+ break;
+ }
case (int)OPT_REPLICATE_DO_TABLE:
+ {
+ if (!do_table_inited)
+ init_table_rule_hash(&replicate_do_table, &do_table_inited);
+ if (add_table_rule(&replicate_do_table, argument))
{
- if (!do_table_inited)
- init_table_rule_hash(&replicate_do_table, &do_table_inited);
- if(add_table_rule(&replicate_do_table, argument))
- {
- fprintf(stderr, "Could not add do table rule '%s'!\n", argument);
- exit(1);
- }
- table_rules_on = 1;
- break;
+ fprintf(stderr, "Could not add do table rule '%s'!\n", argument);
+ exit(1);
}
+ table_rules_on = 1;
+ break;
+ }
case (int)OPT_REPLICATE_WILD_DO_TABLE:
+ {
+ if (!wild_do_table_inited)
+ init_table_rule_array(&replicate_wild_do_table,
+ &wild_do_table_inited);
+ if (add_wild_table_rule(&replicate_wild_do_table, argument))
{
- if (!wild_do_table_inited)
- init_table_rule_array(&replicate_wild_do_table,
- &wild_do_table_inited);
- if(add_wild_table_rule(&replicate_wild_do_table, argument))
- {
- fprintf(stderr, "Could not add do table rule '%s'!\n", argument);
- exit(1);
- }
- table_rules_on = 1;
- break;
+ fprintf(stderr, "Could not add do table rule '%s'!\n", argument);
+ exit(1);
}
+ table_rules_on = 1;
+ break;
+ }
case (int)OPT_REPLICATE_WILD_IGNORE_TABLE:
+ {
+ if (!wild_ignore_table_inited)
+ init_table_rule_array(&replicate_wild_ignore_table,
+ &wild_ignore_table_inited);
+ if (add_wild_table_rule(&replicate_wild_ignore_table, argument))
{
- if (!wild_ignore_table_inited)
- init_table_rule_array(&replicate_wild_ignore_table,
- &wild_ignore_table_inited);
- if(add_wild_table_rule(&replicate_wild_ignore_table, argument))
- {
- fprintf(stderr, "Could not add ignore table rule '%s'!\n", argument);
- exit(1);
- }
- table_rules_on = 1;
- break;
+ fprintf(stderr, "Could not add ignore table rule '%s'!\n", argument);
+ exit(1);
}
+ table_rules_on = 1;
+ break;
+ }
case (int)OPT_REPLICATE_IGNORE_TABLE:
+ {
+ if (!ignore_table_inited)
+ init_table_rule_hash(&replicate_ignore_table, &ignore_table_inited);
+ if (add_table_rule(&replicate_ignore_table, argument))
{
- if (!ignore_table_inited)
- init_table_rule_hash(&replicate_ignore_table, &ignore_table_inited);
- if(add_table_rule(&replicate_ignore_table, argument))
- {
- fprintf(stderr, "Could not add ignore table rule '%s'!\n", argument);
- exit(1);
- }
- table_rules_on = 1;
- break;
+ fprintf(stderr, "Could not add ignore table rule '%s'!\n", argument);
+ exit(1);
}
+ table_rules_on = 1;
+ break;
+ }
case (int) OPT_SLOW_QUERY_LOG:
opt_slow_log=1;
break;
@@ -4147,38 +4131,32 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
break;
case (int) OPT_SKIP_NEW:
opt_specialflag|= SPECIAL_NO_NEW_FUNC;
- myisam_delay_key_write=0;
+ delay_key_write_options= (uint) DELAY_KEY_WRITE_NONE;
myisam_concurrent_insert=0;
myisam_recover_options= HA_RECOVER_NONE;
my_disable_symlinks=1;
my_use_symdir=0;
have_symlink=SHOW_OPTION_DISABLED;
- ha_open_options&= ~HA_OPEN_ABORT_IF_CRASHED;
+ ha_open_options&= ~(HA_OPEN_ABORT_IF_CRASHED | HA_OPEN_DELAY_KEY_WRITE);
#ifdef HAVE_QUERY_CACHE
query_cache_size=0;
#endif
break;
case (int) OPT_SAFE:
opt_specialflag|= SPECIAL_SAFE_MODE;
- myisam_delay_key_write=0;
+ delay_key_write_options= (uint) DELAY_KEY_WRITE_NONE;
myisam_recover_options= HA_RECOVER_NONE; // To be changed
- ha_open_options&= ~HA_OPEN_ABORT_IF_CRASHED;
+ ha_open_options&= ~(HA_OPEN_ABORT_IF_CRASHED | HA_OPEN_DELAY_KEY_WRITE);
break;
case (int) OPT_SKIP_PRIOR:
opt_specialflag|= SPECIAL_NO_PRIOR;
break;
case (int) OPT_SKIP_LOCK:
- my_disable_locking=myisam_single_user= 1;
+ opt_external_locking=0;
break;
case (int) OPT_SKIP_HOST_CACHE:
opt_specialflag|= SPECIAL_NO_HOST_CACHE;
break;
- case (int) OPT_ENABLE_LOCK:
- my_disable_locking=myisam_single_user=0;
- break;
- case (int) OPT_USE_LOCKING:
- my_disable_locking=0;
- break;
case (int) OPT_SKIP_RESOLVE:
opt_specialflag|=SPECIAL_NO_RESOLVE;
break;
@@ -4253,57 +4231,61 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
flush_time=0; // No auto flush
break;
case OPT_LOW_PRIORITY_UPDATES:
- thd_startup_options|=OPTION_LOW_PRIORITY_UPDATES;
thr_upgraded_concurrent_insert_lock= TL_WRITE_LOW_PRIORITY;
- low_priority_updates=1;
+ global_system_variables.low_priority_updates=1;
break;
case OPT_BOOTSTRAP:
opt_noacl=opt_bootstrap=1;
break;
case OPT_TABLE_TYPE:
+ {
+ int type;
+ if ((type=find_type(argument, &ha_table_typelib, 2)) <= 0)
{
- int type;
- if ((type=find_type(argument, &ha_table_typelib, 2)) <= 0)
- {
- fprintf(stderr,"Unknown table type: %s\n",argument);
- exit(1);
- }
- default_table_type= (enum db_type) type;
- break;
+ fprintf(stderr,"Unknown table type: %s\n",argument);
+ exit(1);
}
+ global_system_variables.table_type= type-1;
+ break;
+ }
case OPT_SERVER_ID:
server_id_supplied = 1;
break;
+ case OPT_DELAY_KEY_WRITE_ALL:
+ if (argument != disabled_my_option)
+ argument= (char*) "ALL";
+ /* Fall through */
case OPT_DELAY_KEY_WRITE:
- ha_open_options|=HA_OPEN_DELAY_KEY_WRITE;
- myisam_delay_key_write=1;
- break;
- case 'C':
- strmake(default_charset, argument, sizeof(default_charset)-1);
+ if (argument == disabled_my_option)
+ delay_key_write_options= (uint) DELAY_KEY_WRITE_NONE;
+ else if (! argument)
+ delay_key_write_options= (uint) DELAY_KEY_WRITE_ON;
+ else
+ {
+ int type;
+ if ((type=find_type(argument, &delay_key_write_typelib, 2)) <= 0)
+ {
+ fprintf(stderr,"Unknown delay_key_write type: %s\n",argument);
+ exit(1);
+ }
+ delay_key_write_options= (uint) type-1;
+ }
break;
case OPT_CHARSETS_DIR:
strmake(mysql_charsets_dir, argument, sizeof(mysql_charsets_dir)-1);
charsets_dir = mysql_charsets_dir;
break;
-#ifdef HAVE_OPENSSL
-#include "sslopt-case.h"
-#endif
- case OPT_DES_KEY_FILE:
-#ifdef HAVE_OPENSSL
- des_key_file=argument;
-#endif
- break;
case OPT_TX_ISOLATION:
+ {
+ int type;
+ if ((type=find_type(argument, &tx_isolation_typelib, 2)) <= 0)
{
- int type;
- if ((type=find_type(argument, &tx_isolation_typelib, 2)) <= 0)
- {
- fprintf(stderr,"Unknown transaction isolation type: %s\n",argument);
- exit(1);
- }
- default_tx_isolation= (enum_tx_isolation) (type-1);
- break;
+ fprintf(stderr,"Unknown transaction isolation type: %s\n",argument);
+ exit(1);
}
+ global_system_variables.tx_isolation= (type-1);
+ break;
+ }
#ifdef HAVE_BERKELEY_DB
case OPT_BDB_NOSYNC:
berkeley_env_flags|=DB_TXN_NOSYNC;
@@ -4312,22 +4294,22 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
berkeley_init_flags&= ~(DB_RECOVER);
break;
case OPT_BDB_LOCK:
+ {
+ int type;
+ if ((type=find_type(argument, &berkeley_lock_typelib, 2)) > 0)
+ berkeley_lock_type=berkeley_lock_types[type-1];
+ else
{
- int type;
- if ((type=find_type(argument, &berkeley_lock_typelib, 2)) > 0)
- berkeley_lock_type=berkeley_lock_types[type-1];
+ if (test_if_int(argument,(uint) strlen(argument)))
+ berkeley_lock_scan_time=atoi(argument);
else
{
- if (test_if_int(argument,(uint) strlen(argument)))
- berkeley_lock_scan_time=atoi(argument);
- else
- {
- fprintf(stderr,"Unknown lock type: %s\n",argument);
- exit(1);
- }
+ fprintf(stderr,"Unknown lock type: %s\n",argument);
+ exit(1);
}
- break;
}
+ break;
+ }
case OPT_BDB_SHARED:
berkeley_init_flags&= ~(DB_PRIVATE);
berkeley_shared_data=1;
@@ -4354,47 +4336,44 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
case OPT_INNODB_LOG_ARCHIVE:
innobase_log_archive= argument ? test(atoi(argument)) : 1;
break;
- case OPT_INNODB_FLUSH_LOG_AT_TRX_COMMIT:
- innobase_flush_log_at_trx_commit= argument ? test(atoi(argument)) : 1;
- break;
case OPT_INNODB_FAST_SHUTDOWN:
innobase_fast_shutdown= argument ? test(atoi(argument)) : 1;
break;
#endif /* HAVE_INNOBASE_DB */
case OPT_MYISAM_RECOVER:
+ {
+ if (!argument || !argument[0])
{
- if (!argument || !argument[0])
- {
- myisam_recover_options= HA_RECOVER_DEFAULT;
- myisam_recover_options_str= myisam_recover_typelib.type_names[0];
- }
- else
- {
- myisam_recover_options_str=argument;
- if ((myisam_recover_options=
- find_bit_type(argument, &myisam_recover_typelib)) == ~(ulong) 0)
- {
- fprintf(stderr, "Unknown option to myisam-recover: %s\n",argument);
- exit(1);
- }
- }
- ha_open_options|=HA_OPEN_ABORT_IF_CRASHED;
- break;
+ myisam_recover_options= HA_RECOVER_DEFAULT;
+ myisam_recover_options_str= myisam_recover_typelib.type_names[0];
}
- case OPT_SQL_MODE:
+ else
{
- sql_mode_str = argument;
- if ((opt_sql_mode =
- find_bit_type(argument, &sql_mode_typelib)) == ~(ulong) 0)
+ myisam_recover_options_str=argument;
+ if ((myisam_recover_options=
+ find_bit_type(argument, &myisam_recover_typelib)) == ~(ulong) 0)
{
- fprintf(stderr, "Unknown option to sql-mode: %s\n", argument);
+ fprintf(stderr, "Unknown option to myisam-recover: %s\n",argument);
exit(1);
}
- default_tx_isolation= ((opt_sql_mode & MODE_SERIALIZABLE) ?
- ISO_SERIALIZABLE :
- ISO_READ_COMMITTED);
- break;
}
+ ha_open_options|=HA_OPEN_ABORT_IF_CRASHED;
+ break;
+ }
+ case OPT_SQL_MODE:
+ {
+ sql_mode_str = argument;
+ if ((opt_sql_mode =
+ find_bit_type(argument, &sql_mode_typelib)) == ~(ulong) 0)
+ {
+ fprintf(stderr, "Unknown option to sql-mode: %s\n", argument);
+ exit(1);
+ }
+ global_system_variables.tx_isolation= ((opt_sql_mode & MODE_SERIALIZABLE) ?
+ ISO_SERIALIZABLE :
+ ISO_READ_COMMITTED);
+ break;
+ }
case OPT_MASTER_PASSWORD:
master_password=argument;
break;
@@ -4413,30 +4392,41 @@ static void get_options(int argc,char **argv)
{
int ho_error;
- myisam_delay_key_write=1; // Allow use of this
-#ifndef HAVE_purify
- my_use_symdir=1; // Use internal symbolic links
-#else
- /* Symlinks gives too many warnings with purify */
- my_disable_symlinks=1;
- my_use_symdir=0;
- have_symlink=SHOW_OPTION_DISABLED;
-#endif
-
if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option)))
exit(ho_error);
- fix_paths();
- default_table_type_name=ha_table_typelib.type_names[default_table_type-1];
- default_tx_isolation_name=tx_isolation_typelib.type_names[default_tx_isolation];
- /* To be deleted in MySQL 4.0 */
- if (!record_rnd_cache_size)
- record_rnd_cache_size=my_default_record_cache_size;
+#ifdef HAVE_BROKEN_REALPATH
+ my_use_symdir=0;
+ my_disable_symlinks=1;
+ have_symlink=SHOW_OPTION_NO;
+#else
+ if (!my_use_symdir)
+ {
+ my_disable_symlinks=1;
+ have_symlink=SHOW_OPTION_DISABLED;
+ }
+#endif
+ /* Set global MyISAM variables from delay_key_write_options */
+ fix_delay_key_write((THD*) 0, OPT_GLOBAL);
- /* Fix variables that are base 1024*1024 */
- myisam_max_temp_length= (my_off_t) min(((ulonglong) myisam_max_sort_file_size)*1024*1024, (ulonglong) MAX_FILE_SIZE);
- myisam_max_extra_temp_length= (my_off_t) min(((ulonglong) myisam_max_extra_sort_file_size)*1024*1024, (ulonglong) MAX_FILE_SIZE);
+ if (mysqld_chroot)
+ set_root(mysqld_chroot);
+ fix_paths();
+ /*
+ Set some global variables from the global_system_variables
+ In most cases the global variables will not be used
+ */
+ my_disable_locking= myisam_single_user= test(opt_external_locking == 0);
+ my_default_record_cache_size=global_system_variables.read_buff_size;
+ myisam_max_temp_length=
+ (my_off_t) min(global_system_variables.myisam_max_sort_file_size,
+ (ulonglong) MAX_FILE_SIZE);
+ myisam_max_extra_temp_length=
+ (my_off_t) min(global_system_variables.myisam_max_extra_sort_file_size,
+ (ulonglong) MAX_FILE_SIZE);
+
+ /* Set global variables based on startup options */
myisam_block_size=(uint) 1 << my_bit_log2(opt_myisam_block_size);
}
@@ -4479,6 +4469,7 @@ 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
convert_dirname(mysql_home,mysql_home,NullS);
convert_dirname(mysql_real_data_home,mysql_real_data_home,NullS);
@@ -4487,7 +4478,7 @@ static void fix_paths(void)
(void) my_load_path(mysql_real_data_home,mysql_real_data_home,mysql_home);
(void) my_load_path(pidfile_name,pidfile_name,mysql_real_data_home);
- char buff[FN_REFLEN],*sharedir=get_relative_path(SHAREDIR);
+ char *sharedir=get_relative_path(SHAREDIR);
if (test_if_hard_path(sharedir))
strmake(buff,sharedir,sizeof(buff)-1); /* purecov: tested */
else
@@ -4503,24 +4494,19 @@ static void fix_paths(void)
charsets_dir=mysql_charsets_dir;
}
- /* Add '/' to TMPDIR if needed */
- char *tmp= (char*) my_malloc(FN_REFLEN,MYF(MY_FAE));
- if (tmp)
- {
- char *end=convert_dirname(tmp, mysql_tmpdir, NullS);
-
- mysql_tmpdir=(char*) my_realloc(tmp,(uint) (end-tmp)+1,
- MYF(MY_HOLD_ON_ERROR));
- allocated_mysql_tmpdir=mysql_tmpdir;
- }
+ char *end=convert_dirname(buff, opt_mysql_tmpdir, NullS);
+ if (!(mysql_tmpdir= my_memdup((byte*) buff,(uint) (end-buff)+1,
+ MYF(MY_FAE))))
+ exit(1);
if (!slave_load_tmpdir)
{
- // no need to check return value, if we fail, my_malloc() never returns
- slave_load_tmpdir = (char*) my_strdup(mysql_tmpdir, MYF(MY_FAE));
+ if (!(slave_load_tmpdir = (char*) my_strdup(mysql_tmpdir, MYF(MY_FAE))))
+ exit(1);
}
}
+
#ifdef SET_RLIMIT_NOFILE
static uint set_maximum_open_files(uint max_file_limit)
{
@@ -4577,10 +4563,10 @@ static uint set_maximum_open_files(uint max_file_limit)
}
#endif
- /*
- Return a bitfield from a string of substrings separated by ','
- returns ~(ulong) 0 on error.
- */
+/*
+ Return a bitfield from a string of substrings separated by ','
+ returns ~(ulong) 0 on error.
+*/
static ulong find_bit_type(const char *x, TYPELIB *bit_lib)
{
@@ -4639,7 +4625,7 @@ skipp: ;
/*****************************************************************************
-** Instantiate templates
+ Instantiate templates
*****************************************************************************/
#ifdef __GNUC__
@@ -4648,4 +4634,6 @@ template class I_List<THD>;
template class I_List_iterator<THD>;
template class I_List<i_string>;
template class I_List<i_string_pair>;
+
+FIX_GCC_LINKING_PROBLEM
#endif
diff --git a/sql/net_pkg.cc b/sql/net_pkg.cc
index fa3abc68bfa..1e7536e3007 100644
--- a/sql/net_pkg.cc
+++ b/sql/net_pkg.cc
@@ -37,7 +37,7 @@ void send_error(NET *net, uint sql_errno, const char *err)
{
if (sql_errno)
err=ER(sql_errno);
- else if (!err)
+ else
{
if ((err=net->last_error)[0])
sql_errno=net->last_errno;
@@ -95,9 +95,10 @@ void send_warning(NET *net, uint sql_errno, const char *err)
DBUG_VOID_RETURN;
}
-/**
-** write error package and flush to client
-** It's a little too low level, but I don't want to allow another buffer
+
+/*
+ Write error package and flush to client
+ It's a little too low level, but I don't want to allow another buffer
*/
/* VARARGS3 */
@@ -348,9 +349,9 @@ bool net_store_data(String* packet, I_List<i_string>* str_list)
I_List_iterator<i_string> it(*str_list);
i_string* s;
- while((s=it++))
+ while ((s=it++))
{
- if(tmp.length())
+ if (tmp.length())
tmp.append(',');
tmp.append(s->ptr);
}
@@ -378,3 +379,19 @@ net_store_data(String *packet, CONVERT *convert, const char *from)
return convert->store(packet, from, length);
return net_store_data(packet,from,length);
}
+
+/*
+ Function called by my_net_init() to set some check variables
+*/
+
+extern "C" {
+void my_net_local_init(NET *net)
+{
+ net->max_packet= (uint) global_system_variables.net_buffer_length;
+ net->read_timeout= (uint) global_system_variables.net_read_timeout;
+ net->write_timeout=(uint) global_system_variables.net_write_timeout;
+ net->retry_count= (uint) global_system_variables.net_retry_count;
+ net->max_packet_size= max(global_system_variables.net_buffer_length,
+ global_system_variables.max_allowed_packet);
+}
+}
diff --git a/sql/net_serv.cc b/sql/net_serv.cc
index 0d6e548a873..bb7100f31be 100644
--- a/sql/net_serv.cc
+++ b/sql/net_serv.cc
@@ -14,17 +14,14 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-/* Write and read of logical packets to/from socket
-** Writes are cached into net_buffer_length big packets.
-** Read packets are reallocated dynamicly when reading big packets.
-** Each logical packet has the following pre-info:
-** 3 byte length & 1 byte package-number.
-*/
+/*
+ Write and read of logical packets to/from socket
-#ifdef EMBEDDED_LIBRARY
-#define net_read_timeout net_read_timeout1
-#define net_write_timeout net_write_timeout1
-#endif
+ Writes are cached into net_buffer_length big packets.
+ Read packets are reallocated dynamicly when reading big packets.
+ Each logical packet has the following pre-info:
+ 3 byte length & 1 byte package-number.
+*/
#ifdef __WIN__
#include <winsock.h>
@@ -51,15 +48,10 @@
*/
#ifdef MYSQL_SERVER
-ulong max_allowed_packet=65536;
-extern ulong net_read_timeout,net_write_timeout;
-extern uint test_flags;
#define USE_QUERY_CACHE
+extern uint test_flags;
extern void query_cache_insert(NET *net, const char *packet, ulong length);
#else
-ulong max_allowed_packet=16*1024*1024L;
-ulong net_read_timeout= NET_READ_TIMEOUT;
-ulong net_write_timeout= NET_WRITE_TIMEOUT;
#endif
#if defined(__WIN__) || !defined(MYSQL_SERVER)
@@ -70,15 +62,12 @@ ulong net_write_timeout= NET_WRITE_TIMEOUT;
#ifndef NO_ALARM
#include "my_pthread.h"
void sql_print_error(const char *format,...);
-#define RETRY_COUNT mysqld_net_retry_count
-extern ulong mysqld_net_retry_count;
extern ulong bytes_sent, bytes_received;
extern pthread_mutex_t LOCK_bytes_sent , LOCK_bytes_received;
#else
#undef statistic_add
#define statistic_add(A,B,C)
#define DONT_USE_THR_ALARM
-#define RETRY_COUNT 1
#endif /* NO_ALARM */
#include "thr_alarm.h"
@@ -86,8 +75,6 @@ extern pthread_mutex_t LOCK_bytes_sent , LOCK_bytes_received;
#define TEST_BLOCKING 8
#define MAX_THREE_BYTES 255L*255L*255L
-ulong net_buffer_length=8192; /* Default length. Enlarged if necessary */
-
static int net_write_buff(NET *net,const char *packet,ulong len);
@@ -95,17 +82,16 @@ static int net_write_buff(NET *net,const char *packet,ulong len);
int my_net_init(NET *net, Vio* vio)
{
- if (!(net->buff=(uchar*) my_malloc((uint32) net_buffer_length+
+ DBUG_ENTER("my_net_init");
+ my_net_local_init(net); /* Set some limits */
+ if (!(net->buff=(uchar*) my_malloc((uint32) net->max_packet+
NET_HEADER_SIZE + COMP_HEADER_SIZE,
MYF(MY_WME))))
- return 1;
- if (net_buffer_length > max_allowed_packet)
- max_allowed_packet=net_buffer_length;
- net->buff_end=net->buff+(net->max_packet=net_buffer_length);
+ DBUG_RETURN(1);
+ net->buff_end=net->buff+net->max_packet;
net->vio = vio;
net->no_send_ok = 0;
net->error=0; net->return_errno=0; net->return_status=0;
- net->timeout=(uint) net_read_timeout; /* Timeout for read */
net->pkt_nr=net->compress_pkt_nr=0;
net->write_pos=net->read_pos = net->buff;
net->last_error[0]=0;
@@ -119,26 +105,33 @@ int my_net_init(NET *net, Vio* vio)
net->fd = vio_fd(vio); /* For perl DBI/DBD */
#if defined(MYSQL_SERVER) && !defined(___WIN__) && !defined(__EMX__) && !defined(OS2)
if (!(test_flags & TEST_BLOCKING))
- vio_blocking(vio, FALSE);
+ {
+ my_bool old_mode;
+ vio_blocking(vio, FALSE, &old_mode);
+ }
#endif
vio_fastsend(vio);
}
- return 0;
+ DBUG_RETURN(0);
}
+
void net_end(NET *net)
{
+ DBUG_ENTER("net_end");
my_free((gptr) net->buff,MYF(MY_ALLOW_ZERO_PTR));
net->buff=0;
+ DBUG_VOID_RETURN;
}
+
/* Realloc the packet buffer */
static my_bool net_realloc(NET *net, ulong length)
{
uchar *buff;
ulong pkt_length;
- if (length >= max_allowed_packet)
+ if (length >= net->max_packet_size)
{
DBUG_PRINT("error",("Packet too large (%lu)", length));
net->error=1;
@@ -146,8 +139,10 @@ static my_bool net_realloc(NET *net, ulong length)
return 1;
}
pkt_length = (length+IO_SIZE-1) & ~(IO_SIZE-1);
- /* We must allocate some extra bytes for the end 0 and to be able to
- read big compressed blocks */
+ /*
+ We must allocate some extra bytes for the end 0 and to be able to
+ read big compressed blocks
+ */
if (!(buff=(uchar*) my_realloc((char*) net->buff, (uint32) pkt_length +
NET_HEADER_SIZE + COMP_HEADER_SIZE,
MYF(MY_WME))))
@@ -167,23 +162,24 @@ static my_bool net_realloc(NET *net, ulong length)
void net_clear(NET *net)
{
+ DBUG_ENTER("net_clear");
#if !defined(EXTRA_DEBUG) && !defined(EMBEDDED_LIBRARY)
- int count; /* One may get 'unused' warn */
- bool is_blocking=vio_is_blocking(net->vio);
- if (is_blocking)
- vio_blocking(net->vio, FALSE);
- if (!vio_is_blocking(net->vio)) /* Safety if SSL */
{
- while ( (count = vio_read(net->vio, (char*) (net->buff),
- (uint32) net->max_packet)) > 0)
- DBUG_PRINT("info",("skipped %d bytes from file: %s",
- count,vio_description(net->vio)));
- if (is_blocking)
- vio_blocking(net->vio, TRUE);
+ int count; /* One may get 'unused' warn */
+ my_bool old_mode;
+ if (!vio_blocking(net->vio, FALSE, &old_mode))
+ {
+ while ((count = vio_read(net->vio, (char*) (net->buff),
+ (uint32) net->max_packet)) > 0)
+ DBUG_PRINT("info",("skipped %d bytes from file: %s",
+ count, vio_description(net->vio)));
+ vio_blocking(net->vio, TRUE, &old_mode);
+ }
}
#endif /* EXTRA_DEBUG */
net->pkt_nr=net->compress_pkt_nr=0; /* Ready for new command */
net->write_pos=net->buff;
+ DBUG_VOID_RETURN;
}
/* Flush write_buffer if not empty. */
@@ -374,7 +370,7 @@ net_real_write(NET *net,const char *packet,ulong len)
#ifndef NO_ALARM
thr_alarm_init(&alarmed);
if (net_blocking)
- thr_alarm(&alarmed,(uint) net_write_timeout,&alarm_buff);
+ thr_alarm(&alarmed,(uint) net->write_timeout,&alarm_buff);
#else
alarmed=0;
#endif /* NO_ALARM */
@@ -388,22 +384,23 @@ net_real_write(NET *net,const char *packet,ulong len)
#if (!defined(__WIN__) && !defined(__EMX__) && !defined(OS2))
if ((interrupted || length==0) && !thr_alarm_in_use(&alarmed))
{
- if (!thr_alarm(&alarmed,(uint) net_write_timeout,&alarm_buff))
+ if (!thr_alarm(&alarmed,(uint) net->write_timeout,&alarm_buff))
{ /* Always true for client */
- if (!vio_is_blocking(net->vio))
+ my_bool old_mode;
+ while (vio_blocking(net->vio, TRUE, &old_mode) < 0)
{
- while (vio_blocking(net->vio, TRUE) < 0)
- {
- if (vio_should_retry(net->vio) && retry_count++ < RETRY_COUNT)
- continue;
+ if (vio_should_retry(net->vio) && retry_count++ < net->retry_count)
+ continue;
#ifdef EXTRA_DEBUG
- fprintf(stderr,
- "%s: my_net_write: fcntl returned error %d, aborting thread\n",
- my_progname,vio_errno(net->vio));
+ fprintf(stderr,
+ "%s: my_net_write: fcntl returned error %d, aborting thread\n",
+ my_progname,vio_errno(net->vio));
#endif /* EXTRA_DEBUG */
- net->error=2; /* Close socket */
- goto end;
- }
+#ifdef MYSQL_SERVER
+ net->last_errno=ER_NET_ERROR_ON_WRITE;
+#endif
+ net->error=2; /* Close socket */
+ goto end;
}
retry_count=0;
continue;
@@ -414,7 +411,7 @@ net_real_write(NET *net,const char *packet,ulong len)
if (thr_alarm_in_use(&alarmed) && !thr_got_alarm(&alarmed) &&
interrupted)
{
- if (retry_count++ < RETRY_COUNT)
+ if (retry_count++ < net->retry_count)
continue;
#ifdef EXTRA_DEBUG
fprintf(stderr, "%s: write looped, aborting thread\n",
@@ -447,8 +444,9 @@ net_real_write(NET *net,const char *packet,ulong len)
#endif
if (thr_alarm_in_use(&alarmed))
{
+ my_bool old_mode;
thr_end_alarm(&alarmed);
- vio_blocking(net->vio, net_blocking);
+ vio_blocking(net->vio, net_blocking, &old_mode);
}
net->reading_or_writing=0;
DBUG_RETURN(((int) (pos != end)));
@@ -469,10 +467,12 @@ static void my_net_skip_rest(NET *net, uint32 remain, thr_alarm_t *alarmed)
{
ALARM alarm_buff;
uint retry_count=0;
+ my_bool old_mode;
+
if (!thr_alarm_in_use(&alarmed))
{
- if (!thr_alarm(alarmed,net->timeout,&alarm_buff) ||
- (!vio_is_blocking(net->vio) && vio_blocking(net->vio,TRUE) < 0))
+ if (!thr_alarm(alarmed,net->read_timeout,&alarm_buff) ||
+ vio_blocking(net->vio, TRUE, &old_mode) < 0)
return; /* Can't setup, abort */
}
while (remain > 0)
@@ -483,7 +483,7 @@ static void my_net_skip_rest(NET *net, uint32 remain, thr_alarm_t *alarmed)
my_bool interrupted = vio_should_retry(net->vio);
if (!thr_got_alarm(&alarmed) && interrupted)
{ /* Probably in MIT threads */
- if (retry_count++ < RETRY_COUNT)
+ if (retry_count++ < net->retry_count)
continue;
}
return;
@@ -521,7 +521,7 @@ my_real_read(NET *net, ulong *complen)
thr_alarm_init(&alarmed);
#ifndef NO_ALARM
if (net_blocking)
- thr_alarm(&alarmed,net->timeout,&alarm_buff);
+ thr_alarm(&alarmed,net->read_timeout,&alarm_buff);
#endif /* NO_ALARM */
pos = net->buff + net->where_b; /* net->packet -4 */
@@ -544,31 +544,29 @@ my_real_read(NET *net, ulong *complen)
*/
if ((interrupted || length == 0) && !thr_alarm_in_use(&alarmed))
{
- if (!thr_alarm(&alarmed,net->timeout,&alarm_buff)) /* Don't wait too long */
+ if (!thr_alarm(&alarmed,net->read_timeout,&alarm_buff)) /* Don't wait too long */
{
- if (!vio_is_blocking(net->vio))
- {
- while (vio_blocking(net->vio,TRUE) < 0)
- {
- if (vio_should_retry(net->vio) &&
- retry_count++ < RETRY_COUNT)
- continue;
- DBUG_PRINT("error",
- ("fcntl returned error %d, aborting thread",
- vio_errno(net->vio)));
+ my_bool old_mode;
+ while (vio_blocking(net->vio, TRUE, &old_mode) < 0)
+ {
+ if (vio_should_retry(net->vio) &&
+ retry_count++ < net->retry_count)
+ continue;
+ DBUG_PRINT("error",
+ ("fcntl returned error %d, aborting thread",
+ vio_errno(net->vio)));
#ifdef EXTRA_DEBUG
- fprintf(stderr,
- "%s: read: fcntl returned error %d, aborting thread\n",
- my_progname,vio_errno(net->vio));
+ fprintf(stderr,
+ "%s: read: fcntl returned error %d, aborting thread\n",
+ my_progname,vio_errno(net->vio));
#endif /* EXTRA_DEBUG */
- len= packet_error;
- net->error=2; /* Close socket */
+ len= packet_error;
+ net->error=2; /* Close socket */
#ifdef MYSQL_SERVER
- net->last_errno=ER_NET_FCNTL_ERROR;
+ net->last_errno=ER_NET_FCNTL_ERROR;
#endif
- goto end;
- }
- }
+ goto end;
+ }
retry_count=0;
continue;
}
@@ -577,7 +575,7 @@ my_real_read(NET *net, ulong *complen)
if (thr_alarm_in_use(&alarmed) && !thr_got_alarm(&alarmed) &&
interrupted)
{ /* Probably in MIT threads */
- if (retry_count++ < RETRY_COUNT)
+ if (retry_count++ < net->retry_count)
continue;
#ifdef EXTRA_DEBUG
fprintf(stderr, "%s: read looped with error %d, aborting thread\n",
@@ -591,7 +589,9 @@ my_real_read(NET *net, ulong *complen)
continue;
}
#endif
- DBUG_PRINT("error",("Couldn't read packet: remain: %lu errno: %d length: %ld alarmed: %d", remain,vio_errno(net->vio),length,alarmed));
+ DBUG_PRINT("error",("Couldn't read packet: remain: %lu errno: %d length: %ld alarmed: %d",
+ remain,vio_errno(net->vio), length,
+ thr_got_alarm(&alarmed)));
len= packet_error;
net->error=2; /* Close socket */
#ifdef MYSQL_SERVER
@@ -661,8 +661,9 @@ my_real_read(NET *net, ulong *complen)
end:
if (thr_alarm_in_use(&alarmed))
{
+ my_bool old_mode;
thr_end_alarm(&alarmed);
- vio_blocking(net->vio, net_blocking);
+ vio_blocking(net->vio, net_blocking, &old_mode);
}
net->reading_or_writing=0;
return(len);
@@ -815,7 +816,7 @@ my_net_read(NET *net)
return len;
}
-int net_request_file(NET* net, const char* fname)
+bool net_request_file(NET* net, const char* fname)
{
char tmp [FN_REFLEN+1],*end;
DBUG_ENTER("net_request_file");
diff --git a/sql/nt_servc.cc b/sql/nt_servc.cc
index be2ceb9cb7a..129df9864e2 100644
--- a/sql/nt_servc.cc
+++ b/sql/nt_servc.cc
@@ -501,11 +501,9 @@ BOOL NTService::IsService(LPCSTR ServiceName)
-------------------------------------------------------------------------- */
BOOL NTService::got_service_option(char **argv, char *service_option)
{
- char *option = argv[1];
-
- while (*option)
- if (!strcmp(option++, service_option))
- return TRUE;
-
+ 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 3764ff2d55c..b0636869d68 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -67,7 +67,9 @@ public:
SEL_ARG(Field *field, uint8 part, char *min_value, char *max_value,
uint8 min_flag, uint8 max_flag, uint8 maybe_flag);
SEL_ARG(enum Type type_arg)
- :elements(1),use_count(1),left(0),next_key_part(0),type(type_arg) {}
+ :elements(1),use_count(1),left(0),next_key_part(0),color(BLACK),
+ type(type_arg)
+ {}
inline bool is_same(SEL_ARG *arg)
{
if (type != arg->type)
@@ -686,27 +688,27 @@ int SQL_SELECT::test_quick_select(key_map keys_to_use, table_map prev_tables,
{
ha_rows found_records;
double found_read_time;
-
if (*key)
{
+ uint keynr= param.real_keynr[idx];
if ((*key)->type == SEL_ARG::MAYBE_KEY ||
(*key)->maybe_flag)
- needed_reg|= (key_map) 1 << param.real_keynr[idx];
+ needed_reg|= (key_map) 1 << keynr;
- found_records=check_quick_select(&param,idx, *key);
+ found_records=check_quick_select(&param, idx, *key);
if (found_records != HA_POS_ERROR && found_records > 2 &&
- head->used_keys & ((table_map) 1 << param.real_keynr[idx]) &&
- (head->file->table_flags() & HA_HAVE_KEY_READ_ONLY))
+ head->used_keys & ((table_map) 1 << keynr) &&
+ (head->file->index_flags(keynr) & HA_KEY_READ_ONLY))
{
/*
- ** We can resolve this by only reading through this key
- ** Assume that we will read trough the whole key range
- ** and that all key blocks are half full (normally things are
- ** much better)
+ We can resolve this by only reading through this key.
+ Assume that we will read trough the whole key range
+ and that all key blocks are half full (normally things are
+ much better).
*/
- uint keys_per_block= head->file->block_size/2/
- (head->key_info[param.real_keynr[idx]].key_length+
- head->file->ref_length) + 1;
+ uint keys_per_block= (head->file->block_size/2/
+ (head->key_info[keynr].key_length+
+ head->file->ref_length) + 1);
found_read_time=((double) (found_records+keys_per_block-1)/
(double) keys_per_block);
}
@@ -889,7 +891,7 @@ get_mm_parts(PARAM *param,Field *field, Item_func::Functype type,Item *value,
if (value &&
value->used_tables() & ~(param->prev_tables | param->read_tables))
DBUG_RETURN(0);
- for ( ; key_part != end ; key_part++)
+ for (; key_part != end ; key_part++)
{
if (field->eq(key_part->field))
{
@@ -1030,6 +1032,7 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part,
if (value->save_in_field(field) == 1)
{
+ // TODO; Check if we can we remove the following block.
if (type == Item_func::EQUAL_FUNC)
{
/* convert column_name <=> NULL -> column_name IS NULL */
@@ -1332,7 +1335,8 @@ and_all_keys(SEL_ARG *key1,SEL_ARG *key2,uint clone_flag)
}
if (key1->type == SEL_ARG::MAYBE_KEY)
{
- key1->left= &null_element; key1->next=0;
+ key1->right= key1->left= &null_element;
+ key1->next= key1->prev= 0;
}
for (next=key1->first(); next ; next=next->next)
{
diff --git a/sql/opt_range.h b/sql/opt_range.h
index e9694b4820f..e96c3792f24 100644
--- a/sql/opt_range.h
+++ b/sql/opt_range.h
@@ -41,10 +41,14 @@ typedef struct st_key_part {
Field::imagetype image_type;
} KEY_PART;
+
class QUICK_RANGE :public Sql_alloc {
public:
char *min_key,*max_key;
uint16 min_length,max_length,flag;
+#ifdef HAVE_purify
+ uint16 dummy; /* Avoid warnings on 'flag' */
+#endif
QUICK_RANGE(); /* Full range */
QUICK_RANGE(const char *min_key_arg,uint min_length_arg,
const char *max_key_arg,uint max_length_arg,
@@ -54,7 +58,11 @@ class QUICK_RANGE :public Sql_alloc {
min_length((uint16) min_length_arg),
max_length((uint16) max_length_arg),
flag((uint16) flag_arg)
- {}
+ {
+#ifdef HAVE_purify
+ dummy=0;
+#endif
+ }
};
diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc
index f399390da4b..38365dbb546 100644
--- a/sql/opt_sum.cc
+++ b/sql/opt_sum.cc
@@ -152,9 +152,9 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
error=table->file->index_last(table->record[0]) !=0;
else
{
- (void) table->file->index_read(table->record[0], key_buff,
- ref.key_length,
- HA_READ_AFTER_KEY);
+ (void)table->file->index_read(table->record[0], key_buff,
+ ref.key_length,
+ HA_READ_AFTER_KEY);
error=table->file->index_prev(table->record[0]) ||
key_cmp(table,key_buff,ref.key,ref.key_length);
}
diff --git a/sql/procedure.h b/sql/procedure.h
index db0e0b7f9e2..349908a8d84 100644
--- a/sql/procedure.h
+++ b/sql/procedure.h
@@ -43,6 +43,7 @@ public:
{
init_make_field(tmp_field,field_type());
}
+ unsigned int size_of() { return sizeof(*this);}
};
class Item_proc_real :public Item_proc
@@ -62,6 +63,7 @@ public:
double val() { return value; }
longlong val_int() { return (longlong) value; }
String *val_str(String *s) { s->set(value,decimals); return s; }
+ unsigned int size_of() { return sizeof(*this);}
};
class Item_proc_int :public Item_proc
@@ -79,6 +81,7 @@ public:
double val() { return (double) value; }
longlong val_int() { return value; }
String *val_str(String *s) { s->set(value); return s; }
+ unsigned int size_of() { return sizeof(*this);}
};
@@ -98,6 +101,7 @@ public:
{
return null_value ? (String*) 0 : (String*) &str_value;
}
+ unsigned int size_of() { return sizeof(*this);}
};
/* The procedure class definitions */
diff --git a/sql/records.cc b/sql/records.cc
index 29ace3cd652..7c3bd1110bb 100644
--- a/sql/records.cc
+++ b/sql/records.cc
@@ -61,7 +61,7 @@ void init_read_record(READ_RECORD *info,THD *thd, TABLE *table,
table->file->rnd_init(0);
if (! (specialflag & SPECIAL_SAFE_MODE) &&
- record_rnd_cache_size &&
+ thd->variables.read_rnd_buff_size &&
!table->file->fast_key_read() &&
(table->db_stat & HA_READ_ONLY ||
table->reginfo.lock_type <= TL_READ_NO_INSERT) &&
@@ -103,7 +103,8 @@ void init_read_record(READ_RECORD *info,THD *thd, TABLE *table,
!(table->db_options_in_use & HA_OPTION_PACK_RECORD) ||
(use_record_cache < 0 &&
!(table->file->table_flags() & HA_NOT_DELETE_WITH_CACHE)))
- VOID(table->file->extra(HA_EXTRA_CACHE)); // Cache reads
+ VOID(table->file->extra_opt(HA_EXTRA_CACHE,
+ thd->variables.read_buff_size));
}
DBUG_VOID_RETURN;
} /* init_read_record */
@@ -229,6 +230,8 @@ tryNext:
static int init_rr_cache(READ_RECORD *info)
{
uint rec_cache_size;
+ THD *thd= current_thd;
+
DBUG_ENTER("init_rr_cache");
info->struct_length=3+MAX_REFLENGTH;
@@ -237,7 +240,7 @@ static int init_rr_cache(READ_RECORD *info)
info->reclength=ALIGN_SIZE(info->struct_length);
info->error_offset=info->table->reclength;
- info->cache_records=record_rnd_cache_size/
+ info->cache_records= thd->variables.read_rnd_buff_size /
(info->reclength+info->struct_length);
rec_cache_size=info->cache_records*info->reclength;
info->rec_cache_size=info->cache_records*info->ref_length;
diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc
index 112642d0a5f..04f1ffce00e 100644
--- a/sql/repl_failsafe.cc
+++ b/sql/repl_failsafe.cc
@@ -24,7 +24,6 @@
#include "mini_client.h"
#include "log_event.h"
#include <mysql.h>
-#include <thr_alarm.h>
#define SLAVE_LIST_CHUNK 128
#define SLAVE_ERRMSG_SIZE (FN_REFLEN+64)
@@ -40,24 +39,28 @@ const char *rpl_role_type[] = {"MASTER","SLAVE",NullS};
TYPELIB rpl_role_typelib = {array_elements(rpl_role_type)-1,"",
rpl_role_type};
-const char* rpl_status_type[] = {"AUTH_MASTER","ACTIVE_SLAVE","IDLE_SLAVE",
- "LOST_SOLDIER","TROOP_SOLDIER",
- "RECOVERY_CAPTAIN","NULL",NullS};
+const char* rpl_status_type[]=
+{
+ "AUTH_MASTER","ACTIVE_SLAVE","IDLE_SLAVE", "LOST_SOLDIER","TROOP_SOLDIER",
+ "RECOVERY_CAPTAIN","NULL",NullS
+};
TYPELIB rpl_status_typelib= {array_elements(rpl_status_type)-1,"",
rpl_status_type};
+
static Slave_log_event* find_slave_event(IO_CACHE* log,
const char* log_file_name,
char* errmsg);
+
static int init_failsafe_rpl_thread(THD* thd)
{
DBUG_ENTER("init_failsafe_rpl_thread");
thd->system_thread = thd->bootstrap = 1;
thd->client_capabilities = 0;
my_net_init(&thd->net, 0);
- thd->net.timeout = slave_net_timeout;
- thd->max_packet_length=thd->net.max_packet;
+ thd->net.read_timeout = slave_net_timeout;
+ thd->max_client_packet_length=thd->net.max_packet;
thd->master_access= ~0;
thd->priv_user = 0;
thd->system_thread = 1;
@@ -65,10 +68,7 @@ static int init_failsafe_rpl_thread(THD* thd)
thd->thread_id = thread_id++;
pthread_mutex_unlock(&LOCK_thread_count);
- if (init_thr_lock() ||
- my_pthread_setspecific_ptr(THR_THD, thd) ||
- my_pthread_setspecific_ptr(THR_MALLOC, &thd->mem_root) ||
- my_pthread_setspecific_ptr(THR_NET, &thd->net))
+ if (init_thr_lock() || thd->store_globals())
{
close_connection(&thd->net,ER_OUT_OF_RESOURCES); // is this needed?
end_thread(thd,0);
@@ -84,8 +84,8 @@ static int init_failsafe_rpl_thread(THD* thd)
#endif
thd->mem_root.free=thd->mem_root.used=0;
- if (thd->max_join_size == (ulong) ~0L)
- thd->options |= OPTION_BIG_SELECTS;
+ if ((ulong) thd->variables.max_join_size == (ulong) HA_POS_ERROR)
+ thd->options|= OPTION_BIG_SELECTS;
thd->proc_info="Thread initialized";
thd->version=refresh_version;
@@ -93,6 +93,7 @@ static int init_failsafe_rpl_thread(THD* thd)
DBUG_RETURN(0);
}
+
void change_rpl_status(RPL_STATUS from_status, RPL_STATUS to_status)
{
pthread_mutex_lock(&LOCK_rpl_status);
@@ -102,6 +103,7 @@ void change_rpl_status(RPL_STATUS from_status, RPL_STATUS to_status)
pthread_mutex_unlock(&LOCK_rpl_status);
}
+
#define get_object(p, obj) \
{\
uint len = (uint)*p++; \
@@ -111,63 +113,81 @@ void change_rpl_status(RPL_STATUS from_status, RPL_STATUS to_status)
p+= len; \
}\
+
static inline int cmp_master_pos(Slave_log_event* sev, LEX_MASTER_INFO* mi)
{
return cmp_master_pos(sev->master_log, sev->master_pos, mi->log_file_name,
mi->pos);
}
+
void unregister_slave(THD* thd, bool only_mine, bool need_mutex)
{
- if (need_mutex)
- pthread_mutex_lock(&LOCK_slave_list);
if (thd->server_id)
{
+ if (need_mutex)
+ pthread_mutex_lock(&LOCK_slave_list);
+
SLAVE_INFO* old_si;
if ((old_si = (SLAVE_INFO*)hash_search(&slave_list,
(byte*)&thd->server_id, 4)) &&
(!only_mine || old_si->thd == thd))
hash_delete(&slave_list, (byte*)old_si);
+
+ if (need_mutex)
+ pthread_mutex_unlock(&LOCK_slave_list);
}
- if (need_mutex)
- pthread_mutex_unlock(&LOCK_slave_list);
}
+
+/*
+ Register slave in 'slave_list' hash table
+
+ RETURN VALUES
+ 0 ok
+ 1 Error. Error message sent to client
+*/
+
int register_slave(THD* thd, uchar* packet, uint packet_length)
{
+ int res;
SLAVE_INFO *si;
- int res = 1;
- uchar* p = packet, *p_end = packet + packet_length;
+ uchar *p= packet, *p_end= packet + packet_length;
- if (check_access(thd, FILE_ACL, any_db))
+ if (check_access(thd, REPL_SLAVE_ACL, any_db))
return 1;
if (!(si = (SLAVE_INFO*)my_malloc(sizeof(SLAVE_INFO), MYF(MY_WME))))
- goto err;
+ goto err2;
- thd->server_id = si->server_id = uint4korr(p);
- p += 4;
+ thd->server_id= si->server_id= uint4korr(p);
+ p+= 4;
get_object(p,si->host);
get_object(p,si->user);
get_object(p,si->password);
- si->port = uint2korr(p);
+ if (p+10 > p_end)
+ goto err;
+ si->port= uint2korr(p);
p += 2;
- si->rpl_recovery_rank = uint4korr(p);
+ si->rpl_recovery_rank= uint4korr(p);
p += 4;
- if (!(si->master_id = uint4korr(p)))
- si->master_id = server_id;
- si->thd = thd;
- pthread_mutex_lock(&LOCK_slave_list);
+ if (!(si->master_id= uint4korr(p)))
+ si->master_id= server_id;
+ si->thd= thd;
+ pthread_mutex_lock(&LOCK_slave_list);
unregister_slave(thd,0,0);
- res = hash_insert(&slave_list, (byte*) si);
+ res= hash_insert(&slave_list, (byte*) si);
pthread_mutex_unlock(&LOCK_slave_list);
return res;
err:
- if (si)
- my_free((gptr) si, MYF(MY_WME));
- return res;
+ my_free((gptr) si, MYF(MY_WME));
+ my_message(ER_UNKNOWN_ERROR, "Wrong parameters to function register_slave",
+ MYF(0));
+err2:
+ send_error(&thd->net);
+ return 1;
}
static uint32* slave_list_key(SLAVE_INFO* si, uint* len,
@@ -199,16 +219,15 @@ void end_slave_list()
}
}
-static int find_target_pos(LEX_MASTER_INFO* mi, IO_CACHE* log, char* errmsg)
+static int find_target_pos(LEX_MASTER_INFO *mi, IO_CACHE *log, char *errmsg)
{
- uint32 log_pos = (uint32) mi->pos;
+ my_off_t log_pos = (my_off_t) mi->pos;
uint32 target_server_id = mi->server_id;
for (;;)
{
Log_event* ev;
- if (!(ev = Log_event::read_log_event(log, (pthread_mutex_t*)0,
- 0)))
+ if (!(ev = Log_event::read_log_event(log, (pthread_mutex_t*) 0, 0)))
{
if (log->error > 0)
strmov(errmsg, "Binary log truncated in the middle of event");
@@ -225,16 +244,16 @@ static int find_target_pos(LEX_MASTER_INFO* mi, IO_CACHE* log, char* errmsg)
mi->pos = my_b_tell(log);
return 0;
}
-
delete ev;
}
+ /* Impossible */
}
int translate_master(THD* thd, LEX_MASTER_INFO* mi, char* errmsg)
{
LOG_INFO linfo;
- char search_file_name[FN_REFLEN],last_log_name[FN_REFLEN];
+ char last_log_name[FN_REFLEN];
IO_CACHE log;
File file = -1, last_file = -1;
pthread_mutex_t *log_lock;
@@ -257,12 +276,7 @@ int translate_master(THD* thd, LEX_MASTER_INFO* mi, char* errmsg)
return 1;
}
- linfo.index_file_offset = 0;
-
-
- search_file_name[0] = 0;
-
- if (mysql_bin_log.find_first_log(&linfo, search_file_name))
+ if (mysql_bin_log.find_log_pos(&linfo, NullS, 1))
{
strmov(errmsg,"Could not find first log");
return 1;
@@ -316,7 +330,7 @@ int translate_master(THD* thd, LEX_MASTER_INFO* mi, char* errmsg)
strmov(last_log_name, linfo.log_file_name);
last_pos = my_b_tell(&log);
- switch (mysql_bin_log.find_next_log(&linfo)) {
+ switch (mysql_bin_log.find_next_log(&linfo, 1)) {
case LOG_INFO_EOF:
if (last_file >= 0)
(void)my_close(last_file, MYF(MY_WME));
@@ -357,7 +371,11 @@ err:
return error;
}
-// caller must delete result when done
+
+/*
+ Caller must delete result when done
+*/
+
static Slave_log_event* find_slave_event(IO_CACHE* log,
const char* log_file_name,
char* errmsg)
@@ -431,6 +449,7 @@ int show_new_master(THD* thd)
}
}
+
int update_slave_list(MYSQL* mysql)
{
MYSQL_RES* res=0;
@@ -438,6 +457,7 @@ int update_slave_list(MYSQL* mysql)
const char* error=0;
bool have_auth_info;
int port_ind;
+ DBUG_ENTER("update_slave_list");
if (mc_mysql_query(mysql,"SHOW SLAVE HOSTS",0) ||
!(res = mc_mysql_store_result(mysql)))
@@ -446,8 +466,7 @@ int update_slave_list(MYSQL* mysql)
goto err;
}
- switch (mc_mysql_num_fields(res))
- {
+ switch (mc_mysql_num_fields(res)) {
case 5:
have_auth_info = 0;
port_ind=2;
@@ -463,13 +482,13 @@ int update_slave_list(MYSQL* mysql)
pthread_mutex_lock(&LOCK_slave_list);
- while ((row = mc_mysql_fetch_row(res)))
+ while ((row= mc_mysql_fetch_row(res)))
{
uint32 server_id;
SLAVE_INFO* si, *old_si;
server_id = atoi(row[0]);
- if ((old_si = (SLAVE_INFO*)hash_search(&slave_list,
- (byte*)&server_id,4)))
+ if ((old_si= (SLAVE_INFO*)hash_search(&slave_list,
+ (byte*)&server_id,4)))
si = old_si;
else
{
@@ -482,34 +501,36 @@ int update_slave_list(MYSQL* mysql)
si->server_id = server_id;
hash_insert(&slave_list, (byte*)si);
}
- strnmov(si->host, row[1], sizeof(si->host));
+ strmake(si->host, row[1], sizeof(si->host)-1);
si->port = atoi(row[port_ind]);
si->rpl_recovery_rank = atoi(row[port_ind+1]);
si->master_id = atoi(row[port_ind+2]);
if (have_auth_info)
{
- strnmov(si->user, row[2], sizeof(si->user));
- strnmov(si->password, row[3], sizeof(si->password));
+ strmake(si->user, row[2], sizeof(si->user)-1);
+ strmake(si->password, row[3], sizeof(si->password)-1);
}
}
pthread_mutex_unlock(&LOCK_slave_list);
+
err:
if (res)
mc_mysql_free_result(res);
if (error)
{
- sql_print_error("Error updating slave list:",error);
- return 1;
+ sql_print_error("Error updating slave list: %s",error);
+ DBUG_RETURN(1);
}
- return 0;
+ DBUG_RETURN(0);
}
+
int find_recovery_captain(THD* thd, MYSQL* mysql)
{
-
return 0;
}
+
pthread_handler_decl(handle_failsafe_rpl,arg)
{
DBUG_ENTER("handle_failsafe_rpl");
@@ -532,8 +553,7 @@ pthread_handler_decl(handle_failsafe_rpl,arg)
thd->proc_info="Processing request";
while (!break_req_chain)
{
- switch (rpl_status)
- {
+ switch (rpl_status) {
case RPL_LOST_SOLDIER:
if (find_recovery_captain(thd, recovery_captain))
rpl_status=RPL_TROOP_SOLDIER;
@@ -558,6 +578,7 @@ err:
DBUG_RETURN(0);
}
+
int show_slave_hosts(THD* thd)
{
List<Item> field_list;
@@ -606,26 +627,28 @@ int show_slave_hosts(THD* thd)
DBUG_RETURN(0);
}
+
int connect_to_master(THD *thd, MYSQL* mysql, MASTER_INFO* mi)
{
- if (!mi->host || !*mi->host) /* empty host */
- return 1;
+ DBUG_ENTER("connect_to_master");
- if (!mc_mysql_connect(mysql, mi->host, mi->user, mi->password, 0,
- mi->port, 0, 0))
+ if (!mi->host || !*mi->host) /* empty host */
{
- sql_print_error("Connection to master failed: %s",
- mc_mysql_error(mysql));
- return 1;
+ strmov(mysql->net.last_error, "Master is not configured");
+ DBUG_RETURN(1);
}
- return 0;
+ if (!mc_mysql_connect(mysql, mi->host, mi->user, mi->password, 0,
+ mi->port, 0, 0,
+ slave_net_timeout))
+ DBUG_RETURN(1);
+ DBUG_RETURN(0);
}
static inline void cleanup_mysql_results(MYSQL_RES* db_res,
- MYSQL_RES** cur, MYSQL_RES** start)
+ MYSQL_RES** cur, MYSQL_RES** start)
{
- for( ; cur >= start; --cur)
+ for (; cur >= start; --cur)
{
if (*cur)
mc_mysql_free_result(*cur);
@@ -634,44 +657,51 @@ static inline void cleanup_mysql_results(MYSQL_RES* db_res,
}
-static inline int fetch_db_tables(THD* thd, MYSQL* mysql, const char* db,
- MYSQL_RES* table_res, MASTER_INFO* mi)
+static int fetch_db_tables(THD *thd, MYSQL *mysql, const char *db,
+ MYSQL_RES *table_res, MASTER_INFO *mi)
{
MYSQL_ROW row;
- for( row = mc_mysql_fetch_row(table_res); row;
+ for (row = mc_mysql_fetch_row(table_res); row;
row = mc_mysql_fetch_row(table_res))
{
TABLE_LIST table;
- const char* table_name = row[0];
+ const char* table_name= row[0];
int error;
if (table_rules_on)
{
- table.next = 0;
- table.db = (char*)db;
- table.real_name = (char*)table_name;
- table.updating = 1;
+ table.next= 0;
+ table.db= (char*) db;
+ table.real_name= (char*) table_name;
+ table.updating= 1;
if (!tables_ok(thd, &table))
continue;
}
- if ((error = fetch_master_table(thd, db, table_name, mi, mysql)))
+ if ((error= fetch_master_table(thd, db, table_name, mi, mysql)))
return error;
}
return 0;
}
+/*
+ Load all MyISAM tables from master to this slave.
+
+ REQUIREMENTS
+ - No active transaction (flush_relay_log_info would not work in this case)
+*/
int load_master_data(THD* thd)
{
MYSQL mysql;
MYSQL_RES* master_status_res = 0;
- bool slave_was_running = 0;
int error = 0;
const char* errmsg=0;
int restart_thread_mask;
mc_mysql_init(&mysql);
- // we do not want anyone messing with the slave at all for the entire
- // duration of the data load;
+ /*
+ We do not want anyone messing with the slave at all for the entire
+ duration of the data load.
+ */
LOCK_ACTIVE_MI;
lock_slave_threads(active_mi);
init_thread_mask(&restart_thread_mask,active_mi,0 /*not inverse*/);
@@ -687,8 +717,8 @@ int load_master_data(THD* thd)
if (connect_to_master(thd, &mysql, active_mi))
{
- net_printf(&thd->net, error = ER_CONNECT_TO_MASTER,
- mc_mysql_error(&mysql));
+ net_printf(&thd->net, error= ER_CONNECT_TO_MASTER,
+ mc_mysql_error(&mysql));
goto err;
}
@@ -707,8 +737,10 @@ int load_master_data(THD* thd)
if (!(num_dbs = (uint) mc_mysql_num_rows(db_res)))
goto err;
- // in theory, the master could have no databases at all
- // and run with skip-grant
+ /*
+ In theory, the master could have no databases at all
+ and run with skip-grant
+ */
if (!(table_res = (MYSQL_RES**)thd->alloc(num_dbs * sizeof(MYSQL_RES*))))
{
@@ -716,10 +748,12 @@ int load_master_data(THD* thd)
goto err;
}
- // this is a temporary solution until we have online backup
- // capabilities - to be replaced once online backup is working
- // we wait to issue FLUSH TABLES WITH READ LOCK for as long as we
- // can to minimize the lock time
+ /*
+ This is a temporary solution until we have online backup
+ capabilities - to be replaced once online backup is working
+ we wait to issue FLUSH TABLES WITH READ LOCK for as long as we
+ can to minimize the lock time.
+ */
if (mc_mysql_query(&mysql, "FLUSH TABLES WITH READ LOCK", 0) ||
mc_mysql_query(&mysql, "SHOW MASTER STATUS",0) ||
!(master_status_res = mc_mysql_store_result(&mysql)))
@@ -729,13 +763,15 @@ int load_master_data(THD* thd)
goto err;
}
- // go through every table in every database, and if the replication
- // rules allow replicating it, get it
+ /*
+ Go through every table in every database, and if the replication
+ rules allow replicating it, get it
+ */
table_res_end = table_res + num_dbs;
- for(cur_table_res = table_res; cur_table_res < table_res_end;
- cur_table_res++)
+ for (cur_table_res = table_res; cur_table_res < table_res_end;
+ cur_table_res++)
{
// since we know how many rows we have, this can never be NULL
MYSQL_ROW row = mc_mysql_fetch_row(db_res);
@@ -753,7 +789,7 @@ int load_master_data(THD* thd)
*/
if (!db_ok(db, replicate_do_db, replicate_ignore_db) ||
- !strcmp(db,"mysql"))
+ !strcmp(db,"mysql"))
{
*cur_table_res = 0;
continue;
@@ -769,7 +805,7 @@ int load_master_data(THD* thd)
if (mc_mysql_select_db(&mysql, db) ||
mc_mysql_query(&mysql, "show tables", 0) ||
- !(*cur_table_res = mc_mysql_store_result(&mysql)))
+ !(*cur_table_res = mc_mysql_store_result(&mysql)))
{
net_printf(&thd->net, error = ER_QUERY_ON_MASTER,
mc_mysql_error(&mysql));
@@ -796,15 +832,16 @@ int load_master_data(THD* thd)
We need this check because the master may not be running with
log-bin, but it will still allow us to do all the steps
of LOAD DATA FROM MASTER - no reason to forbid it, really,
- although it does not make much sense for the user to do it
+ although it does not make much sense for the user to do it
*/
if (row[0] && row[1])
{
strmake(active_mi->master_log_name, row[0],
sizeof(active_mi->master_log_name));
active_mi->master_log_pos = strtoull(row[1], (char**) 0, 10);
- if (active_mi->master_log_pos < 4)
- active_mi->master_log_pos = 4; // don't hit the magic number
+ // don't hit the magic number
+ if (active_mi->master_log_pos < BIN_LOG_HEADER_SIZE)
+ active_mi->master_log_pos = BIN_LOG_HEADER_SIZE;
active_mi->rli.pending = 0;
flush_master_info(active_mi);
}
@@ -819,7 +856,8 @@ int load_master_data(THD* thd)
}
}
thd->proc_info="purging old relay logs";
- if (purge_relay_logs(&active_mi->rli,0 /* not only reset, but also reinit*/,
+ if (purge_relay_logs(&active_mi->rli,thd,
+ 0 /* not only reset, but also reinit */,
&errmsg))
{
send_error(&thd->net, 0, "Failed purging old relay logs");
@@ -829,18 +867,18 @@ int load_master_data(THD* thd)
}
pthread_mutex_lock(&active_mi->rli.data_lock);
active_mi->rli.master_log_pos = active_mi->master_log_pos;
- strnmov(active_mi->rli.master_log_name,active_mi->master_log_name,
- sizeof(active_mi->rli.master_log_name));
+ strmake(active_mi->rli.master_log_name,active_mi->master_log_name,
+ sizeof(active_mi->rli.master_log_name)-1);
flush_relay_log_info(&active_mi->rli);
pthread_cond_broadcast(&active_mi->rli.data_cond);
pthread_mutex_unlock(&active_mi->rli.data_lock);
thd->proc_info = "starting slave";
if (restart_thread_mask)
{
- error=start_slave_threads(0 /* mutex not needed*/,
- 1 /* wait for start*/,
- active_mi,master_info_file,relay_log_info_file,
- restart_thread_mask);
+ error=start_slave_threads(0 /* mutex not needed */,
+ 1 /* wait for start */,
+ active_mi,master_info_file,relay_log_info_file,
+ restart_thread_mask);
}
err:
diff --git a/sql/repl_failsafe.h b/sql/repl_failsafe.h
index 77bc03ce8c0..ef1dc1f8778 100644
--- a/sql/repl_failsafe.h
+++ b/sql/repl_failsafe.h
@@ -14,7 +14,6 @@ extern RPL_STATUS rpl_status;
extern pthread_mutex_t LOCK_rpl_status;
extern pthread_cond_t COND_rpl_status;
extern TYPELIB rpl_role_typelib, rpl_status_typelib;
-extern uint rpl_recovery_rank;
extern const char* rpl_role_type[], *rpl_status_type[];
pthread_handler_decl(handle_failsafe_rpl,arg);
diff --git a/sql/set_var.cc b/sql/set_var.cc
new file mode 100644
index 00000000000..3c71d1d32e3
--- /dev/null
+++ b/sql/set_var.cc
@@ -0,0 +1,1357 @@
+/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/*
+ Handling of MySQL SQL variables
+
+ To add a new variable, one has to do the following:
+
+ - If the variable is thread specific, add it to 'system_variables' struct.
+ If not, add it to mysqld.cc and an declaration in 'mysql_priv.h'
+ - Use one of the 'sys_var... classes from set_var.h or write a specific
+ one for the variable type.
+ - Define it in the 'variable definition list' in this file.
+ - If the variable should be changeable, it should be added to the
+ 'list of all variables' list in this file.
+ - If the variable should be changed from the command line, add a definition
+ of it in the my_option structure list in mysqld.dcc
+ - If the variable should show up in 'show variables' add it to the
+ init_vars[] struct in this file
+
+ TODO:
+ - Add full support for the variable character_set (for 4.1)
+
+ - When updating myisam_delay_key_write, we should do a 'flush tables'
+ of all MyISAM tables to ensure that they are reopen with the
+ new attribute.
+*/
+
+#ifdef __GNUC__
+#pragma implementation // gcc: Class implementation
+#endif
+
+#include "mysql_priv.h"
+#include "slave.h"
+#include "sql_acl.h"
+#include <my_getopt.h>
+#include <myisam.h>
+#ifdef HAVE_BERKELEY_DB
+#include "ha_berkeley.h"
+#endif
+#ifdef HAVE_INNOBASE_DB
+#include "ha_innodb.h"
+#endif
+
+static HASH system_variable_hash;
+const char *bool_type_names[]= { "OFF", "ON", NullS };
+TYPELIB bool_typelib=
+{
+ array_elements(bool_type_names)-1, "", bool_type_names
+};
+
+const char *delay_key_write_type_names[]= { "OFF", "ON", "ALL", NullS };
+TYPELIB delay_key_write_typelib=
+{
+ array_elements(delay_key_write_type_names)-1, "", delay_key_write_type_names
+};
+
+static bool sys_check_charset(THD *thd, set_var *var);
+static bool sys_update_charset(THD *thd, set_var *var);
+static void sys_set_default_charset(THD *thd, enum_var_type type);
+static bool set_option_bit(THD *thd, set_var *var);
+static bool set_option_autocommit(THD *thd, set_var *var);
+static bool set_log_update(THD *thd, set_var *var);
+static void fix_low_priority_updates(THD *thd, enum_var_type type);
+static void fix_tx_isolation(THD *thd, enum_var_type type);
+static void fix_net_read_timeout(THD *thd, enum_var_type type);
+static void fix_net_write_timeout(THD *thd, enum_var_type type);
+static void fix_net_retry_count(THD *thd, enum_var_type type);
+static void fix_max_join_size(THD *thd, enum_var_type type);
+static void fix_query_cache_size(THD *thd, enum_var_type type);
+static void fix_key_buffer_size(THD *thd, enum_var_type type);
+
+/*
+ Variable definition list
+
+ These are variables that can be set from the command line, in
+ alphabetic order
+*/
+
+sys_var_long_ptr sys_binlog_cache_size("binlog_cache_size",
+ &binlog_cache_size);
+sys_var_thd_ulong sys_bulk_insert_buff_size("bulk_insert_buffer_size",
+ &SV::bulk_insert_buff_size);
+sys_var_str sys_charset("character_set",
+ sys_check_charset,
+ sys_update_charset,
+ sys_set_default_charset);
+sys_var_thd_conv_charset sys_convert_charset("convert_character_set");
+sys_var_bool_ptr sys_concurrent_insert("concurrent_insert",
+ &myisam_concurrent_insert);
+sys_var_long_ptr sys_connect_timeout("connect_timeout",
+ &connect_timeout);
+sys_var_enum sys_delay_key_write("delay_key_write",
+ &delay_key_write_options,
+ &delay_key_write_typelib,
+ fix_delay_key_write);
+sys_var_long_ptr sys_delayed_insert_limit("delayed_insert_limit",
+ &delayed_insert_limit);
+sys_var_long_ptr sys_delayed_insert_timeout("delayed_insert_timeout",
+ &delayed_insert_timeout);
+sys_var_long_ptr sys_delayed_queue_size("delayed_queue_size",
+ &delayed_queue_size);
+sys_var_bool_ptr sys_flush("flush", &myisam_flush);
+sys_var_long_ptr sys_flush_time("flush_time", &flush_time);
+sys_var_thd_ulong sys_interactive_timeout("interactive_timeout",
+ &SV::net_interactive_timeout);
+sys_var_thd_ulong sys_join_buffer_size("join_buffer_size",
+ &SV::join_buff_size);
+sys_var_long_ptr sys_key_buffer_size("key_buffer_size",
+ &keybuff_size,
+ fix_key_buffer_size);
+sys_var_bool_ptr sys_local_infile("local_infile",
+ &opt_local_infile);
+sys_var_thd_bool sys_log_warnings("log_warnings", &SV::log_warnings);
+sys_var_thd_ulong sys_long_query_time("long_query_time",
+ &SV::long_query_time);
+sys_var_thd_bool sys_low_priority_updates("low_priority_updates",
+ &SV::low_priority_updates,
+ fix_low_priority_updates);
+#ifndef TO_BE_DELETED /* Alias for the low_priority_updates */
+sys_var_thd_bool sys_sql_low_priority_updates("sql_low_priority_updates",
+ &SV::low_priority_updates,
+ fix_low_priority_updates);
+#endif
+sys_var_thd_ulong sys_max_allowed_packet("max_allowed_packet",
+ &SV::max_allowed_packet);
+sys_var_long_ptr sys_max_binlog_cache_size("max_binlog_cache_size",
+ &max_binlog_cache_size);
+sys_var_long_ptr sys_max_binlog_size("max_binlog_size",
+ &max_binlog_size);
+sys_var_long_ptr sys_max_connections("max_connections",
+ &max_connections);
+sys_var_long_ptr sys_max_connect_errors("max_connect_errors",
+ &max_connect_errors);
+sys_var_long_ptr sys_max_delayed_threads("max_delayed_threads",
+ &max_insert_delayed_threads);
+sys_var_thd_ulong sys_max_heap_table_size("max_heap_table_size",
+ &SV::max_heap_table_size);
+sys_var_thd_ulong sys_max_join_size("max_join_size",
+ &SV::max_join_size,
+ fix_max_join_size);
+#ifndef TO_BE_DELETED /* Alias for max_join_size */
+sys_var_thd_ulong sys_sql_max_join_size("sql_max_join_size",
+ &SV::max_join_size,
+ fix_max_join_size);
+#endif
+sys_var_thd_ulong sys_max_sort_length("max_sort_length",
+ &SV::max_sort_length);
+sys_var_long_ptr sys_max_user_connections("max_user_connections",
+ &max_user_connections);
+sys_var_thd_ulong sys_max_tmp_tables("max_tmp_tables",
+ &SV::max_tmp_tables);
+sys_var_long_ptr sys_max_write_lock_count("max_write_lock_count",
+ &max_write_lock_count);
+sys_var_thd_ulonglong sys_myisam_max_extra_sort_file_size("myisam_max_extra_sort_file_size", &SV::myisam_max_extra_sort_file_size);
+sys_var_thd_ulonglong sys_myisam_max_sort_file_size("myisam_max_sort_file_size", &SV::myisam_max_sort_file_size);
+sys_var_thd_ulong sys_myisam_sort_buffer_size("myisam_sort_buffer_size", &SV::myisam_sort_buff_size);
+sys_var_thd_ulong sys_net_buffer_length("net_buffer_length",
+ &SV::net_buffer_length);
+sys_var_thd_ulong sys_net_read_timeout("net_read_timeout",
+ &SV::net_read_timeout,
+ fix_net_read_timeout);
+sys_var_thd_ulong sys_net_write_timeout("net_write_timeout",
+ &SV::net_write_timeout,
+ fix_net_write_timeout);
+sys_var_thd_ulong sys_net_retry_count("net_retry_count",
+ &SV::net_retry_count,
+ fix_net_retry_count);
+sys_var_thd_ulong sys_read_buff_size("read_buffer_size",
+ &SV::read_buff_size);
+sys_var_thd_ulong sys_read_rnd_buff_size("read_rnd_buffer_size",
+ &SV::read_rnd_buff_size);
+sys_var_long_ptr sys_rpl_recovery_rank("rpl_recovery_rank",
+ &rpl_recovery_rank);
+sys_var_long_ptr sys_query_cache_size("query_cache_size",
+ &query_cache_size,
+ fix_query_cache_size);
+#ifdef HAVE_QUERY_CACHE
+sys_var_long_ptr sys_query_cache_limit("query_cache_limit",
+ &query_cache.query_cache_limit);
+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);
+sys_var_long_ptr sys_slave_net_timeout("slave_net_timeout",
+ &slave_net_timeout);
+sys_var_long_ptr sys_slow_launch_time("slow_launch_time",
+ &slow_launch_time);
+sys_var_thd_ulong sys_sort_buffer("sort_buffer_size",
+ &SV::sortbuff_size);
+sys_var_thd_enum sys_table_type("table_type", &SV::table_type,
+ &ha_table_typelib);
+sys_var_long_ptr sys_table_cache_size("table_cache",
+ &table_cache_size);
+sys_var_long_ptr sys_thread_cache_size("thread_cache_size",
+ &thread_cache_size);
+sys_var_thd_enum sys_tx_isolation("tx_isolation",
+ &SV::tx_isolation,
+ &tx_isolation_typelib,
+ fix_tx_isolation);
+sys_var_thd_ulong sys_tmp_table_size("tmp_table_size",
+ &SV::tmp_table_size);
+sys_var_thd_ulong sys_net_wait_timeout("wait_timeout",
+ &SV::net_wait_timeout);
+
+
+/*
+ Variables that are bits in THD
+*/
+
+static sys_var_thd_bit sys_autocommit("autocommit",
+ set_option_autocommit,
+ OPTION_NOT_AUTOCOMMIT,
+ 1);
+static sys_var_thd_bit sys_big_tables("big_tables",
+ set_option_bit,
+ OPTION_BIG_TABLES);
+#ifndef TO_BE_DELETED /* Alias for big_tables */
+static sys_var_thd_bit sys_sql_big_tables("sql_big_tables",
+ set_option_bit,
+ OPTION_BIG_TABLES);
+#endif
+static sys_var_thd_bit sys_big_selects("sql_big_selects",
+ set_option_bit,
+ OPTION_BIG_TABLES);
+static sys_var_thd_bit sys_log_off("sql_log_off",
+ set_option_bit,
+ OPTION_LOG_OFF);
+static sys_var_thd_bit sys_log_update("sql_log_update",
+ set_log_update,
+ OPTION_UPDATE_LOG);
+static sys_var_thd_bit sys_log_binlog("sql_log_bin",
+ set_log_update,
+ OPTION_BIN_LOG);
+static sys_var_thd_bit sys_sql_warnings("sql_warnings",
+ set_option_bit,
+ OPTION_WARNINGS);
+static sys_var_thd_bit sys_auto_is_null("sql_auto_is_null",
+ set_option_bit,
+ OPTION_AUTO_IS_NULL);
+static sys_var_thd_bit sys_safe_updates("sql_safe_updates",
+ set_option_bit,
+ OPTION_SAFE_UPDATES);
+static sys_var_thd_bit sys_buffer_results("sql_buffer_result",
+ set_option_bit,
+ OPTION_BUFFER_RESULT);
+static sys_var_thd_bit sys_quote_show_create("sql_quote_show_create",
+ set_option_bit,
+ OPTION_QUOTE_SHOW_CREATE);
+static sys_var_thd_bit sys_foreign_key_checks("foreign_key_checks",
+ set_option_bit,
+ OPTION_NO_FOREIGN_KEY_CHECKS,
+ 1);
+static sys_var_thd_bit sys_unique_checks("unique_checks",
+ set_option_bit,
+ OPTION_RELAXED_UNIQUE_CHECKS,
+ 1);
+
+
+/* Local state variables */
+
+static sys_var_thd_ulong sys_select_limit("sql_select_limit",
+ &SV::select_limit);
+static sys_var_timestamp sys_timestamp("timestamp");
+static sys_var_last_insert_id sys_last_insert_id("last_insert_id");
+static sys_var_last_insert_id sys_identity("identity");
+static sys_var_insert_id sys_insert_id("insert_id");
+/* alias for last_insert_id() to be compatible with Sybase */
+static sys_var_slave_skip_counter sys_slave_skip_counter("sql_slave_skip_counter");
+
+
+/*
+ List of all variables for initialisation and storage in hash
+ This is sorted in alphabetical order to make it easy to add new variables
+
+ If the variable is not in this list, it can't be changed with
+ SET variable_name=
+*/
+
+sys_var *sys_variables[]=
+{
+ &sys_auto_is_null,
+ &sys_autocommit,
+ &sys_big_tables,
+ &sys_big_selects,
+ &sys_binlog_cache_size,
+ &sys_buffer_results,
+ &sys_bulk_insert_buff_size,
+ &sys_concurrent_insert,
+ &sys_connect_timeout,
+ &sys_convert_charset,
+ &sys_delay_key_write,
+ &sys_delayed_insert_limit,
+ &sys_delayed_insert_timeout,
+ &sys_delayed_queue_size,
+ &sys_flush,
+ &sys_flush_time,
+ &sys_foreign_key_checks,
+ &sys_identity,
+ &sys_insert_id,
+ &sys_interactive_timeout,
+ &sys_join_buffer_size,
+ &sys_key_buffer_size,
+ &sys_last_insert_id,
+ &sys_local_infile,
+ &sys_log_binlog,
+ &sys_log_off,
+ &sys_log_update,
+ &sys_log_warnings,
+ &sys_long_query_time,
+ &sys_low_priority_updates,
+ &sys_max_allowed_packet,
+ &sys_max_binlog_cache_size,
+ &sys_max_binlog_size,
+ &sys_max_connect_errors,
+ &sys_max_connections,
+ &sys_max_delayed_threads,
+ &sys_max_heap_table_size,
+ &sys_max_join_size,
+ &sys_max_sort_length,
+ &sys_max_tmp_tables,
+ &sys_max_user_connections,
+ &sys_max_write_lock_count,
+ &sys_myisam_max_extra_sort_file_size,
+ &sys_myisam_max_sort_file_size,
+ &sys_myisam_sort_buffer_size,
+ &sys_net_buffer_length,
+ &sys_net_read_timeout,
+ &sys_net_retry_count,
+ &sys_net_wait_timeout,
+ &sys_net_write_timeout,
+ &sys_query_cache_size,
+#ifdef HAVE_QUERY_CACHE
+ &sys_query_cache_limit,
+ &sys_query_cache_type,
+#endif /* HAVE_QUERY_CACHE */
+ &sys_quote_show_create,
+ &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,
+ &sys_slave_compressed_protocol,
+ &sys_slave_net_timeout,
+ &sys_slave_skip_counter,
+ &sys_slow_launch_time,
+ &sys_sort_buffer,
+ &sys_sql_big_tables,
+ &sys_sql_low_priority_updates,
+ &sys_sql_max_join_size,
+ &sys_sql_warnings,
+ &sys_table_cache_size,
+ &sys_table_type,
+ &sys_thread_cache_size,
+ &sys_timestamp,
+ &sys_tmp_table_size,
+ &sys_tx_isolation,
+ &sys_unique_checks
+};
+
+
+/*
+ Variables shown by SHOW variables in alphabetical order
+*/
+
+struct show_var_st init_vars[]= {
+ {"back_log", (char*) &back_log, SHOW_LONG},
+ {"basedir", mysql_home, SHOW_CHAR},
+#ifdef HAVE_BERKELEY_DB
+ {"bdb_cache_size", (char*) &berkeley_cache_size, SHOW_LONG},
+ {"bdb_log_buffer_size", (char*) &berkeley_log_buffer_size, SHOW_LONG},
+ {"bdb_home", (char*) &berkeley_home, SHOW_CHAR_PTR},
+ {"bdb_max_lock", (char*) &berkeley_max_lock, SHOW_LONG},
+ {"bdb_logdir", (char*) &berkeley_logdir, SHOW_CHAR_PTR},
+ {"bdb_shared_data", (char*) &berkeley_shared_data, SHOW_BOOL},
+ {"bdb_tmpdir", (char*) &berkeley_tmpdir, SHOW_CHAR_PTR},
+ {"bdb_version", (char*) DB_VERSION_STRING, SHOW_CHAR},
+#endif
+ {sys_binlog_cache_size.name,(char*) &sys_binlog_cache_size, SHOW_SYS},
+ {sys_bulk_insert_buff_size.name,(char*) &sys_bulk_insert_buff_size,SHOW_SYS},
+ {sys_charset.name, (char*) &sys_charset, SHOW_SYS},
+ {"character_sets", (char*) &charsets_list, SHOW_CHAR_PTR},
+ {sys_concurrent_insert.name,(char*) &sys_concurrent_insert, SHOW_SYS},
+ {sys_connect_timeout.name, (char*) &sys_connect_timeout, SHOW_SYS},
+ {sys_convert_charset.name, (char*) &sys_convert_charset, SHOW_SYS},
+ {"datadir", mysql_real_data_home, SHOW_CHAR},
+ {sys_delay_key_write.name, (char*) &sys_delay_key_write, SHOW_SYS},
+ {sys_delayed_insert_limit.name, (char*) &sys_delayed_insert_limit,SHOW_SYS},
+ {sys_delayed_insert_timeout.name, (char*) &sys_delayed_insert_timeout, SHOW_SYS},
+ {sys_delayed_queue_size.name,(char*) &sys_delayed_queue_size, SHOW_SYS},
+ {sys_flush.name, (char*) &sys_flush, SHOW_SYS},
+ {sys_flush_time.name, (char*) &sys_flush_time, SHOW_SYS},
+ {"ft_min_word_len", (char*) &ft_min_word_len, SHOW_LONG},
+ {"ft_max_word_len", (char*) &ft_max_word_len, SHOW_LONG},
+ {"ft_max_word_len_for_sort",(char*) &ft_max_word_len_for_sort, SHOW_LONG},
+ {"ft_boolean_syntax", (char*) ft_boolean_syntax, SHOW_CHAR},
+ {"have_bdb", (char*) &have_berkeley_db, SHOW_HAVE},
+ {"have_innodb", (char*) &have_innodb, SHOW_HAVE},
+ {"have_isam", (char*) &have_isam, SHOW_HAVE},
+ {"have_raid", (char*) &have_raid, SHOW_HAVE},
+ {"have_symlink", (char*) &have_symlink, SHOW_HAVE},
+ {"have_openssl", (char*) &have_openssl, SHOW_HAVE},
+ {"have_query_cache", (char*) &have_query_cache, SHOW_HAVE},
+ {"init_file", (char*) &opt_init_file, SHOW_CHAR_PTR},
+#ifdef HAVE_INNOBASE_DB
+ {"innodb_additional_mem_pool_size", (char*) &innobase_additional_mem_pool_size, SHOW_LONG },
+ {"innodb_buffer_pool_size", (char*) &innobase_buffer_pool_size, SHOW_LONG },
+ {"innodb_data_file_path", (char*) &innobase_data_file_path, SHOW_CHAR_PTR},
+ {"innodb_data_home_dir", (char*) &innobase_data_home_dir, SHOW_CHAR_PTR},
+ {"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_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 },
+ {"innodb_log_arch_dir", (char*) &innobase_log_arch_dir, SHOW_CHAR_PTR},
+ {"innodb_log_archive", (char*) &innobase_log_archive, SHOW_MY_BOOL},
+ {"innodb_log_buffer_size", (char*) &innobase_log_buffer_size, SHOW_LONG },
+ {"innodb_log_file_size", (char*) &innobase_log_file_size, SHOW_LONG},
+ {"innodb_log_files_in_group", (char*) &innobase_log_files_in_group, SHOW_LONG},
+ {"innodb_log_group_home_dir", (char*) &innobase_log_group_home_dir, SHOW_CHAR_PTR},
+ {"innodb_mirrored_log_groups", (char*) &innobase_mirrored_log_groups, SHOW_LONG},
+#endif
+ {sys_interactive_timeout.name,(char*) &sys_interactive_timeout, SHOW_SYS},
+ {sys_join_buffer_size.name, (char*) &sys_join_buffer_size, SHOW_SYS},
+ {sys_key_buffer_size.name, (char*) &sys_key_buffer_size, SHOW_SYS},
+ {"language", language, SHOW_CHAR},
+ {"large_files_support", (char*) &opt_large_files, SHOW_BOOL},
+ {sys_local_infile.name, (char*) &sys_local_infile, SHOW_SYS},
+#ifdef HAVE_MLOCKALL
+ {"locked_in_memory", (char*) &locked_in_memory, SHOW_BOOL},
+#endif
+ {"log", (char*) &opt_log, SHOW_BOOL},
+ {"log_update", (char*) &opt_update_log, SHOW_BOOL},
+ {"log_bin", (char*) &opt_bin_log, SHOW_BOOL},
+ {"log_slave_updates", (char*) &opt_log_slave_updates, SHOW_BOOL},
+ {"log_slow_queries", (char*) &opt_slow_log, SHOW_BOOL},
+ {sys_log_warnings.name, (char*) &sys_log_warnings, SHOW_SYS},
+ {sys_long_query_time.name, (char*) &sys_long_query_time, SHOW_SYS},
+ {sys_low_priority_updates.name, (char*) &sys_low_priority_updates, SHOW_SYS},
+ {"lower_case_table_names", (char*) &lower_case_table_names, SHOW_MY_BOOL},
+ {sys_max_allowed_packet.name,(char*) &sys_max_allowed_packet, SHOW_SYS},
+ {sys_max_binlog_cache_size.name,(char*) &sys_max_binlog_cache_size, SHOW_SYS},
+ {sys_max_binlog_size.name, (char*) &sys_max_binlog_size, SHOW_SYS},
+ {sys_max_connections.name, (char*) &sys_max_connections, SHOW_SYS},
+ {sys_max_connect_errors.name, (char*) &sys_max_connect_errors, SHOW_SYS},
+ {sys_max_delayed_threads.name,(char*) &sys_max_delayed_threads, SHOW_SYS},
+ {sys_max_heap_table_size.name,(char*) &sys_max_heap_table_size, SHOW_SYS},
+ {sys_max_join_size.name, (char*) &sys_max_join_size, SHOW_SYS},
+ {sys_max_sort_length.name, (char*) &sys_max_sort_length, SHOW_SYS},
+ {sys_max_user_connections.name,(char*) &sys_max_user_connections, SHOW_SYS},
+ {sys_max_tmp_tables.name, (char*) &sys_max_tmp_tables, SHOW_SYS},
+ {sys_max_write_lock_count.name, (char*) &sys_max_write_lock_count,SHOW_SYS},
+ {sys_myisam_max_extra_sort_file_size.name,
+ (char*) &sys_myisam_max_extra_sort_file_size,
+ SHOW_SYS},
+ {sys_myisam_max_sort_file_size.name,
+ (char*) &sys_myisam_max_sort_file_size,
+ SHOW_SYS},
+ {"myisam_recover_options", (char*) &myisam_recover_options_str, SHOW_CHAR_PTR},
+ {sys_myisam_sort_buffer_size.name, (char*) &sys_myisam_sort_buffer_size, SHOW_SYS},
+#ifdef __NT__
+ {"named_pipe", (char*) &opt_enable_named_pipe, SHOW_BOOL},
+#endif
+ {sys_net_buffer_length.name,(char*) &sys_net_buffer_length, SHOW_SYS},
+ {sys_net_read_timeout.name, (char*) &sys_net_read_timeout, SHOW_SYS},
+ {sys_net_retry_count.name, (char*) &sys_net_retry_count, SHOW_SYS},
+ {sys_net_write_timeout.name,(char*) &sys_net_write_timeout, SHOW_SYS},
+ {"open_files_limit", (char*) &open_files_limit, SHOW_LONG},
+ {"pid_file", (char*) pidfile_name, SHOW_CHAR},
+ {"port", (char*) &mysql_port, SHOW_INT},
+ {"protocol_version", (char*) &protocol_version, SHOW_INT},
+ {sys_read_buff_size.name, (char*) &sys_read_buff_size, SHOW_SYS},
+ {sys_read_rnd_buff_size.name,(char*) &sys_read_rnd_buff_size, SHOW_SYS},
+ {sys_rpl_recovery_rank.name,(char*) &sys_rpl_recovery_rank, SHOW_SYS},
+#ifdef HAVE_QUERY_CACHE
+ {sys_query_cache_limit.name,(char*) &sys_query_cache_limit, SHOW_SYS},
+ {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},
+ {sys_server_id.name, (char*) &sys_server_id, SHOW_SYS},
+ {sys_slave_net_timeout.name,(char*) &sys_slave_net_timeout, SHOW_SYS},
+ {"skip_external_locking", (char*) &my_disable_locking, SHOW_MY_BOOL},
+ {"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},
+ {"socket", (char*) &mysql_unix_port, SHOW_CHAR_PTR},
+ {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},
+ {sys_table_type.name, (char*) &sys_table_type, SHOW_SYS},
+ {sys_thread_cache_size.name,(char*) &sys_thread_cache_size, SHOW_SYS},
+#ifdef HAVE_THR_SETCONCURRENCY
+ {"thread_concurrency", (char*) &concurrency, SHOW_LONG},
+#endif
+ {"thread_stack", (char*) &thread_stack, SHOW_LONG},
+ {sys_tx_isolation.name, (char*) &sys_tx_isolation, SHOW_SYS},
+#ifdef HAVE_TZNAME
+ {"timezone", time_zone, SHOW_CHAR},
+#endif
+ {sys_tmp_table_size.name, (char*) &sys_tmp_table_size, SHOW_SYS},
+ {"tmpdir", (char*) &mysql_tmpdir, SHOW_CHAR_PTR},
+ {"version", server_version, SHOW_CHAR},
+ {sys_net_wait_timeout.name, (char*) &sys_net_wait_timeout, SHOW_SYS},
+ {NullS, NullS, SHOW_LONG}
+};
+
+/*
+ Functions to check and update variables
+*/
+
+/*
+ The following 3 functions need to be changed in 4.1 when we allow
+ one to change character sets
+*/
+
+static bool sys_check_charset(THD *thd, set_var *var)
+{
+ return 0;
+}
+
+
+static bool sys_update_charset(THD *thd, set_var *var)
+{
+ return 0;
+}
+
+
+static void sys_set_default_charset(THD *thd, enum_var_type type)
+{
+}
+
+
+/*
+ If one sets the LOW_PRIORIY UPDATES flag, we also must change the
+ used lock type
+*/
+
+static void fix_low_priority_updates(THD *thd, enum_var_type type)
+{
+ if (type != OPT_GLOBAL)
+ thd->update_lock_default= (thd->variables.low_priority_updates ?
+ TL_WRITE_LOW_PRIORITY : TL_WRITE);
+}
+
+
+/*
+ Set the OPTION_BIG_SELECTS flag if max_join_size == HA_POS_ERROR
+*/
+
+static void fix_max_join_size(THD *thd, enum_var_type type)
+{
+ if (type != OPT_GLOBAL)
+ {
+ if (thd->variables.max_join_size == (ulong) HA_POS_ERROR)
+ thd->options|= OPTION_BIG_SELECTS;
+ else
+ thd->options&= ~OPTION_BIG_SELECTS;
+ }
+}
+
+
+/*
+ If one doesn't use the SESSION modifier, the isolation level
+ is only active for the next command
+*/
+
+static void fix_tx_isolation(THD *thd, enum_var_type type)
+{
+ if (type == OPT_SESSION)
+ thd->session_tx_isolation= ((enum_tx_isolation)
+ thd->variables.tx_isolation);
+}
+
+
+/*
+ If we are changing the thread variable, we have to copy it to NET too
+*/
+
+static void fix_net_read_timeout(THD *thd, enum_var_type type)
+{
+ if (type != OPT_GLOBAL)
+ thd->net.read_timeout=thd->variables.net_read_timeout;
+}
+
+
+static void fix_net_write_timeout(THD *thd, enum_var_type type)
+{
+ if (type != OPT_GLOBAL)
+ thd->net.write_timeout=thd->variables.net_write_timeout;
+}
+
+static void fix_net_retry_count(THD *thd, enum_var_type type)
+{
+ if (type != OPT_GLOBAL)
+ thd->net.retry_count=thd->variables.net_retry_count;
+}
+
+
+static void fix_query_cache_size(THD *thd, enum_var_type type)
+{
+#ifdef HAVE_QUERY_CACHE
+ query_cache.resize(query_cache_size);
+#endif
+}
+
+
+static void fix_key_buffer_size(THD *thd, enum_var_type type)
+{
+ ha_resize_key_cache();
+}
+
+
+void fix_delay_key_write(THD *thd, enum_var_type type)
+{
+ switch ((enum_delay_key_write) delay_key_write_options) {
+ case DELAY_KEY_WRITE_NONE:
+ myisam_delay_key_write=0;
+ break;
+ case DELAY_KEY_WRITE_ON:
+ myisam_delay_key_write=1;
+ break;
+ case DELAY_KEY_WRITE_ALL:
+ myisam_delay_key_write=1;
+ ha_open_options|= HA_OPEN_DELAY_KEY_WRITE;
+ break;
+ }
+}
+
+
+bool sys_var_long_ptr::update(THD *thd, set_var *var)
+{
+ ulonglong tmp= var->value->val_int();
+ if (option_limits)
+ *value= (ulong) getopt_ull_limit_value(tmp, option_limits);
+ else
+ *value= (ulong) tmp;
+ return 0;
+}
+
+
+void sys_var_long_ptr::set_default(THD *thd, enum_var_type type)
+{
+ *value= (ulong) option_limits->def_value;
+}
+
+
+bool sys_var_bool_ptr::update(THD *thd, set_var *var)
+{
+ *value= (my_bool) var->save_result.ulong_value;
+ return 0;
+}
+
+
+void sys_var_bool_ptr::set_default(THD *thd, enum_var_type type)
+{
+ *value= (my_bool) option_limits->def_value;
+}
+
+
+bool sys_var_enum::update(THD *thd, set_var *var)
+{
+ *value= (uint) var->save_result.ulong_value;
+ return 0;
+}
+
+
+byte *sys_var_enum::value_ptr(THD *thd, enum_var_type type)
+{
+ return (byte*) enum_names->type_names[*value];
+}
+
+
+bool sys_var_thd_ulong::update(THD *thd, set_var *var)
+{
+ ulonglong tmp= var->value->val_int();
+
+ /* Don't use bigger value than given with --maximum-variable-name=.. */
+ if ((ulong) tmp > max_system_variables.*offset)
+ tmp= max_system_variables.*offset;
+
+ if (option_limits)
+ tmp= (ulong) getopt_ull_limit_value(tmp, option_limits);
+ if (var->type == OPT_GLOBAL)
+ {
+ /* Lock is needed to make things safe on 32 bit systems */
+ pthread_mutex_lock(&LOCK_global_system_variables);
+ global_system_variables.*offset= (ulong) tmp;
+ pthread_mutex_unlock(&LOCK_global_system_variables);
+ }
+ else
+ thd->variables.*offset= (ulong) tmp;
+ return 0;
+}
+
+
+void sys_var_thd_ulong::set_default(THD *thd, enum_var_type type)
+{
+ if (type == OPT_GLOBAL)
+ {
+ /* We will not come here if option_limits is not set */
+ global_system_variables.*offset= (ulong) option_limits->def_value;
+ }
+ else
+ thd->variables.*offset= global_system_variables.*offset;
+}
+
+
+byte *sys_var_thd_ulong::value_ptr(THD *thd, enum_var_type type)
+{
+ if (type == OPT_GLOBAL)
+ return (byte*) &(global_system_variables.*offset);
+ return (byte*) &(thd->variables.*offset);
+}
+
+
+bool sys_var_thd_ulonglong::update(THD *thd, set_var *var)
+{
+ if (var->type == OPT_GLOBAL)
+ global_system_variables.*offset= var->value->val_int();
+ else
+ thd->variables.*offset= var->value->val_int();
+ return 0;
+}
+
+
+void sys_var_thd_ulonglong::set_default(THD *thd, enum_var_type type)
+{
+ if (type == OPT_GLOBAL)
+ global_system_variables.*offset= (ulong) option_limits->def_value;
+ else
+ thd->variables.*offset= global_system_variables.*offset;
+}
+
+
+byte *sys_var_thd_ulonglong::value_ptr(THD *thd, enum_var_type type)
+{
+ if (type == OPT_GLOBAL)
+ return (byte*) &(global_system_variables.*offset);
+ return (byte*) &(thd->variables.*offset);
+}
+
+
+bool sys_var_thd_bool::update(THD *thd, set_var *var)
+{
+ if (var->type == OPT_GLOBAL)
+ global_system_variables.*offset= (my_bool) var->save_result.ulong_value;
+ else
+ thd->variables.*offset= (my_bool) var->save_result.ulong_value;
+ return 0;
+}
+
+
+void sys_var_thd_bool::set_default(THD *thd, enum_var_type type)
+{
+ if (type == OPT_GLOBAL)
+ global_system_variables.*offset= (my_bool) option_limits->def_value;
+ else
+ thd->variables.*offset= global_system_variables.*offset;
+}
+
+
+byte *sys_var_thd_bool::value_ptr(THD *thd, enum_var_type type)
+{
+ if (type == OPT_GLOBAL)
+ return (byte*) &(global_system_variables.*offset);
+ return (byte*) &(thd->variables.*offset);
+}
+
+
+bool sys_var::check_enum(THD *thd, set_var *var, TYPELIB *enum_names)
+{
+ char buff[80], *value;
+ String str(buff,sizeof(buff)), *res;
+
+ if (var->value->result_type() == STRING_RESULT)
+ {
+ if (!(res=var->value->val_str(&str)) ||
+ ((long) (var->save_result.ulong_value=
+ (ulong) find_type(res->c_ptr(), enum_names, 3)-1))
+ < 0)
+ {
+ value=res->c_ptr();
+ goto err;
+ }
+ }
+ else
+ {
+ ulonglong tmp=var->value->val_int();
+ if (tmp >= enum_names->count)
+ {
+ llstr(tmp,buff);
+ value=buff; // Wrong value is here
+ goto err;
+ }
+ var->save_result.ulong_value= (ulong) tmp; // Save for update
+ }
+ return 0;
+
+err:
+ my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, value);
+ return 1;
+}
+
+/*
+ Return an Item for a variable. Used with @@[global.]variable_name
+
+ If type is not given, return local value if exists, else global
+
+ We have to use netprintf() instead of my_error() here as this is
+ called on the parsing stage.
+*/
+
+Item *sys_var::item(THD *thd, enum_var_type var_type)
+{
+ if (check_type(var_type))
+ {
+ if (var_type != OPT_DEFAULT)
+ {
+ net_printf(&thd->net,
+ var_type == OPT_GLOBAL ? ER_LOCAL_VARIABLE :
+ ER_GLOBAL_VARIABLE, name);
+ return 0;
+ }
+ /* As there was no local variable, return the global value */
+ var_type= OPT_GLOBAL;
+ }
+ switch (type()) {
+ case SHOW_LONG:
+ return new Item_uint((int32) *(ulong*) value_ptr(thd, var_type));
+ case SHOW_LONGLONG:
+ return new Item_int(*(longlong*) value_ptr(thd, var_type));
+ case SHOW_MY_BOOL:
+ return new Item_int((int32) *(my_bool*) value_ptr(thd, var_type),1);
+ case SHOW_CHAR:
+ {
+ char *str= (char*) value_ptr(thd, var_type);
+ return new Item_string(str,strlen(str));
+ }
+ default:
+ net_printf(&thd->net, ER_VAR_CANT_BE_READ, name);
+ }
+ return 0;
+}
+
+
+bool sys_var_thd_enum::update(THD *thd, set_var *var)
+{
+ if (var->type == OPT_GLOBAL)
+ global_system_variables.*offset= var->save_result.ulong_value;
+ else
+ thd->variables.*offset= var->save_result.ulong_value;
+ return 0;
+}
+
+
+void sys_var_thd_enum::set_default(THD *thd, enum_var_type type)
+{
+ if (type == OPT_GLOBAL)
+ global_system_variables.*offset= (ulong) option_limits->def_value;
+ else
+ thd->variables.*offset= global_system_variables.*offset;
+}
+
+
+byte *sys_var_thd_enum::value_ptr(THD *thd, enum_var_type type)
+{
+ ulong tmp= ((type == OPT_GLOBAL) ?
+ global_system_variables.*offset :
+ thd->variables.*offset);
+ return (byte*) enum_names->type_names[tmp];
+}
+
+
+bool sys_var_thd_bit::update(THD *thd, set_var *var)
+{
+ bool res= (*update_func)(thd, var);
+ thd->lex.select_lex.options=thd->options;
+ return res;
+}
+
+
+byte *sys_var_thd_bit::value_ptr(THD *thd, enum_var_type type)
+{
+ /*
+ If reverse is 0 (default) return 1 if bit is set.
+ If reverse is 1, return 0 if bit is set
+ */
+ thd->sys_var_tmp.my_bool_value= ((thd->options & bit_flag) ?
+ !reverse : reverse);
+ return (byte*) &thd->sys_var_tmp.my_bool_value;
+}
+
+
+bool sys_var_thd_conv_charset::check(THD *thd, set_var *var)
+{
+ CONVERT *tmp;
+ char buff[80];
+ String str(buff,sizeof(buff)), *res;
+
+ if (!var->value) // Default value
+ {
+ var->save_result.convert= (var->type != OPT_GLOBAL ?
+ global_system_variables.convert_set
+ : (CONVERT*) 0);
+ return 0;
+ }
+ if (!(res=var->value->val_str(&str)))
+ res= &empty_string;
+
+ if (!(tmp=get_convert_set(res->c_ptr())))
+ {
+ my_error(ER_UNKNOWN_CHARACTER_SET, MYF(0), res->c_ptr());
+ return 1;
+ }
+ var->save_result.convert=tmp; // Save for update
+ return 0;
+}
+
+
+bool sys_var_thd_conv_charset::update(THD *thd, set_var *var)
+{
+ if (var->type == OPT_GLOBAL)
+ global_system_variables.convert_set= var->save_result.convert;
+ else
+ thd->lex.convert_set= thd->variables.convert_set=
+ var->save_result.convert;
+ return 0;
+}
+
+
+byte *sys_var_thd_conv_charset::value_ptr(THD *thd, enum_var_type type)
+{
+ CONVERT *conv= ((type == OPT_GLOBAL) ?
+ global_system_variables.convert_set :
+ thd->variables.convert_set);
+ return conv ? (byte*) conv->name : (byte*) "";
+}
+
+
+
+bool sys_var_timestamp::update(THD *thd, set_var *var)
+{
+ thd->set_time((time_t) var->value->val_int());
+ return 0;
+}
+
+
+void sys_var_timestamp::set_default(THD *thd, enum_var_type type)
+{
+ thd->user_time=0;
+}
+
+
+byte *sys_var_timestamp::value_ptr(THD *thd, enum_var_type type)
+{
+ thd->sys_var_tmp.long_value= (long) thd->start_time;
+ return (byte*) &thd->sys_var_tmp.long_value;
+}
+
+
+bool sys_var_last_insert_id::update(THD *thd, set_var *var)
+{
+ thd->insert_id(var->value->val_int());
+ return 0;
+}
+
+
+byte *sys_var_last_insert_id::value_ptr(THD *thd, enum_var_type type)
+{
+ thd->sys_var_tmp.long_value= (long) thd->insert_id();
+ return (byte*) &thd->last_insert_id;
+}
+
+
+bool sys_var_insert_id::update(THD *thd, set_var *var)
+{
+ thd->next_insert_id=var->value->val_int();
+ return 0;
+}
+
+
+byte *sys_var_insert_id::value_ptr(THD *thd, enum_var_type type)
+{
+ return (byte*) &thd->current_insert_id;
+}
+
+
+bool sys_var_slave_skip_counter::check(THD *thd, set_var *var)
+{
+ bool result=0;
+ LOCK_ACTIVE_MI;
+ pthread_mutex_lock(&active_mi->rli.run_lock);
+ if (active_mi->rli.slave_running)
+ {
+ my_error(ER_SLAVE_MUST_STOP, MYF(0));
+ result=1;
+ }
+ pthread_mutex_unlock(&active_mi->rli.run_lock);
+ UNLOCK_ACTIVE_MI;
+ return result;
+}
+
+
+bool sys_var_slave_skip_counter::update(THD *thd, set_var *var)
+{
+ LOCK_ACTIVE_MI;
+ pthread_mutex_lock(&active_mi->rli.run_lock);
+ /*
+ The following test should normally never be true as we test this
+ in the check function; To be safe against multiple
+ SQL_SLAVE_SKIP_COUNTER request, we do the check anyway
+ */
+ if (!active_mi->rli.slave_running)
+ {
+ pthread_mutex_lock(&active_mi->rli.data_lock);
+ active_mi->rli.slave_skip_counter= (ulong) var->value->val_int();
+ pthread_mutex_unlock(&active_mi->rli.data_lock);
+ }
+ pthread_mutex_unlock(&active_mi->rli.run_lock);
+ UNLOCK_ACTIVE_MI;
+ return 0;
+}
+
+
+/*
+ Functions to update thd->options bits
+*/
+
+static bool set_option_bit(THD *thd, set_var *var)
+{
+ sys_var_thd_bit *sys_var= ((sys_var_thd_bit*) var->var);
+ if ((var->save_result.ulong_value != 0) == sys_var->reverse)
+ thd->options&= ~sys_var->bit_flag;
+ else
+ thd->options|= sys_var->bit_flag;
+ return 0;
+}
+
+
+static bool set_option_autocommit(THD *thd, set_var *var)
+{
+ /* The test is negative as the flag we use is NOT autocommit */
+
+ ulong org_options=thd->options;
+
+ if (var->save_result.ulong_value != 0)
+ thd->options&= ~((sys_var_thd_bit*) var->var)->bit_flag;
+ else
+ thd->options|= ((sys_var_thd_bit*) var->var)->bit_flag;
+
+ if ((org_options ^ thd->options) & OPTION_NOT_AUTOCOMMIT)
+ {
+ if ((org_options & OPTION_NOT_AUTOCOMMIT))
+ {
+ /* We changed to auto_commit mode */
+ thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE);
+ thd->server_status|= SERVER_STATUS_AUTOCOMMIT;
+ if (ha_commit(thd))
+ return 1;
+ }
+ else
+ {
+ thd->options&= ~(ulong) (OPTION_STATUS_NO_TRANS_UPDATE);
+ thd->server_status&= ~SERVER_STATUS_AUTOCOMMIT;
+ }
+ }
+ return 0;
+}
+
+
+static bool set_log_update(THD *thd, set_var *var)
+{
+ if (opt_sql_bin_update)
+ ((sys_var_thd_bit*) var->var)->bit_flag|= (OPTION_BIN_LOG |
+ OPTION_UPDATE_LOG);
+ set_option_bit(thd, var);
+ return 0;
+}
+
+
+/****************************************************************************
+ Main handling of variables:
+ - Initialisation
+ - Searching during parsing
+ - Update loop
+****************************************************************************/
+
+/*
+ Find variable name in option my_getopt structure used for command line args
+
+ SYNOPSIS
+ find_option()
+ opt option structure array to search in
+ name variable name
+
+ RETURN VALUES
+ 0 Error
+ ptr pointer to option structure
+*/
+
+static struct my_option *find_option(struct my_option *opt, const char *name)
+{
+ uint length=strlen(name);
+ for (; opt->name; opt++)
+ {
+ if (!getopt_compare_strings(opt->name, name, length) &&
+ !opt->name[length])
+ {
+ /*
+ Only accept the option if one can set values through it.
+ If not, there is no default value or limits in the option.
+ */
+ return (opt->value) ? opt : 0;
+ }
+ }
+ return 0;
+}
+
+
+/*
+ Return variable name and length for hashing of variables
+*/
+
+static byte *get_sys_var_length(const sys_var *var, uint *length,
+ my_bool first)
+{
+ *length= var->name_length;
+ return (byte*) var->name;
+}
+
+
+/*
+ Initialises sys variables and put them in system_variable_hash
+*/
+
+
+void set_var_init()
+{
+ extern struct my_option my_long_options[]; // From mysqld
+
+ hash_init(&system_variable_hash,array_elements(sys_variables),0,0,
+ (hash_get_key) get_sys_var_length,0, HASH_CASE_INSENSITIVE);
+ sys_var **var, **end;
+ for (var= sys_variables, end= sys_variables+array_elements(sys_variables) ;
+ var < end;
+ var++)
+ {
+ (*var)->name_length= strlen((*var)->name);
+ (*var)->option_limits= find_option(my_long_options, (*var)->name);
+ hash_insert(&system_variable_hash, (byte*) *var);
+ }
+
+ /*
+ Special cases
+ Needed because MySQL can't find the limits for a variable it it has
+ a different name than the command line option.
+ As these variables are deprecated, this code will disappear soon...
+ */
+ sys_sql_max_join_size.option_limits= sys_max_join_size.option_limits;
+}
+
+
+void set_var_free()
+{
+ hash_free(&system_variable_hash);
+}
+
+
+/*
+ Find a user set-table variable
+
+ SYNOPSIS
+ find_sys_var()
+ str Name of system variable to find
+ length Length of variable. zero means that we should use strlen()
+ on the variable
+
+ NOTE
+ We have to use net_printf() as this is called during the parsing stage
+
+ RETURN VALUES
+ pointer pointer to variable definitions
+ 0 Unknown variable (error message is given)
+*/
+
+sys_var *find_sys_var(const char *str, uint length)
+{
+ sys_var *var= (sys_var*) hash_search(&system_variable_hash, str,
+ length ? length :
+ strlen(str));
+ if (!var)
+ net_printf(&current_thd->net, ER_UNKNOWN_SYSTEM_VARIABLE, (char*) str);
+ return var;
+}
+
+
+/*
+ Execute update of all variables
+
+ SYNOPSIS
+
+ sql_set
+ THD Thread id
+ set_var List of variables to update
+
+ DESCRIPTION
+ First run a check of all variables that all updates will go ok.
+ If yes, then execute all updates, returning an error if any one failed.
+
+ This should ensure that in all normal cases none all or variables are
+ updated
+
+ RETURN VALUE
+ 0 ok
+ 1 Something got wrong (normally no variables was updated)
+*/
+
+bool sql_set_variables(THD *thd, List<set_var_base> *var_list)
+{
+ bool error=0;
+ List_iterator<set_var_base> it(*var_list);
+
+ set_var_base *var;
+ while ((var=it++))
+ {
+ if (var->check(thd))
+ return 1;
+ }
+ it.rewind();
+ while ((var=it++))
+ {
+ if (var->update(thd))
+ error=1;
+ }
+ return error;
+}
+
+
+/*****************************************************************************
+ Functions to handle SET mysql_internal_variable=const_expr
+*****************************************************************************/
+
+bool set_var::check(THD *thd)
+{
+ if (var->check_type(type))
+ {
+ my_error(type == OPT_GLOBAL ? ER_LOCAL_VARIABLE : ER_GLOBAL_VARIABLE,
+ MYF(0),
+ var->name);
+ return 1;
+ }
+ if ((type == OPT_GLOBAL && check_global_access(thd, SUPER_ACL)))
+ return 1;
+
+ /* value is a NULL pointer if we are using SET ... = DEFAULT */
+ if (!value)
+ {
+ if (var->check_default(type))
+ {
+ my_error(ER_NO_DEFAULT, MYF(0), var->name);
+ return 1;
+ }
+ return 0;
+ }
+
+ if (value->fix_fields(thd,0))
+ return 1;
+ if (var->check_update_type(value->result_type()))
+ {
+ my_error(ER_WRONG_TYPE_FOR_VAR, MYF(0), var->name);
+ return 1;
+ }
+ return var->check(thd, this);
+}
+
+
+bool set_var::update(THD *thd)
+{
+ if (!value)
+ var->set_default(thd, type);
+ else if (var->update(thd, this))
+ return 1; // should never happen
+ if (var->after_update)
+ (*var->after_update)(thd, type);
+ return 0;
+}
+
+
+/*****************************************************************************
+ Functions to handle SET @user_variable=const_expr
+*****************************************************************************/
+
+bool set_var_user::check(THD *thd)
+{
+ return user_var_item->fix_fields(thd,0);
+}
+
+
+bool set_var_user::update(THD *thd)
+{
+ if (user_var_item->update())
+ {
+ /* Give an error if it's not given already */
+ send_error(&thd->net, ER_SET_CONSTANTS_ONLY);
+ return 1;
+ }
+ return 0;
+}
+
+
+/*****************************************************************************
+ Functions to handle SET PASSWORD
+*****************************************************************************/
+
+bool set_var_password::check(THD *thd)
+{
+ if (!user->host.str)
+ user->host.str= (char*) thd->host_or_ip;
+ return check_change_password(thd, user->host.str, user->user.str);
+}
+
+bool set_var_password::update(THD *thd)
+{
+ return change_password(thd, user->host.str, user->user.str, password);
+}
+
+/****************************************************************************
+ Used templates
+****************************************************************************/
+
+#ifdef __GNUC__
+template class List<set_var_base>;
+template class List_iterator<set_var_base>;
+#endif
diff --git a/sql/set_var.h b/sql/set_var.h
new file mode 100644
index 00000000000..cbe479b7902
--- /dev/null
+++ b/sql/set_var.h
@@ -0,0 +1,440 @@
+/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/* Classes to support the SET command */
+
+#ifdef __GNUC__
+#pragma interface /* gcc class implementation */
+#endif
+
+/****************************************************************************
+ Variables that are changable runtime are declared using the
+ following classes
+****************************************************************************/
+
+class sys_var;
+class set_var;
+typedef struct system_variables SV;
+extern TYPELIB bool_typelib, delay_key_write_typelib;
+
+enum enum_var_type
+{
+ OPT_DEFAULT, OPT_SESSION, OPT_GLOBAL
+};
+
+typedef bool (*sys_check_func)(THD *, set_var *);
+typedef bool (*sys_update_func)(THD *, set_var *);
+typedef void (*sys_after_update_func)(THD *,enum_var_type);
+typedef void (*sys_set_default_func)(THD *, enum_var_type);
+
+class sys_var
+{
+public:
+ struct my_option *option_limits; /* Updated by by set_var_init() */
+ uint name_length; /* Updated by by set_var_init() */
+ const char *name;
+ sys_after_update_func after_update;
+ sys_var(const char *name_arg) :name(name_arg),after_update(0)
+ {}
+ sys_var(const char *name_arg,sys_after_update_func func)
+ :name(name_arg),after_update(func)
+ {}
+ virtual ~sys_var() {}
+ virtual bool check(THD *thd, set_var *var) { return 0; }
+ bool check_enum(THD *thd, set_var *var, TYPELIB *enum_names);
+ virtual bool update(THD *thd, set_var *var)=0;
+ virtual void set_default(THD *thd, enum_var_type type) {}
+ virtual SHOW_TYPE type() { return SHOW_UNDEF; }
+ virtual byte *value_ptr(THD *thd, enum_var_type type) { return 0; }
+ virtual bool check_type(enum_var_type type)
+ { return type != OPT_GLOBAL; } /* Error if not GLOBAL */
+ virtual bool check_update_type(Item_result type)
+ { return type != INT_RESULT; } /* Assume INT */
+ virtual bool check_default(enum_var_type type)
+ { return option_limits == 0; }
+ Item *item(THD *thd, enum_var_type type);
+};
+
+
+class sys_var_long_ptr :public sys_var
+{
+public:
+ ulong *value;
+ sys_var_long_ptr(const char *name_arg, ulong *value_ptr)
+ :sys_var(name_arg),value(value_ptr) {}
+ sys_var_long_ptr(const char *name_arg, ulong *value_ptr,
+ sys_after_update_func func)
+ :sys_var(name_arg,func), value(value_ptr) {}
+ bool update(THD *thd, set_var *var);
+ void set_default(THD *thd, enum_var_type type);
+ SHOW_TYPE type() { return SHOW_LONG; }
+ byte *value_ptr(THD *thd, enum_var_type type) { return (byte*) value; }
+};
+
+
+class sys_var_bool_ptr :public sys_var
+{
+public:
+ my_bool *value;
+ sys_var_bool_ptr(const char *name_arg, my_bool *value_arg)
+ :sys_var(name_arg),value(value_arg)
+ {}
+ bool check(THD *thd, set_var *var)
+ {
+ return check_enum(thd, var, &bool_typelib);
+ }
+ bool update(THD *thd, set_var *var);
+ void set_default(THD *thd, enum_var_type type);
+ SHOW_TYPE type() { return SHOW_MY_BOOL; }
+ byte *value_ptr(THD *thd, enum_var_type type) { return (byte*) value; }
+ bool check_update_type(Item_result type) { return 0; }
+};
+
+
+class sys_var_str :public sys_var
+{
+public:
+ char *value; // Pointer to allocated string
+ sys_check_func check_func;
+ sys_update_func update_func;
+ sys_set_default_func set_default_func;
+ sys_var_str(const char *name_arg,
+ sys_check_func check_func_arg,
+ sys_update_func update_func_arg,
+ sys_set_default_func set_default_func_arg)
+ :sys_var(name_arg), check_func(check_func_arg),
+ update_func(update_func_arg),set_default_func(set_default_func_arg)
+ {}
+ bool check(THD *thd, set_var *var)
+ {
+ return check_func ? (*check_func)(thd, var) : 0;
+ }
+ bool update(THD *thd, set_var *var)
+ {
+ return (*update_func)(thd, var);
+ }
+ void set_default(THD *thd, enum_var_type type)
+ {
+ (*set_default_func)(thd, type);
+ }
+ SHOW_TYPE type() { return SHOW_CHAR; }
+ byte *value_ptr(THD *thd, enum_var_type type) { return (byte*) value; }
+ bool check_update_type(Item_result type)
+ {
+ return type != STRING_RESULT; /* Only accept strings */
+ }
+ bool check_default(enum_var_type type) { return 0; }
+};
+
+
+class sys_var_enum :public sys_var
+{
+ uint *value;
+ TYPELIB *enum_names;
+public:
+ sys_var_enum(const char *name_arg, uint *value_arg,
+ TYPELIB *typelib, sys_after_update_func func)
+ :sys_var(name_arg,func), value(value_arg), enum_names(typelib)
+ {}
+ bool check(THD *thd, set_var *var)
+ {
+ return check_enum(thd, var, enum_names);
+ }
+ bool update(THD *thd, set_var *var);
+ SHOW_TYPE type() { return SHOW_CHAR; }
+ byte *value_ptr(THD *thd, enum_var_type type);
+ bool check_update_type(Item_result type) { return 0; }
+};
+
+
+class sys_var_thd :public sys_var
+{
+public:
+ sys_var_thd(const char *name_arg)
+ :sys_var(name_arg)
+ {}
+ sys_var_thd(const char *name_arg, sys_after_update_func func)
+ :sys_var(name_arg,func)
+ {}
+ bool check_type(enum_var_type type) { return 0; }
+ bool check_default(enum_var_type type)
+ {
+ return type == OPT_GLOBAL && !option_limits;
+ }
+};
+
+
+class sys_var_thd_ulong :public sys_var_thd
+{
+public:
+ ulong SV::*offset;
+ sys_var_thd_ulong(const char *name_arg, ulong SV::*offset_arg)
+ :sys_var_thd(name_arg), offset(offset_arg)
+ {}
+ sys_var_thd_ulong(const char *name_arg, ulong SV::*offset_arg,
+ sys_after_update_func func)
+ :sys_var_thd(name_arg,func), offset(offset_arg)
+ {}
+ bool update(THD *thd, set_var *var);
+ void set_default(THD *thd, enum_var_type type);
+ SHOW_TYPE type() { return SHOW_LONG; }
+ byte *value_ptr(THD *thd, enum_var_type type);
+};
+
+
+class sys_var_thd_ulonglong :public sys_var_thd
+{
+public:
+ ulonglong SV::*offset;
+ sys_var_thd_ulonglong(const char *name_arg, ulonglong SV::*offset_arg)
+ :sys_var_thd(name_arg), offset(offset_arg)
+ {}
+ bool update(THD *thd, set_var *var);
+ void set_default(THD *thd, enum_var_type type);
+ SHOW_TYPE type() { return SHOW_LONGLONG; }
+ byte *value_ptr(THD *thd, enum_var_type type);
+};
+
+
+class sys_var_thd_bool :public sys_var_thd
+{
+public:
+ my_bool SV::*offset;
+ sys_var_thd_bool(const char *name_arg, my_bool SV::*offset_arg)
+ :sys_var_thd(name_arg), offset(offset_arg)
+ {}
+ sys_var_thd_bool(const char *name_arg, my_bool SV::*offset_arg,
+ sys_after_update_func func)
+ :sys_var_thd(name_arg,func), offset(offset_arg)
+ {}
+ bool update(THD *thd, set_var *var);
+ void set_default(THD *thd, enum_var_type type);
+ SHOW_TYPE type() { return SHOW_MY_BOOL; }
+ byte *value_ptr(THD *thd, enum_var_type type);
+ bool check(THD *thd, set_var *var)
+ {
+ return check_enum(thd, var, &bool_typelib);
+ }
+ bool check_update_type(Item_result type) { return 0; }
+};
+
+
+class sys_var_thd_enum :public sys_var_thd
+{
+ ulong SV::*offset;
+ TYPELIB *enum_names;
+public:
+ sys_var_thd_enum(const char *name_arg, ulong SV::*offset_arg,
+ TYPELIB *typelib)
+ :sys_var_thd(name_arg), offset(offset_arg), enum_names(typelib)
+ {}
+ sys_var_thd_enum(const char *name_arg, ulong SV::*offset_arg,
+ TYPELIB *typelib,
+ sys_after_update_func func)
+ :sys_var_thd(name_arg,func), offset(offset_arg), enum_names(typelib)
+ {}
+ bool check(THD *thd, set_var *var)
+ {
+ return check_enum(thd, var, enum_names);
+ }
+ bool update(THD *thd, set_var *var);
+ void set_default(THD *thd, enum_var_type type);
+ SHOW_TYPE type() { return SHOW_CHAR; }
+ byte *value_ptr(THD *thd, enum_var_type type);
+ bool check_update_type(Item_result type) { return 0; }
+};
+
+
+class sys_var_thd_bit :public sys_var_thd
+{
+ sys_update_func update_func;
+public:
+ ulong bit_flag;
+ bool reverse;
+ sys_var_thd_bit(const char *name_arg, sys_update_func func, ulong bit,
+ bool reverse_arg=0)
+ :sys_var_thd(name_arg), update_func(func), bit_flag(bit),
+ reverse(reverse_arg)
+ {}
+ bool check(THD *thd, set_var *var)
+ {
+ return check_enum(thd, var, &bool_typelib);
+ }
+ bool update(THD *thd, set_var *var);
+ bool check_update_type(Item_result type) { return 0; }
+ bool check_type(enum_var_type type) { return type == OPT_GLOBAL; }
+ SHOW_TYPE type() { return SHOW_MY_BOOL; }
+ byte *value_ptr(THD *thd, enum_var_type type);
+};
+
+
+/* some variables that require special handling */
+
+class sys_var_timestamp :public sys_var
+{
+public:
+ sys_var_timestamp(const char *name_arg) :sys_var(name_arg) {}
+ bool update(THD *thd, set_var *var);
+ void set_default(THD *thd, enum_var_type type);
+ bool check_type(enum_var_type type) { return type == OPT_GLOBAL; }
+ bool check_default(enum_var_type type) { return 0; }
+ SHOW_TYPE type() { return SHOW_LONG; }
+ byte *value_ptr(THD *thd, enum_var_type type);
+};
+
+
+class sys_var_last_insert_id :public sys_var
+{
+public:
+ sys_var_last_insert_id(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; }
+ SHOW_TYPE type() { return SHOW_LONGLONG; }
+ byte *value_ptr(THD *thd, enum_var_type type);
+};
+
+
+class sys_var_insert_id :public sys_var
+{
+public:
+ sys_var_insert_id(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; }
+ SHOW_TYPE type() { return SHOW_LONGLONG; }
+ byte *value_ptr(THD *thd, enum_var_type type);
+};
+
+
+class sys_var_slave_skip_counter :public sys_var
+{
+public:
+ sys_var_slave_skip_counter(const char *name_arg) :sys_var(name_arg) {}
+ bool check(THD *thd, set_var *var);
+ bool update(THD *thd, set_var *var);
+ bool check_type(enum_var_type type) { return type != OPT_GLOBAL; }
+ /*
+ We can't retrieve the value of this, so we don't have to define
+ type() or value_ptr()
+ */
+};
+
+
+class sys_var_thd_conv_charset :public sys_var_thd
+{
+public:
+ sys_var_thd_conv_charset(const char *name_arg)
+ :sys_var_thd(name_arg)
+ {}
+ bool check(THD *thd, set_var *var);
+ bool update(THD *thd, set_var *var);
+ SHOW_TYPE type() { return SHOW_CHAR; }
+ byte *value_ptr(THD *thd, enum_var_type type);
+ bool check_update_type(Item_result type)
+ {
+ return type != STRING_RESULT; /* Only accept strings */
+ }
+ bool check_default(enum_var_type type) { return 0; }
+};
+
+
+/****************************************************************************
+ Classes for parsing of the SET command
+****************************************************************************/
+
+class set_var_base :public Sql_alloc
+{
+public:
+ set_var_base() {}
+ virtual ~set_var_base() {}
+ virtual bool check(THD *thd)=0; /* To check privileges etc. */
+ virtual bool update(THD *thd)=0; /* To set the value */
+};
+
+
+/* MySQL internal variables, like query_cache_size */
+
+class set_var :public set_var_base
+{
+public:
+ sys_var *var;
+ Item *value;
+ enum_var_type type;
+ union
+ {
+ CONVERT *convert;
+ ulong ulong_value;
+ } save_result;
+
+ set_var(enum_var_type type_arg, sys_var *var_arg, Item *value_arg)
+ :var(var_arg), type(type_arg)
+ {
+ /*
+ If the set value is a field, change it to a string to allow things like
+ SET table_type=MYISAM;
+ */
+ if (value_arg && value_arg->type() == Item::FIELD_ITEM)
+ {
+ Item_field *item= (Item_field*) value_arg;
+ if (!(value=new Item_string(item->field_name, strlen(item->field_name))))
+ value=value_arg; /* Give error message later */
+ }
+ else
+ value=value_arg;
+ }
+ bool check(THD *thd);
+ bool update(THD *thd);
+};
+
+
+/* User variables like @my_own_variable */
+
+class set_var_user: public set_var_base
+{
+ Item_func_set_user_var *user_var_item;
+public:
+ set_var_user(Item_func_set_user_var *item)
+ :user_var_item(item)
+ {}
+ bool check(THD *thd);
+ bool update(THD *thd);
+};
+
+/* For SET PASSWORD */
+
+class set_var_password: public set_var_base
+{
+ LEX_USER *user;
+ char *password;
+public:
+ set_var_password(LEX_USER *user_arg,char *password_arg)
+ :user(user_arg), password(password_arg)
+ {}
+ bool check(THD *thd);
+ bool update(THD *thd);
+};
+
+
+/*
+ Prototypes for helper functions
+*/
+
+void set_var_init();
+void set_var_free();
+sys_var *find_sys_var(const char *str, uint length=0);
+bool sql_set_variables(THD *thd, List<set_var_base> *var_list);
+void fix_delay_key_write(THD *thd, enum_var_type type);
+
+extern sys_var_str sys_charset;
diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt
index 9ce8875ceeb..e9f3b997a96 100644
--- a/sql/share/czech/errmsg.txt
+++ b/sql/share/czech/errmsg.txt
@@ -237,6 +237,16 @@
"Mixing of transactional and non-transactional tables is disabled",
"Option '%s' used twice in statement",
"User '%-.64s' has exceeded the '%s' resource (current value: %ld)",
+"Access denied. You need the %-.128s privilege for this operation",
+"Variable '%-.64s' is a LOCAL variable and can't be used with SET GLOBAL",
+"Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL",
+"Variable '%-.64s' doesn't have a default value",
+"Variable '%-.64s' can't be set to the value of '%-.64s'",
+"Wrong argument type to variable '%-.64s'",
+"Variable '%-.64s' can only be set, not read",
+"Wrong usage/placement of '%s'",
+"This version of MySQL doesn't yet support '%s'",
+"Got fatal error %d: '%-.128s' from master when reading data from binary log",
"Wrong foreign key definition for '%-.64s': %s",
"Key reference and table reference doesn't match",
"Subselect return more than 1 field",
diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt
index 0babb8981a8..71785bb8ba2 100644
--- a/sql/share/danish/errmsg.txt
+++ b/sql/share/danish/errmsg.txt
@@ -231,6 +231,16 @@
"Mixing of transactional and non-transactional tables is disabled",
"Option '%s' used twice in statement",
"User '%-.64s' has exceeded the '%s' resource (current value: %ld)",
+"Access denied. You need the %-.128s privilege for this operation",
+"Variable '%-.64s' is a LOCAL variable and can't be used with SET GLOBAL",
+"Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL",
+"Variable '%-.64s' doesn't have a default value",
+"Variable '%-.64s' can't be set to the value of '%-.64s'",
+"Wrong argument type to variable '%-.64s'",
+"Variable '%-.64s' can only be set, not read",
+"Wrong usage/placement of '%s'",
+"This version of MySQL doesn't yet support '%s'",
+"Got fatal error %d: '%-.128s' from master when reading data from binary log",
"Wrong foreign key definition for '%-.64s': %s",
"Key reference and table reference doesn't match",
"Subselect return more than 1 field",
diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt
index b2fab274db1..e129b1cc30e 100644
--- a/sql/share/dutch/errmsg.txt
+++ b/sql/share/dutch/errmsg.txt
@@ -6,6 +6,9 @@
Completed earlier partial translation; worked on consistency and spelling.
2002-01-29 - Arjen Lentz (arjen@mysql.com)
2002-04-11 - Arjen Lentz (arjen@mysql.com)
+ 2002-06-13 - Arjen Lentz (arjen@mysql.com)
+ 2002-08-08 - Arjen Lentz (arjen@mysql.com)
+ 2002-08-22 - Arjen Lentz (arjen@mysql.com)
Translated new error messages.
*/
@@ -236,6 +239,16 @@
"Het combineren van transactionele en niet-transactionele tabellen is uitgeschakeld.",
"Optie '%s' tweemaal gebruikt in opdracht",
"Gebruiker '%-.64s' heeft het maximale gebruik van de '%s' faciliteit overschreden (huidige waarde: %ld)",
+"Toegang geweigerd. U moet het %-.128s privilege hebben voor deze operatie",
+"Variabele '%-.64s' is LOCAL en kan niet worden gebruikt met SET GLOBAL",
+"Variabele '%-.64s' is GLOBAL en dient te worden gewijzigd met SET GLOBAL",
+"Variabele '%-.64s' heeft geen standaard waarde",
+"Variabele '%-.64s' kan niet worden gewijzigd naar de waarde '%-.64s'",
+"Foutief argumenttype voor variabele '%-.64s'",
+"Variabele '%-.64s' kan alleen worden gewijzigd, niet gelezen",
+"Foutieve toepassing/plaatsing van '%s'",
+"Deze versie van MySQL ondersteunt nog geen '%s'",
+"Kreeg fatale fout %d: '%-.128s' van master tijdens lezen van data uit binaire log",
"Wrong foreign key definition for '%-.64s': %s",
"Key reference and table reference doesn't match",
"Subselect return more than 1 field",
diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt
index 1a68a9dcb85..88ab604fbcf 100644
--- a/sql/share/english/errmsg.txt
+++ b/sql/share/english/errmsg.txt
@@ -228,6 +228,16 @@
"Mixing of transactional and non-transactional tables is disabled",
"Option '%s' used twice in statement",
"User '%-.64s' has exceeded the '%s' resource (current value: %ld)",
+"Access denied. You need the %-.128s privilege for this operation",
+"Variable '%-.64s' is a LOCAL variable and can't be used with SET GLOBAL",
+"Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL",
+"Variable '%-.64s' doesn't have a default value",
+"Variable '%-.64s' can't be set to the value of '%-.64s'",
+"Wrong argument type to variable '%-.64s'",
+"Variable '%-.64s' can only be set, not read",
+"Wrong usage/placement of '%s'",
+"This version of MySQL doesn't yet support '%s'",
+"Got fatal error %d: '%-.128s' from master when reading data from binary log",
"Wrong foreign key definition for '%-.64s': %s",
"Key reference and table reference doesn't match",
"Subselect return more than 1 field",
diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt
index e52dfd72c5a..9f412bb1594 100644
--- a/sql/share/estonian/errmsg.txt
+++ b/sql/share/estonian/errmsg.txt
@@ -233,6 +233,16 @@
"Transaktsioone toetavate ning mittetoetavate tabelite kooskasutamine ei ole lubatud",
"Määrangut '%s' on lauses kasutatud topelt",
"User '%-.64s' has exceeded the '%s' resource (current value: %ld)",
+"Access denied. You need the %-.128s privilege for this operation",
+"Variable '%-.64s' is a LOCAL variable and can't be used with SET GLOBAL",
+"Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL",
+"Variable '%-.64s' doesn't have a default value",
+"Variable '%-.64s' can't be set to the value of '%-.64s'",
+"Wrong argument type to variable '%-.64s'",
+"Variable '%-.64s' can only be set, not read",
+"Wrong usage/placement of '%s'",
+"This version of MySQL doesn't yet support '%s'",
+"Got fatal error %d: '%-.128s' from master when reading data from binary log",
"Wrong foreign key definition for '%-.64s': %s",
"Key reference and table reference doesn't match",
"Subselect return more than 1 field",
diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt
index 8d0e2505eb0..33cf1a9e377 100644
--- a/sql/share/french/errmsg.txt
+++ b/sql/share/french/errmsg.txt
@@ -147,7 +147,7 @@
"La commande '%-.16s' est interdite à l'utilisateur: '%-.32s@%-.64s' sur la colonne '%-.64s' de la table '%-.64s'",
"Commande GRANT/REVOKE incorrecte. Consultez le manuel.",
"L'hôte ou l'utilisateur donné en argument à GRANT est trop long",
-"La table '%-64s.%s' n'existe pas",
+"La table '%-.64s.%s' n'existe pas",
"Un tel droit n'est pas défini pour l'utilisateur '%-.32s' sur l'hôte '%-.64s' sur la table '%-.64s'",
"Cette commande n'existe pas dans cette version de MySQL",
"Erreur de syntaxe",
@@ -228,6 +228,16 @@
"Mixing of transactional and non-transactional tables is disabled",
"Option '%s' used twice in statement",
"User '%-.64s' has exceeded the '%s' resource (current value: %ld)",
+"Access denied. You need the %-.128s privilege for this operation",
+"Variable '%-.64s' is a LOCAL variable and can't be used with SET GLOBAL",
+"Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL",
+"Variable '%-.64s' doesn't have a default value",
+"Variable '%-.64s' can't be set to the value of '%-.64s'",
+"Wrong argument type to variable '%-.64s'",
+"Variable '%-.64s' can only be set, not read",
+"Wrong usage/placement of '%s'",
+"This version of MySQL doesn't yet support '%s'",
+"Got fatal error %d: '%-.128s' from master when reading data from binary log",
"Wrong foreign key definition for '%-.64s': %s",
"Key reference and table reference doesn't match",
"Subselect return more than 1 field",
diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt
index afd727a19ea..1056dccba2b 100644
--- a/sql/share/german/errmsg.txt
+++ b/sql/share/german/errmsg.txt
@@ -231,6 +231,16 @@
"Mixing of transactional and non-transactional tables is disabled",
"Option '%s' used twice in statement",
"User '%-.64s' has exceeded the '%s' resource (current value: %ld)",
+"Access denied. You need the %-.128s privilege for this operation",
+"Variable '%-.64s' is a LOCAL variable and can't be used with SET GLOBAL",
+"Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL",
+"Variable '%-.64s' doesn't have a default value",
+"Variable '%-.64s' can't be set to the value of '%-.64s'",
+"Wrong argument type to variable '%-.64s'",
+"Variable '%-.64s' can only be set, not read",
+"Wrong usage/placement of '%s'",
+"This version of MySQL doesn't yet support '%s'",
+"Got fatal error %d: '%-.128s' from master when reading data from binary log",
"Wrong foreign key definition for '%-.64s': %s",
"Key reference and table reference doesn't match",
"Subselect return more than 1 field",
diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt
index 171493458c9..a344ed2df9e 100644
--- a/sql/share/greek/errmsg.txt
+++ b/sql/share/greek/errmsg.txt
@@ -228,6 +228,16 @@
"Mixing of transactional and non-transactional tables is disabled",
"Option '%s' used twice in statement",
"User '%-.64s' has exceeded the '%s' resource (current value: %ld)",
+"Access denied. You need the %-.128s privilege for this operation",
+"Variable '%-.64s' is a LOCAL variable and can't be used with SET GLOBAL",
+"Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL",
+"Variable '%-.64s' doesn't have a default value",
+"Variable '%-.64s' can't be set to the value of '%-.64s'",
+"Wrong argument type to variable '%-.64s'",
+"Variable '%-.64s' can only be set, not read",
+"Wrong usage/placement of '%s'",
+"This version of MySQL doesn't yet support '%s'",
+"Got fatal error %d: '%-.128s' from master when reading data from binary log",
"Wrong foreign key definition for '%-.64s': %s",
"Key reference and table reference doesn't match",
"Subselect return more than 1 field",
diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt
index f891f8a7e91..9e88f2c3e2c 100644
--- a/sql/share/hungarian/errmsg.txt
+++ b/sql/share/hungarian/errmsg.txt
@@ -230,6 +230,16 @@
"Mixing of transactional and non-transactional tables is disabled",
"Option '%s' used twice in statement",
"User '%-.64s' has exceeded the '%s' resource (current value: %ld)",
+"Access denied. You need the %-.128s privilege for this operation",
+"Variable '%-.64s' is a LOCAL variable and can't be used with SET GLOBAL",
+"Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL",
+"Variable '%-.64s' doesn't have a default value",
+"Variable '%-.64s' can't be set to the value of '%-.64s'",
+"Wrong argument type to variable '%-.64s'",
+"Variable '%-.64s' can only be set, not read",
+"Wrong usage/placement of '%s'",
+"This version of MySQL doesn't yet support '%s'",
+"Got fatal error %d: '%-.128s' from master when reading data from binary log",
"Wrong foreign key definition for '%-.64s': %s",
"Key reference and table reference doesn't match",
"Subselect return more than 1 field",
diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt
index 9b8eb214215..c9275a70878 100644
--- a/sql/share/italian/errmsg.txt
+++ b/sql/share/italian/errmsg.txt
@@ -228,6 +228,16 @@
"Mixing of transactional and non-transactional tables is disabled",
"Option '%s' used twice in statement",
"User '%-.64s' has exceeded the '%s' resource (current value: %ld)",
+"Access denied. You need the %-.128s privilege for this operation",
+"Variable '%-.64s' is a LOCAL variable and can't be used with SET GLOBAL",
+"Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL",
+"Variable '%-.64s' doesn't have a default value",
+"Variable '%-.64s' can't be set to the value of '%-.64s'",
+"Wrong argument type to variable '%-.64s'",
+"Variable '%-.64s' can only be set, not read",
+"Wrong usage/placement of '%s'",
+"This version of MySQL doesn't yet support '%s'",
+"Got fatal error %d: '%-.128s' from master when reading data from binary log",
"Wrong foreign key definition for '%-.64s': %s",
"Key reference and table reference doesn't match",
"Subselect return more than 1 field",
diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt
index 4016dd50189..07bdcd6bee5 100644
--- a/sql/share/japanese/errmsg.txt
+++ b/sql/share/japanese/errmsg.txt
@@ -230,6 +230,16 @@
"Mixing of transactional and non-transactional tables is disabled",
"Option '%s' used twice in statement",
"User '%-.64s' has exceeded the '%s' resource (current value: %ld)",
+"Access denied. You need the %-.128s privilege for this operation",
+"Variable '%-.64s' is a LOCAL variable and can't be used with SET GLOBAL",
+"Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL",
+"Variable '%-.64s' doesn't have a default value",
+"Variable '%-.64s' can't be set to the value of '%-.64s'",
+"Wrong argument type to variable '%-.64s'",
+"Variable '%-.64s' can only be set, not read",
+"Wrong usage/placement of '%s'",
+"This version of MySQL doesn't yet support '%s'",
+"Got fatal error %d: '%-.128s' from master when reading data from binary log",
"Wrong foreign key definition for '%-.64s': %s",
"Key reference and table reference doesn't match",
"Subselect return more than 1 field",
diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt
index 93e9948d4fd..57f990fdc04 100644
--- a/sql/share/korean/errmsg.txt
+++ b/sql/share/korean/errmsg.txt
@@ -228,6 +228,16 @@
"Mixing of transactional and non-transactional tables is disabled",
"Option '%s' used twice in statement",
"User '%-.64s' has exceeded the '%s' resource (current value: %ld)",
+"Access denied. You need the %-.128s privilege for this operation",
+"Variable '%-.64s' is a LOCAL variable and can't be used with SET GLOBAL",
+"Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL",
+"Variable '%-.64s' doesn't have a default value",
+"Variable '%-.64s' can't be set to the value of '%-.64s'",
+"Wrong argument type to variable '%-.64s'",
+"Variable '%-.64s' can only be set, not read",
+"Wrong usage/placement of '%s'",
+"This version of MySQL doesn't yet support '%s'",
+"Got fatal error %d: '%-.128s' from master when reading data from binary log",
"Wrong foreign key definition for '%-.64s': %s",
"Key reference and table reference doesn't match",
"Subselect return more than 1 field",
diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt
index 612757726c7..37f7f2fac01 100644
--- a/sql/share/norwegian-ny/errmsg.txt
+++ b/sql/share/norwegian-ny/errmsg.txt
@@ -230,6 +230,16 @@
"Mixing of transactional and non-transactional tables is disabled",
"Option '%s' used twice in statement",
"User '%-.64s' has exceeded the '%s' resource (current value: %ld)",
+"Access denied. You need the %-.128s privilege for this operation",
+"Variable '%-.64s' is a LOCAL variable and can't be used with SET GLOBAL",
+"Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL",
+"Variable '%-.64s' doesn't have a default value",
+"Variable '%-.64s' can't be set to the value of '%-.64s'",
+"Wrong argument type to variable '%-.64s'",
+"Variable '%-.64s' can only be set, not read",
+"Wrong usage/placement of '%s'",
+"This version of MySQL doesn't yet support '%s'",
+"Got fatal error %d: '%-.128s' from master when reading data from binary log",
"Wrong foreign key definition for '%-.64s': %s",
"Key reference and table reference doesn't match",
"Subselect return more than 1 field",
diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt
index f0d884c330f..93f4090d697 100644
--- a/sql/share/norwegian/errmsg.txt
+++ b/sql/share/norwegian/errmsg.txt
@@ -230,6 +230,16 @@
"Mixing of transactional and non-transactional tables is disabled",
"Option '%s' used twice in statement",
"User '%-.64s' has exceeded the '%s' resource (current value: %ld)",
+"Access denied. You need the %-.128s privilege for this operation",
+"Variable '%-.64s' is a LOCAL variable and can't be used with SET GLOBAL",
+"Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL",
+"Variable '%-.64s' doesn't have a default value",
+"Variable '%-.64s' can't be set to the value of '%-.64s'",
+"Wrong argument type to variable '%-.64s'",
+"Variable '%-.64s' can only be set, not read",
+"Wrong usage/placement of '%s'",
+"This version of MySQL doesn't yet support '%s'",
+"Got fatal error %d: '%-.128s' from master when reading data from binary log",
"Wrong foreign key definition for '%-.64s': %s",
"Key reference and table reference doesn't match",
"Subselect return more than 1 field",
diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt
index 22f7c331a98..3b43ce539c7 100644
--- a/sql/share/polish/errmsg.txt
+++ b/sql/share/polish/errmsg.txt
@@ -232,6 +232,16 @@
"Mixing of transactional and non-transactional tables is disabled",
"Option '%s' used twice in statement",
"User '%-.64s' has exceeded the '%s' resource (current value: %ld)",
+"Access denied. You need the %-.128s privilege for this operation",
+"Variable '%-.64s' is a LOCAL variable and can't be used with SET GLOBAL",
+"Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL",
+"Variable '%-.64s' doesn't have a default value",
+"Variable '%-.64s' can't be set to the value of '%-.64s'",
+"Wrong argument type to variable '%-.64s'",
+"Variable '%-.64s' can only be set, not read",
+"Wrong usage/placement of '%s'",
+"This version of MySQL doesn't yet support '%s'",
+"Got fatal error %d: '%-.128s' from master when reading data from binary log",
"Wrong foreign key definition for '%-.64s': %s",
"Key reference and table reference doesn't match",
"Subselect return more than 1 field",
diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt
index a00dabc391b..fcdbf607807 100644
--- a/sql/share/portuguese/errmsg.txt
+++ b/sql/share/portuguese/errmsg.txt
@@ -1,28 +1,28 @@
/* Copyright Abandoned 1997 TCX DataKonsult AB & Monty Program KB & Detron HB
This file is public domain and comes with NO WARRANTY of any kind */
-/* Updated by Roberto de Martin Serqueira - martinsc@uol.com.br - 08.20.2001 */
+/* Updated by Thiago Delgado Pinto - thiagodp@ieg.com.br - 06.07.2002 */
"hashchk",
"isamchk",
-"não",
-"sim",
-"Não pode criar arquivo '%-.64s' (erro no. %d)",
-"Não pode criar tabela '%-.64s' (erro no. %d)",
-"Não pode criar banco de dados '%-.64s' (erro no. %d)",
-"Não pode criar banco de dados '%-.64s'. Banco de dados já existe",
-"Não pode eliminar banco de dados '%-.64s'. Banco de dados não existe",
+"NÃO",
+"SIM",
+"Não pode criar o arquivo '%-.64s' (erro no. %d)",
+"Não pode criar a tabela '%-.64s' (erro no. %d)",
+"Não pode criar o banco de dados '%-.64s' (erro no. %d)",
+"Não pode criar o banco de dados '%-.64s'. Este banco de dados já existe",
+"Não pode eliminar o banco de dados '%-.64s'. Este banco de dados não existe",
"Erro ao eliminar banco de dados (não pode eliminar '%-.64s' - erro no. %d)",
"Erro ao eliminar banco de dados (não pode remover diretório '%-.64s' - erro no. %d)",
-"Erro na deleção de '%-.64s' (erro no. %d)",
-"Não pode ler registro em tabela do sistema",
-"Não pode obter status de '%-.64s' (erro no. %d)",
-"Não pode obter diretório corrente (erro no. %d)",
-"Não pode travar arquivo (erro no. %d)",
-"Não pode abrir arquivo '%-.64s' (erro no. %d)",
-"Não pode encontrar arquivo '%-.64s' (erro no. %d)",
-"Não pode ler diretório de '%-.64s' (erro no. %d)",
+"Erro na remoção de '%-.64s' (erro no. %d)",
+"Não pode ler um registro numa tabela do sistema",
+"Não pode obter o status de '%-.64s' (erro no. %d)",
+"Não pode obter o diretório corrente (erro no. %d)",
+"Não pode travar o arquivo (erro no. %d)",
+"Não pode abrir o arquivo '%-.64s' (erro no. %d)",
+"Não pode encontrar o arquivo '%-.64s' (erro no. %d)",
+"Não pode ler o diretório de '%-.64s' (erro no. %d)",
"Não pode mudar para o diretório '%-.64s' (erro no. %d)",
"Registro alterado desde a última leitura da tabela '%-.64s'",
-"Disco cheio (%s). Aguardando alguém liberar algum espaço....",
+"Disco cheio (%s). Aguardando alguém liberar algum espaço...",
"Não pode gravar. Chave duplicada na tabela '%-.64s'",
"Erro ao fechar '%-.64s' (erro no. %d)",
"Erro ao ler arquivo '%-.64s' (erro no. %d)",
@@ -30,13 +30,13 @@
"Erro ao gravar arquivo '%-.64s' (erro no. %d)",
"'%-.64s' está com travamento contra alterações",
"Ordenação abortada",
-"'View' '%-.64s' não existe para '%-.64s'",
+"Visão '%-.64s' não existe para '%-.64s'",
"Obteve erro %d no manipulador de tabelas",
"Manipulador de tabela para '%-.64s' não tem esta opção",
"Não pode encontrar registro em '%-.64s'",
"Informação incorreta no arquivo '%-.64s'",
-"Arquivo de índice incorreto para tabela '%-.64s'. Tente reparar",
-"Arquivo chave desatualizado para tabela '%-.64s'. Repare-o!",
+"Arquivo de índice incorreto para tabela '%-.64s'. Tente repará-lo",
+"Arquivo de índice desatualizado para tabela '%-.64s'. Repare-o!",
"Tabela '%-.64s' é somente para leitura",
"Sem memória. Reinicie o programa e tente novamente (necessita de %d bytes)",
"Sem memória para ordenação. Aumente tamanho do 'buffer' de ordenação",
@@ -46,10 +46,10 @@
"Não pode obter nome do 'host' para seu endereço",
"Negociação de acesso falhou",
"Acesso negado para o usuário '%-.32s@%-.64s' ao banco de dados '%-.64s'",
-"Acesso negado para o usuário '%-.32s@%-.64s' (uso de senha: %s)",
+"Acesso negado para o usuário '%-.32s@%-.64s' (senha usada: %s)",
"Nenhum banco de dados foi selecionado",
"Comando desconhecido",
-"Coluna '%-.64s' não pode ter NULL",
+"Coluna '%-.64s' não pode ser vazia",
"Banco de dados '%-.64s' desconhecido",
"Tabela '%-.64s' já existe",
"Tabela '%-.64s' desconhecida",
@@ -66,9 +66,9 @@
"Entrada '%-.64s' duplicada para a chave %d",
"Especificador de coluna incorreto para a coluna '%-.64s'",
"%s próximo a '%-.80s' na linha %d",
-"'Query' estava vazia",
+"Consulta (query) estava vazia",
"Tabela/alias '%-.64s' não única",
-"Valor 'default' inválido para '%-.64s'",
+"Valor padrão (default) inválido para '%-.64s'",
"Definida mais de uma chave primária",
"Especificadas chaves demais. O máximo permitido são %d chaves",
"Especificadas partes de chave demais. O máximo permitido são %d partes",
@@ -82,50 +82,50 @@
"%s: Obteve sinal %d. Abortando!\n",
"%s: 'Shutdown' completo\n",
"%s: Forçando finalização da 'thread' %ld - usuário '%-.32s'\n",
-"Não pode criar 'IP socket'",
+"Não pode criar o soquete IP",
"Tabela '%-.64s' não possui um índice como o usado em CREATE INDEX. Recrie a tabela",
-"Argumento separador de campos não é o esperado. Confira no manual",
-"Você não pode usar comprimento de linha fixo com BLOBs. Favor usar 'fields terminated by'",
+"Argumento separador de campos não é o esperado. Cheque o manual",
+"Você não pode usar comprimento de linha fixo com BLOBs. Por favor, use campos com comprimento limitado.",
"Arquivo '%-.64s' tem que estar no diretório do banco de dados ou ter leitura possível para todos",
"Arquivo '%-.80s' já existe",
"Registros: %ld - Deletados: %ld - Ignorados: %ld - Avisos: %ld",
"Registros: %ld - Duplicados: %ld",
-"Parte de chave incorreta. A parte de chave usada não é um 'string' ou o comprimento usado é maior do que a parte de chave ou o manipulador de tabelas não aceita partes de chaves únicas",
+"Sub parte da chave incorreta. A parte da chave usada não é uma 'string' ou o comprimento usado é maior que parte da chave ou o manipulador de tabelas não suporta sub chaves únicas",
"Você não pode deletar todas as colunas com ALTER TABLE. Use DROP TABLE em seu lugar",
-"Não pode fazer DROP '%-.64s'. Confira se esta coluna/chave existe",
+"Não se pode fazer DROP '%-.64s'. Confira se esta coluna/chave existe",
"Registros: %ld - Duplicados: %ld - Avisos: %ld",
-"INSERT TABLE '%-.64s' não é permitido em lista de tabelas FROM",
+"INSERT TABLE '%-.64s' não é permitido na lista de tabelas contidas em FROM",
"'Id' de 'thread' %lu desconhecido",
"Você não é proprietário da 'thread' %lu",
"Nenhuma tabela usada",
"'Strings' demais para coluna '%-.64s' e SET",
"Não pode gerar um nome de arquivo de 'log' único '%-.64s'.(1-999)\n",
-"Tabela '%-.64s' foi travada com trava de READ e não pode ser atualizada",
+"Tabela '%-.64s' foi travada com trava de leitura e não pode ser atualizada",
"Tabela '%-.64s' não foi travada com LOCK TABLES",
-"Coluna BLOB '%-.64s' não pode ter um valor 'default'",
+"Coluna BLOB '%-.64s' não pode ter um valor padrão (default)",
"Nome de banco de dados '%-.100s' incorreto",
"Nome de tabela '%-.100s' incorreto",
-"O SELECT examinaria registros demais e provavelmente tomaria um tempo muito longo. Confira sua cláusula WHERE e use SET OPTION SQL_BIG_SELECTS=1, se o SELECT estiver correto",
+"O SELECT examinaria registros demais e provavelmente levaria muito tempo. Cheque sua cláusula WHERE e use SET OPTION SQL_BIG_SELECTS=1, se o SELECT estiver correto",
"Erro desconhecido",
"'Procedure' '%-.64s' desconhecida",
"Número de parâmetros incorreto para a 'procedure' '%-.64s'",
"Parâmetros incorretos para a 'procedure' '%-.64s'",
"Tabela '%-.64s' desconhecida em '%-.32s'",
"Coluna '%-.64s' especificada duas vezes",
-"Uso inválido de função de grupo",
+"Uso inválido de função de agrupamento (GROUP)",
"Tabela '%-.64s' usa uma extensão que não existe nesta versão do MySQL",
"Uma tabela tem que ter pelo menos uma (1) coluna",
"Tabela '%-.64s' está cheia",
"Conjunto de caracteres '%-.64s' desconhecido",
-"Tabelas demais. O MySQL pode usar somente %d tabelas em um JOIN",
+"Tabelas demais. O MySQL pode usar somente %d tabelas em uma junção (JOIN)",
"Colunas demais",
"Tamanho de linha grande demais. O máximo tamanho de linha, não contando BLOBs, é %d. Você tem que mudar alguns campos para BLOBs",
"Estouro da pilha do 'thread'. Usados %ld de uma pilha de %ld . Use 'mysqld -O thread_stack=#' para especificar uma pilha maior, se necessário",
-"Dependência cruzada encontrada em OUTER JOIN. Examine suas condições ON",
-"Coluna '%-.64s' é usada com UNIQUE ou INDEX, mas não está definida como NOT NULL",
+"Dependência cruzada encontrada em junção externa (OUTER JOIN). Examine as condições utilizadas nas cláusulas 'ON'",
+"Coluna '%-.64s' é usada com única (UNIQUE) ou índice (INDEX), mas não está definida como não-nula (NOT NULL)",
"Não pode carregar a função '%-.64s'",
"Não pode inicializar a função '%-.64s' - '%-.80s'",
-"Não é permitido caminho para biblioteca compartilhada",
+"Não há caminhos (paths) permitidos para biblioteca compartilhada",
"Função '%-.64s' já existe",
"Não pode abrir biblioteca compartilhada '%-.64s' (erro no. '%d' - '%-.64s')",
"Não pode encontrar a função '%-.64s' na biblioteca",
@@ -133,34 +133,34 @@
"'Host' '%-.64s' está bloqueado devido a muitos erros de conexão. Desbloqueie com 'mysqladmin flush-hosts'",
"'Host' '%-.64s' não tem permissão para se conectar com este servidor MySQL",
"Você está usando o MySQL como usuário anônimo e usuários anônimos não têm permissão para mudar senhas",
-"Você tem que ter o privilégio para atualizar tabelas no banco de dados mysql para ser capaz de mudar a senha de outros",
-"Não pode encontrar nenhuma linha que combine na tabela user",
+"Você deve ter privilégios para atualizar tabelas no banco de dados mysql para ser capaz de mudar a senha de outros",
+"Não pode encontrar nenhuma linha que combine na tabela usuário (user table)",
"Linhas que combinaram: %ld - Alteradas: %ld - Avisos: %ld",
"Não pode criar uma nova 'thread' (erro no. %d). Se você não estiver sem memória disponível, você pode consultar o manual sobre um possível 'bug' dependente do sistema operacional",
"Contagem de colunas não confere com a contagem de valores na linha %ld",
"Não pode reabrir a tabela '%-.64s',
"Uso inválido do valor NULL",
"Obteve erro '%-.64s' em regexp",
-"Mistura de colunas GROUP (MIN(),MAX(),COUNT()...) com colunas não GROUP é ilegal, se não existir cláusula GROUP BY",
-"Não existe tal 'grant' definido para o usuário '%-.32s' no 'host' '%-.64s'",
+"Mistura de colunas agrupadas (com MIN(), MAX(), COUNT(), ...) com colunas não agrupadas é ilegal, se não existir uma cláusula de agrupamento (cláusula GROUP BY)",
+"Não existe tal permissão (grant) definida para o usuário '%-.32s' no 'host' '%-.64s'",
"Comando '%-.16s' negado para o usuário '%-.32s@%-.64s' na tabela '%-.64s'",
"Comando '%-.16s' negado para o usuário '%-.32s@%-.64s' na coluna '%-.64s', na tabela '%-.64s'",
"Comando GRANT/REVOKE ilegal. Por favor consulte no manual quais privilégios podem ser usados.",
"Argumento de 'host' ou de usuário para o GRANT é longo demais",
"Tabela '%-.64s.%-.64s' não existe",
-"Não existe tal 'grant' definido para o usuário '%-.32s' no 'host' '%-.64s', na tabela '%-.64s'",
+"Não existe tal permissão (grant) definido para o usuário '%-.32s' no 'host' '%-.64s', na tabela '%-.64s'",
"Comando usado não é permitido para esta versão do MySQL",
"Você tem um erro de sintaxe no seu SQL",
-"'Thread' de inserção retardada ('delayed') não conseguiu obter trava solicitada para tabela '%-.64s'",
-"Excesso de 'threads' retardadas ('delayed') em uso",
+"'Thread' de inserção retardada (atrasada) pois não conseguiu obter a trava solicitada para tabela '%-.64s'",
+"Excesso de 'threads' retardadas (atrasadas) em uso",
"Conexão %ld abortou para o banco de dados '%-.64s' - usuário '%-.32s' (%-.64s)",
-"Obteve um pacote maior do que 'max_allowed_packet'",
+"Obteve um pacote maior do que a taxa máxima de pacotes definida (max_allowed_packet)",
"Obteve um erro de leitura no 'pipe' da conexão",
"Obteve um erro em fcntl()",
"Obteve pacotes fora de ordem",
"Não conseguiu descomprimir pacote de comunicação",
"Obteve um erro na leitura de pacotes de comunicação",
-"Obteve expiração de tempo ('timeout') na leitura de pacotes de comunicação",
+"Obteve expiração de tempo (timeout) na leitura de pacotes de comunicação",
"Obteve um erro na escrita de pacotes de comunicação",
"Obteve expiração de tempo ('timeout') na escrita de pacotes de comunicação",
"'String' resultante é mais longa do que 'max_allowed_packet'",
@@ -169,56 +169,56 @@
"INSERT DELAYED não pode ser usado com a tabela '%-.64s', porque ela está travada com LOCK TABLES",
"Nome de coluna '%-.100s' incorreto",
"O manipulador de tabela usado não pode indexar a coluna '%-.64s'",
-"Tabelas no MERGE não estão todas definidas identicamente",
+"Todas as tabelas contidas na tabela fundida (MERGE) não estão definidas identicamente",
"Não pode gravar, devido à restrição UNIQUE, na tabela '%-.64s'",
"Coluna BLOB '%-.64s' usada na especificação de chave sem o comprimento da chave",
-"Todas as partes de uma PRIMARY KEY têm que ser NOT NULL. Se você precisar de NULL em uma chave, use UNIQUE em seu lugar",
+"Todas as partes de uma chave primária devem ser não-nulas. Se você precisou usar um valor nulo (NULL) em uma chave, use a cláusula UNIQUE em seu lugar",
"O resultado consistiu em mais do que uma linha",
"Este tipo de tabela requer uma chave primária",
"Esta versão do MySQL não foi compilada com suporte a RAID",
-"Você está usando modo de atualização seguro e tentou atualizar uma tabela sem um WHERE que use uma coluna de KEY",
+"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 check/repair",
-"Não lhe é permitido executar este comando em uma 'transaction'",
+"O manipulador de tabela não suporta checagem/reparação (check/repair)",
+"Não lhe é permitido executar este comando em uma transação",
"Obteve erro %d durante COMMIT",
"Obteve erro %d durante ROLLBACK",
"Obteve erro %d durante FLUSH_LOGS",
"Obteve erro %d durante CHECKPOINT",
-"Conexão %ld abortada ao banco de dados '%-.64s' - usuário '%-.32s' - 'host' `%-.64s' ('%-.64s')",
-"O manipulador de tabela não suporta DUMP binário de tabela",
+"Conexão %ld abortada para banco de dados '%-.64s' - usuário '%-.32s' - 'host' `%-.64s' ('%-.64s')",
+"O manipulador de tabela não suporta 'dump' binário de tabela",
"Binlog fechado. Não pode fazer RESET MASTER",
-"Falhou na reconstrução do índice da tabela '%-.64s' 'dumped'",
+"Falhou na reconstrução do índice da tabela 'dumped' '%-.64s'",
"Erro no 'master' '%-.64s'",
-"Erro de rede na leitura do 'master'",
-"Erro de rede na gravação do 'master'",
-"Não pode encontrar índice FULLTEXT que combine com a lista de colunas",
-"Não pode executar o comando dado porque você tem tabelas ativas travadas ou uma 'transaction' ativa",
-"Variável de sistema '%-.64s' desconhecida",
+"Erro de rede lendo do 'master'",
+"Erro de rede gravando no 'master'",
+"Não pode encontrar um índice para o texto todo que combine com a lista de colunas",
+"Não pode executar o comando dado porque você tem tabelas ativas travadas ou uma transação ativa",
+"Variável de sistema '%-.64' desconhecida",
"Tabela '%-.64s' está marcada como danificada e deve ser reparada",
"Tabela '%-.64s' está marcada como danificada e a última reparação (automática?) falhou",
-"Aviso: Algumas tabelas não-transacionais alteradas não puderam ser reconstituídas ('rolled back')",
-"'Multi-statement transaction' requereu mais do que 'max_binlog_cache_size' bytes de armazenagem. Aumente o valor desta variável do mysqld e tente novamente',
+"Aviso: Algumas tabelas não-transacionais alteradas não puderam ser reconstituídas (rolled back)",
+"Transações multi-declaradas (multi-statement transactions) requeriram mais do que o valor limite (max_binlog_cache_size) de bytes para armazenagem. Aumente o valor desta variável do mysqld e tente novamente",
"Esta operação não pode ser realizada com um 'slave' em execução. Execute SLAVE STOP primeiro",
"Esta operação requer um 'slave' em execução. Configure o 'slave' e execute SLAVE START",
"O servidor não está configurado como 'slave'. Acerte o arquivo de configuração ou use CHANGE MASTER TO",
"Não pode inicializar a estrutura de informação do 'master'. Verifique as permissões em 'master.info'",
"Não conseguiu criar 'thread' de 'slave'. Verifique os recursos do sistema",
-"Usuário '%-.64s' já possui 'max_user_connections' conexões ativas",
-"Você pode usar apenas expressões de constante com SET",
-"Excedido tempo de espera (timeout) do travamento",
+"Usuário '%-.64s' já possui mais que o valor máximo de conexões (max_user_connections) ativas",
+"Você pode usar apenas expressões constantes com SET",
+"Tempo de espera (timeout) de travamento excedido. Tente reiniciar a transação.",
"O número total de travamentos excede o tamanho da tabela de travamentos",
-"Travamentos de atualização não podem ser obtidos durante uma transação de READ UNCOMMITTED",
+"Travamentos de atualização não podem ser obtidos durante uma transação de tipo READ UNCOMMITTED",
"DROP DATABASE não permitido enquanto uma 'thread' está mantendo um travamento global de leitura",
"CREATE DATABASE não permitido enquanto uma 'thread' está mantendo um travamento global de leitura",
"Argumentos errados para %s",
"Não é permitido a %-.32s@%-.64s criar novos usuários",
-"Incorrect table definition; All MERGE tables must be in the same database",
-"Deadlock found when trying to get lock; Try restarting transaction",
-"The used table type doesn't support FULLTEXT indexes",
-"Cannot add foreign key constraint",
-"Cannot add a child row: a foreign key constraint fails",
-"Cannot delete a parent row: a foreign key constraint fails",
+"Definição incorreta da tabela. Todas as tabelas contidas na junção devem estar no mesmo banco de dados.",
+"Encontrado um travamento fatal (deadlock) quando tentava obter uma trava. Tente reiniciar a transação.",
+"O tipo de tabela utilizado não suporta índices de texto completo (fulltext indexes)",
+"Não pode acrescentar uma restrição de chave estrangeira",
+"Não pode acrescentar uma linha filha: uma restrição de chave estrangeira falhou",
+"Não pode apagar uma linha pai: uma restrição de chave estrangeira falhou",
"Error connecting to master: %-.128s",
"Error running query on master: %-.128s",
"Error when executing command %s: %-.128s",
@@ -228,6 +228,16 @@
"Mixing of transactional and non-transactional tables is disabled",
"Option '%s' used twice in statement",
"User '%-.64s' has exceeded the '%s' resource (current value: %ld)",
+"Access denied. You need the %-.128s privilege for this operation",
+"Variable '%-.64s' is a LOCAL variable and can't be used with SET GLOBAL",
+"Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL",
+"Variable '%-.64s' doesn't have a default value",
+"Variable '%-.64s' can't be set to the value of '%-.64s'",
+"Wrong argument type to variable '%-.64s'",
+"Variable '%-.64s' can only be set, not read",
+"Wrong usage/placement of '%s'",
+"This version of MySQL doesn't yet support '%s'",
+"Got fatal error %d: '%-.128s' from master when reading data from binary log",
"Wrong foreign key definition for '%-.64s': %s",
"Key reference and table reference doesn't match",
"Subselect return more than 1 field",
diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt
index 61ca19a598e..ce237d755d4 100644
--- a/sql/share/romanian/errmsg.txt
+++ b/sql/share/romanian/errmsg.txt
@@ -232,6 +232,16 @@
"Mixing of transactional and non-transactional tables is disabled",
"Option '%s' used twice in statement",
"User '%-.64s' has exceeded the '%s' resource (current value: %ld)",
+"Access denied. You need the %-.128s privilege for this operation",
+"Variable '%-.64s' is a LOCAL variable and can't be used with SET GLOBAL",
+"Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL",
+"Variable '%-.64s' doesn't have a default value",
+"Variable '%-.64s' can't be set to the value of '%-.64s'",
+"Wrong argument type to variable '%-.64s'",
+"Variable '%-.64s' can only be set, not read",
+"Wrong usage/placement of '%s'",
+"This version of MySQL doesn't yet support '%s'",
+"Got fatal error %d: '%-.128s' from master when reading data from binary log",
"Wrong foreign key definition for '%-.64s': %s",
"Key reference and table reference doesn't match",
"Subselect return more than 1 field",
diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt
index 8ce3223ea7a..35b9c8080c2 100644
--- a/sql/share/russian/errmsg.txt
+++ b/sql/share/russian/errmsg.txt
@@ -231,6 +231,16 @@
"ïÄÎÏ×ÒÅÍÅÎÎÏÅ ÉÓÐÏÌØÚÏ×ÁÎÉÅ transactional É non-transactional ÔÁÂÌÉà ÏÔËÌÀÞÅÎÏ",
"ïÐÃÉÑ '%s' ÉÓÐÏÌØÚÏ×ÁÎÁ Ä×ÁÖÄÙ",
"User '%-.64s' has exceeded the '%s' resource (current value: %ld)",
+"Access denied. You need the %-.128s privilege for this operation",
+"Variable '%-.64s' is a LOCAL variable and can't be used with SET GLOBAL",
+"Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL",
+"Variable '%-.64s' doesn't have a default value",
+"Variable '%-.64s' can't be set to the value of '%-.64s'",
+"Wrong argument type to variable '%-.64s'",
+"Variable '%-.64s' can only be set, not read",
+"Wrong usage/placement of '%s'",
+"This version of MySQL doesn't yet support '%s'",
+"Got fatal error %d: '%-.128s' from master when reading data from binary log",
"Wrong foreign key definition for '%-.64s': %s",
"Key reference and table reference doesn't match",
"ðÏÄÚÁÐÒÏÓ ×ÏÚ×ÒÁÝÁÅÔ ÂÏÌÅÅ ÏÄÎÏÇÏ ÐÏÌÑ",
diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt
index 9c0ecc8ca14..9912e4c9191 100644
--- a/sql/share/slovak/errmsg.txt
+++ b/sql/share/slovak/errmsg.txt
@@ -236,6 +236,16 @@
"Mixing of transactional and non-transactional tables is disabled",
"Option '%s' used twice in statement",
"User '%-.64s' has exceeded the '%s' resource (current value: %ld)",
+"Access denied. You need the %-.128s privilege for this operation",
+"Variable '%-.64s' is a LOCAL variable and can't be used with SET GLOBAL",
+"Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL",
+"Variable '%-.64s' doesn't have a default value",
+"Variable '%-.64s' can't be set to the value of '%-.64s'",
+"Wrong argument type to variable '%-.64s'",
+"Variable '%-.64s' can only be set, not read",
+"Wrong usage/placement of '%s'",
+"This version of MySQL doesn't yet support '%s'",
+"Got fatal error %d: '%-.128s' from master when reading data from binary log",
"Wrong foreign key definition for '%-.64s': %s",
"Key reference and table reference doesn't match",
"Subselect return more than 1 field",
diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt
index 2eca37146e4..118970141bc 100644
--- a/sql/share/spanish/errmsg.txt
+++ b/sql/share/spanish/errmsg.txt
@@ -229,6 +229,16 @@
"Mixing of transactional and non-transactional tables is disabled",
"Option '%s' used twice in statement",
"User '%-.64s' has exceeded the '%s' resource (current value: %ld)",
+"Access denied. You need the %-.128s privilege for this operation",
+"Variable '%-.64s' is a LOCAL variable and can't be used with SET GLOBAL",
+"Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL",
+"Variable '%-.64s' doesn't have a default value",
+"Variable '%-.64s' can't be set to the value of '%-.64s'",
+"Wrong argument type to variable '%-.64s'",
+"Variable '%-.64s' can only be set, not read",
+"Wrong usage/placement of '%s'",
+"This version of MySQL doesn't yet support '%s'",
+"Got fatal error %d: '%-.128s' from master when reading data from binary log",
"Wrong foreign key definition for '%-.64s': %s",
"Key reference and table reference doesn't match",
"Subselect return more than 1 field",
diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt
index 557c6e55394..f6553f247b6 100644
--- a/sql/share/swedish/errmsg.txt
+++ b/sql/share/swedish/errmsg.txt
@@ -228,6 +228,16 @@
"Blandning av transaktionella och icke-transaktionella tabeller är inaktiverat",
"Option '%s' användes två gånger",
"Användare '%-.64s' har överskridit '%s' (nuvarande värde: %ld)",
+"Du har inte privlegiet '%-.128s' som behövs för denna operation",
+"Variable '%-.64s' is a LOCAL variable and can't be used with SET GLOBAL",
+"Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL",
+"Variable '%-.64s' doesn't have a default value",
+"Variable '%-.64s' can't be set to the value of '%-.64s'",
+"Wrong argument type to variable '%-.64s'",
+"Variable '%-.64s' can only be set, not read",
+"Wrong usage/placement of '%s'",
+"This version of MySQL doesn't yet support '%s'",
+"Got fatal error %d: '%-.128s' from master when reading data from binary log",
"Wrong foreign key definition for '%-.64s': %s",
"Key reference and table reference doesn't match",
"Subselect return more than 1 field",
diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt
index 2fcb3405729..e37fae8f923 100644
--- a/sql/share/ukrainian/errmsg.txt
+++ b/sql/share/ukrainian/errmsg.txt
@@ -233,6 +233,16 @@
"Mixing of transactional and non-transactional tables is disabled",
"Option '%s' used twice in statement",
"User '%-.64s' has exceeded the '%s' resource (current value: %ld)",
+"Access denied. You need the %-.128s privilege for this operation",
+"Variable '%-.64s' is a LOCAL variable and can't be used with SET GLOBAL",
+"Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL",
+"Variable '%-.64s' doesn't have a default value",
+"Variable '%-.64s' can't be set to the value of '%-.64s'",
+"Wrong argument type to variable '%-.64s'",
+"Variable '%-.64s' can only be set, not read",
+"Wrong usage/placement of '%s'",
+"This version of MySQL doesn't yet support '%s'",
+"Got fatal error %d: '%-.128s' from master when reading data from binary log",
"Wrong foreign key definition for '%-.64s': %s",
"Key reference and table reference doesn't match",
"ðiÄÚÁÐÉÔ ÐÏ×ÅÒÔÁ¤ ÂiÌØÛ ÎiÖ 1 ÓÔÏ×ÂÅÃØ",
diff --git a/sql/slave.cc b/sql/slave.cc
index 2673644b65a..01f6233a2e0 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -41,63 +41,62 @@ DYNAMIC_ARRAY replicate_wild_do_table, replicate_wild_ignore_table;
bool do_table_inited = 0, ignore_table_inited = 0;
bool wild_do_table_inited = 0, wild_ignore_table_inited = 0;
bool table_rules_on = 0;
-static TABLE* save_temporary_tables = 0;
-ulong relay_log_space_limit = 0; /* TODO: fix variables to access ulonglong
- values and make it ulonglong */
-// when slave thread exits, we need to remember the temporary tables so we
-// can re-use them on slave start
+ulonglong relay_log_space_limit = 0;
+
+/*
+ When slave thread exits, we need to remember the temporary tables so we
+ can re-use them on slave start.
+
+ TODO: move the vars below under MASTER_INFO
+*/
-// TODO: move the vars below under MASTER_INFO
int disconnect_slave_event_count = 0, abort_slave_event_count = 0;
-static int events_till_disconnect = -1;
int events_till_abort = -1;
-static int stuck_count = 0;
+static int events_till_disconnect = -1;
typedef enum { SLAVE_THD_IO, SLAVE_THD_SQL} SLAVE_THD_TYPE;
void skip_load_data_infile(NET* net);
static int process_io_rotate(MASTER_INFO* mi, Rotate_log_event* rev);
static int process_io_create_file(MASTER_INFO* mi, Create_file_log_event* cev);
-static int queue_old_event(MASTER_INFO* mi, const char* buf,
- uint event_len);
static bool wait_for_relay_log_space(RELAY_LOG_INFO* rli);
static inline bool io_slave_killed(THD* thd,MASTER_INFO* mi);
static inline bool sql_slave_killed(THD* thd,RELAY_LOG_INFO* rli);
static int count_relay_log_space(RELAY_LOG_INFO* rli);
static int init_slave_thread(THD* thd, SLAVE_THD_TYPE thd_type);
static int safe_connect(THD* thd, MYSQL* mysql, MASTER_INFO* mi);
-static int safe_reconnect(THD* thd, MYSQL* mysql, MASTER_INFO* mi);
+static int safe_reconnect(THD* thd, MYSQL* mysql, MASTER_INFO* mi,
+ bool suppress_warnings);
static int connect_to_master(THD* thd, MYSQL* mysql, MASTER_INFO* mi,
- bool reconnect);
+ bool reconnect, bool suppress_warnings);
static int safe_sleep(THD* thd, int sec, CHECK_KILLED_FUNC thread_killed,
void* thread_killed_arg);
static int request_table_dump(MYSQL* mysql, const char* db, const char* table);
static int create_table_from_dump(THD* thd, NET* net, const char* db,
const char* table_name);
static int check_master_version(MYSQL* mysql, MASTER_INFO* mi);
-
char* rewrite_db(char* db);
+
+/*
+ Get a bit mask for which threads are running so that we later can
+ restart these threads
+*/
+
void init_thread_mask(int* mask,MASTER_INFO* mi,bool inverse)
{
bool set_io = mi->slave_running, set_sql = mi->rli.slave_running;
- if (inverse)
- {
- /* This makes me think of the Russian idiom "I am not I, and this is
- not my horse", which is used to deny reponsibility for
- one's actions.
- */
- set_io = !set_io;
- set_sql = !set_sql;
- }
register int tmp_mask=0;
if (set_io)
tmp_mask |= SLAVE_IO;
if (set_sql)
tmp_mask |= SLAVE_SQL;
+ if (inverse)
+ tmp_mask^= (SLAVE_IO | SLAVE_SQL);
*mask = tmp_mask;
}
+
void lock_slave_threads(MASTER_INFO* mi)
{
//TODO: see if we can do this without dual mutex
@@ -112,45 +111,50 @@ void unlock_slave_threads(MASTER_INFO* mi)
pthread_mutex_unlock(&mi->run_lock);
}
+
int init_slave()
{
- // TODO (multi-master): replace this with list initialization
+ DBUG_ENTER("init_slave");
+
+ /*
+ TODO: re-write this to interate through the list of files
+ for multi-master
+ */
active_mi = &main_mi;
- // TODO: the code below is a copy-paste mess - clean it up
+ /*
+ If master_host is not specified, try to read it from the master_info file.
+ If master_host is specified, create the master_info file if it doesn't
+ exists.
+ */
+ if (init_master_info(active_mi,master_info_file,relay_log_info_file,
+ !master_host))
+ {
+ sql_print_error("Warning: failed to initialized master info");
+ DBUG_RETURN(0);
+ }
+
/*
make sure slave thread gets started if server_id is set,
valid master.info is present, and master_host has not been specified
*/
- if (server_id && !master_host)
- {
- // TODO: re-write this to interate through the list of files
- // for multi-master
- char fname[FN_REFLEN+128];
- MY_STAT stat_area;
- fn_format(fname, master_info_file, mysql_data_home, "", 4+16+32);
- if (my_stat(fname, &stat_area, MYF(0)) &&
- !init_master_info(active_mi,master_info_file,relay_log_info_file))
- master_host = active_mi->host;
- }
- // slave thread
- if (master_host)
- {
- if (!opt_skip_slave_start && start_slave_threads(1 /* need mutex */,
- 0 /* no wait for start*/,
- active_mi,
- master_info_file,
- relay_log_info_file,
- SLAVE_IO|SLAVE_SQL
- ))
+ if (server_id && !master_host && active_mi->host[0])
+ master_host= active_mi->host;
+
+ if (master_host && !opt_skip_slave_start)
+ {
+ if (start_slave_threads(1 /* need mutex */,
+ 0 /* no wait for start*/,
+ active_mi,
+ master_info_file,
+ relay_log_info_file,
+ SLAVE_IO | SLAVE_SQL))
sql_print_error("Warning: Can't create threads to handle slave");
- else if (opt_skip_slave_start)
- if (init_master_info(active_mi, master_info_file, relay_log_info_file))
- sql_print_error("Warning: failed to initialized master info");
}
- return 0;
+ DBUG_RETURN(0);
}
+
static void free_table_ent(TABLE_RULE_ENT* e)
{
my_free((gptr) e, MYF(0));
@@ -163,19 +167,51 @@ static byte* get_table_key(TABLE_RULE_ENT* e, uint* len,
return (byte*)e->db;
}
-// TODO: check proper initialization of master_log_name/master_log_pos
+
+/*
+ Open the given relay log
+
+ SYNOPSIS
+ init_relay_log_pos()
+ rli Relay information (will be initialized)
+ log Name of relay log file to read from. NULL = First log
+ pos Position in relay log file
+ need_data_lock Set to 1 if this functions should do mutex locks
+ errmsg Store pointer to error message here
+
+ DESCRIPTION
+ - Close old open relay log files.
+ - If we are using the same relay log as the running IO-thread, then set
+ rli->cur_log to point to the same IO_CACHE entry.
+ - If not, open the 'log' binary file.
+
+ TODO
+ - check proper initialization of master_log_name/master_log_pos
+ - We may always want to delete all logs before 'log'.
+ Currently if we are not calling this with 'log' as NULL or the first
+ log we will never delete relay logs.
+ If we want this we should not set skip_log_purge to 1.
+
+ RETURN VALUES
+ 0 ok
+ 1 error. errmsg is set to point to the error message
+*/
+
int init_relay_log_pos(RELAY_LOG_INFO* rli,const char* log,
ulonglong pos, bool need_data_lock,
const char** errmsg)
{
+ DBUG_ENTER("init_relay_log_pos");
+
*errmsg=0;
- if (rli->log_pos_current)
- return 0;
+ if (rli->log_pos_current) // TODO: When can this happen ?
+ DBUG_RETURN(0);
pthread_mutex_t *log_lock=rli->relay_log.get_log_lock();
pthread_mutex_lock(log_lock);
if (need_data_lock)
pthread_mutex_lock(&rli->data_lock);
+ /* Close log file and free buffers if it's already open */
if (rli->cur_log_fd >= 0)
{
end_io_cache(&rli->cache_buf);
@@ -183,72 +219,70 @@ int init_relay_log_pos(RELAY_LOG_INFO* rli,const char* log,
rli->cur_log_fd = -1;
}
- if (!log)
- log = rli->relay_log_name; // already inited
- if (!pos)
- pos = rli->relay_log_pos; // already inited
- else
- rli->relay_log_pos = pos;
+ rli->relay_log_pos = pos;
- // test to see if the previous run was with the skip of purging
- // if yes, we do not purge when we restart
- if (rli->relay_log.find_first_log(&rli->linfo,""))
+ /*
+ Test to see if the previous run was with the skip of purging
+ If yes, we do not purge when we restart
+ */
+ if (rli->relay_log.find_log_pos(&rli->linfo, NullS, 1))
{
*errmsg="Could not find first log during relay log initialization";
goto err;
}
- if (strcmp(log,rli->linfo.log_file_name))
- rli->skip_log_purge=1;
-
- if (rli->relay_log.find_first_log(&rli->linfo,log))
+
+ if (log) // If not first log
{
- *errmsg="Could not find target log during relay log initialization";
- goto err;
+ if (strcmp(log, rli->linfo.log_file_name))
+ rli->skip_log_purge=1; // Different name; Don't purge
+ if (rli->relay_log.find_log_pos(&rli->linfo, log, 1))
+ {
+ *errmsg="Could not find target log during relay log initialization";
+ goto err;
+ }
}
- strnmov(rli->relay_log_name,rli->linfo.log_file_name,
- sizeof(rli->relay_log_name));
- // to make end_io_cache(&rli->cache_buf) safe in all cases
- if (!rli->inited)
- bzero((char*) &rli->cache_buf, sizeof(IO_CACHE));
+ strmake(rli->relay_log_name,rli->linfo.log_file_name,
+ sizeof(rli->relay_log_name)-1);
if (rli->relay_log.is_active(rli->linfo.log_file_name))
{
+ /*
+ The IO thread is using this log file.
+ In this case, we will use the same IO_CACHE pointer to
+ read data as the IO thread is using to write data.
+ */
if (my_b_tell((rli->cur_log=rli->relay_log.get_log_file())) == 0 &&
- check_binlog_magic(rli->cur_log,errmsg))
- {
+ check_binlog_magic(rli->cur_log,errmsg))
goto err;
- }
- rli->cur_log_init_count=rli->cur_log->init_count;
+ rli->cur_log_old_open_count=rli->relay_log.get_open_count();
}
else
{
- if (rli->inited)
- end_io_cache(&rli->cache_buf);
- if (rli->cur_log_fd>=0)
- my_close(rli->cur_log_fd,MYF(MY_WME));
+ /*
+ Open the relay log and set rli->cur_log to point at this one
+ */
if ((rli->cur_log_fd=open_binlog(&rli->cache_buf,
rli->linfo.log_file_name,errmsg)) < 0)
- {
goto err;
- }
rli->cur_log = &rli->cache_buf;
}
- if (pos > 4)
- my_b_seek(rli->cur_log,(off_t)pos);
- rli->log_pos_current=1;
+ if (pos > BIN_LOG_HEADER_SIZE)
+ my_b_seek(rli->cur_log,(off_t)pos);
+ rli->log_pos_current=1;
+
err:
- pthread_cond_broadcast(&rli->data_cond);
- if (need_data_lock)
- pthread_mutex_unlock(&rli->data_lock);
- pthread_mutex_unlock(log_lock);
- return (*errmsg) ? 1 : 0;
+ pthread_cond_broadcast(&rli->data_cond);
+ if (need_data_lock)
+ pthread_mutex_unlock(&rli->data_lock);
+ pthread_mutex_unlock(log_lock);
+ DBUG_RETURN ((*errmsg) ? 1 : 0);
}
+
/* called from get_options() in mysqld.cc on start-up */
void init_slave_skip_errors(const char* arg)
{
const char *p;
- my_bool last_was_digit = 0;
if (bitmap_init(&slave_error_mask,MAX_SLAVE_ERROR,0))
{
fprintf(stderr, "Badly out of memory, please check your system status\n");
@@ -274,48 +308,56 @@ void init_slave_skip_errors(const char* arg)
}
}
+
/*
- We assume we have a run lock on rli and that the both slave thread
+ We assume we have a run lock on rli and that both slave thread
are not running
*/
-int purge_relay_logs(RELAY_LOG_INFO* rli, bool just_reset, const char** errmsg)
+int purge_relay_logs(RELAY_LOG_INFO* rli, THD *thd, bool just_reset,
+ const char** errmsg)
{
+ int error=0;
DBUG_ENTER("purge_relay_logs");
if (!rli->inited)
DBUG_RETURN(0); /* successfully do nothing */
+
DBUG_ASSERT(rli->slave_running == 0);
DBUG_ASSERT(rli->mi->slave_running == 0);
- int error=0;
+
rli->slave_skip_counter=0;
pthread_mutex_lock(&rli->data_lock);
rli->pending=0;
rli->master_log_name[0]=0;
rli->master_log_pos=0; // 0 means uninitialized
- if (rli->relay_log.reset_logs(rli->sql_thd) ||
- rli->relay_log.find_first_log(&rli->linfo,""))
+ if (rli->relay_log.reset_logs(thd))
{
*errmsg = "Failed during log reset";
error=1;
goto err;
}
- strnmov(rli->relay_log_name,rli->linfo.log_file_name,
+ /* Save name of used relay log file */
+ strmake(rli->relay_log_name, rli->relay_log.get_log_fname(),
sizeof(rli->relay_log_name)-1);
- rli->log_space_total=4; //just first log with magic number and nothing else
- rli->relay_log_pos=4;
+ // Just first log with magic number and nothing else
+ rli->log_space_total= BIN_LOG_HEADER_SIZE;
+ rli->relay_log_pos= BIN_LOG_HEADER_SIZE;
rli->relay_log.reset_bytes_written();
rli->log_pos_current=0;
if (!just_reset)
- error = init_relay_log_pos(rli,0,0,0/*do not need data lock*/,errmsg);
+ error= init_relay_log_pos(rli, rli->relay_log_name, rli->relay_log_pos,
+ 0 /* do not need data lock */, errmsg);
+
err:
#ifndef DBUG_OFF
char buf[22];
#endif
- DBUG_PRINT("info",("log_space_total=%s",llstr(rli->log_space_total,buf)));
+ DBUG_PRINT("info",("log_space_total: %s",llstr(rli->log_space_total,buf)));
pthread_mutex_unlock(&rli->data_lock);
DBUG_RETURN(error);
}
+
int terminate_slave_threads(MASTER_INFO* mi,int thread_mask,bool skip_lock)
{
if (!mi->inited)
@@ -323,6 +365,7 @@ int terminate_slave_threads(MASTER_INFO* mi,int thread_mask,bool skip_lock)
int error,force_all = (thread_mask & SLAVE_FORCE_ALL);
pthread_mutex_t *sql_lock = &mi->rli.run_lock, *io_lock = &mi->run_lock;
pthread_mutex_t *sql_cond_lock,*io_cond_lock;
+ DBUG_ENTER("terminate_slave_threads");
sql_cond_lock=sql_lock;
io_cond_lock=io_lock;
@@ -339,7 +382,7 @@ int terminate_slave_threads(MASTER_INFO* mi,int thread_mask,bool skip_lock)
&mi->stop_cond,
&mi->slave_running)) &&
!force_all)
- return error;
+ DBUG_RETURN(error);
}
if ((thread_mask & (SLAVE_SQL|SLAVE_FORCE_ALL)) && mi->rli.slave_running)
{
@@ -350,11 +393,12 @@ int terminate_slave_threads(MASTER_INFO* mi,int thread_mask,bool skip_lock)
&mi->rli.stop_cond,
&mi->rli.slave_running)) &&
!force_all)
- return error;
+ DBUG_RETURN(error);
}
- return 0;
+ DBUG_RETURN(0);
}
+
int terminate_slave_thread(THD* thd, pthread_mutex_t* term_lock,
pthread_mutex_t *cond_lock,
pthread_cond_t* term_cond,
@@ -370,8 +414,9 @@ int terminate_slave_thread(THD* thd, pthread_mutex_t* term_lock,
}
}
DBUG_ASSERT(thd != 0);
- /* is is criticate to test if the slave is running. Otherwise, we might
- be referening freed memory trying to kick it
+ /*
+ Is is criticate to test if the slave is running. Otherwise, we might
+ be referening freed memory trying to kick it
*/
THD_CHECK_SENTRY(thd);
if (*slave_running)
@@ -380,23 +425,12 @@ int terminate_slave_thread(THD* thd, pthread_mutex_t* term_lock,
}
while (*slave_running)
{
- /* there is a small chance that slave thread might miss the first
- alarm. To protect againts it, resend the signal until it reacts
+ /*
+ There is a small chance that slave thread might miss the first
+ alarm. To protect againts it, resend the signal until it reacts
*/
struct timespec abstime;
-#ifdef HAVE_TIMESPEC_TS_SEC
- abstime.ts_sec=time(NULL)+2;
- abstime.ts_nsec=0;
-#elif defined(__WIN__)
- abstime.tv_sec=time((time_t*) 0)+2;
- abstime.tv_nsec=0;
-#else
- struct timeval tv;
- gettimeofday(&tv,0);
- abstime.tv_sec=tv.tv_sec+2;
- abstime.tv_nsec=tv.tv_usec*1000;
-#endif
- DBUG_ASSERT_LOCK(cond_lock);
+ set_timespec(abstime,2);
pthread_cond_timedwait(term_cond, cond_lock, &abstime);
if (*slave_running)
{
@@ -408,14 +442,19 @@ int terminate_slave_thread(THD* thd, pthread_mutex_t* term_lock,
return 0;
}
-int start_slave_thread(pthread_handler h_func, pthread_mutex_t* start_lock,
+
+int start_slave_thread(pthread_handler h_func, pthread_mutex_t *start_lock,
pthread_mutex_t *cond_lock,
- pthread_cond_t* start_cond,
- volatile bool* slave_running,
+ pthread_cond_t *start_cond,
+ volatile bool *slave_running,
+ volatile ulong *slave_run_id,
MASTER_INFO* mi)
{
pthread_t th;
+ ulong start_id;
DBUG_ASSERT(mi->inited);
+ DBUG_ENTER("start_slave_thread");
+
if (start_lock)
pthread_mutex_lock(start_lock);
if (!server_id)
@@ -425,51 +464,54 @@ int start_slave_thread(pthread_handler h_func, pthread_mutex_t* start_lock,
if (start_lock)
pthread_mutex_unlock(start_lock);
sql_print_error("Server id not set, will not start slave");
- return ER_BAD_SLAVE;
+ DBUG_RETURN(ER_BAD_SLAVE);
}
if (*slave_running)
- {
- if (start_cond)
- pthread_cond_broadcast(start_cond);
- if (start_lock)
- pthread_mutex_unlock(start_lock);
- return ER_SLAVE_MUST_STOP;
- }
+ {
+ if (start_cond)
+ pthread_cond_broadcast(start_cond);
+ if (start_lock)
+ pthread_mutex_unlock(start_lock);
+ DBUG_RETURN(ER_SLAVE_MUST_STOP);
+ }
+ start_id= *slave_run_id;
+ DBUG_PRINT("info",("Creating new slave thread"));
if (pthread_create(&th, &connection_attrib, h_func, (void*)mi))
{
if (start_lock)
pthread_mutex_unlock(start_lock);
- return ER_SLAVE_THREAD;
+ DBUG_RETURN(ER_SLAVE_THREAD);
}
if (start_cond && cond_lock)
{
THD* thd = current_thd;
- while (!*slave_running)
+ while (start_id == *slave_run_id)
{
+ DBUG_PRINT("sleep",("Waiting for slave thread to start"));
const char* old_msg = thd->enter_cond(start_cond,cond_lock,
- "Waiting for slave thread to start");
+ "Waiting for slave thread to start");
pthread_cond_wait(start_cond,cond_lock);
thd->exit_cond(old_msg);
- // TODO: in a very rare case of init_slave_thread failing, it is
- // possible that we can get stuck here since slave_running will not
- // be set. We need to change slave_running to int and have -1 as
- // error code
if (thd->killed)
{
pthread_mutex_unlock(cond_lock);
- return ER_SERVER_SHUTDOWN;
+ DBUG_RETURN(ER_SERVER_SHUTDOWN);
}
}
}
if (start_lock)
pthread_mutex_unlock(start_lock);
- return 0;
+ DBUG_RETURN(0);
}
-/* SLAVE_FORCE_ALL is not implemented here on purpose since it does not make
- sense to do that for starting a slave - we always care if it actually
- started the threads that were not previously running
+
+
+/*
+ SLAVE_FORCE_ALL is not implemented here on purpose since it does not make
+ sense to do that for starting a slave - we always care if it actually
+ started the threads that were not previously running
*/
+
int start_slave_threads(bool need_slave_mutex, bool wait_for_start,
MASTER_INFO* mi, const char* master_info_fname,
const char* slave_info_fname, int thread_mask)
@@ -477,6 +519,7 @@ int start_slave_threads(bool need_slave_mutex, bool wait_for_start,
pthread_mutex_t *lock_io=0,*lock_sql=0,*lock_cond_io=0,*lock_cond_sql=0;
pthread_cond_t* cond_io=0,*cond_sql=0;
int error=0;
+ DBUG_ENTER("start_slave_threads");
if (need_slave_mutex)
{
@@ -490,22 +533,25 @@ int start_slave_threads(bool need_slave_mutex, bool wait_for_start,
lock_cond_io = &mi->run_lock;
lock_cond_sql = &mi->rli.run_lock;
}
- if (init_master_info(mi,master_info_fname,slave_info_fname))
- return ER_MASTER_INFO;
-
- if ((thread_mask & SLAVE_IO) &&
- (error=start_slave_thread(handle_slave_io,lock_io,lock_cond_io,
- cond_io,&mi->slave_running,
- mi)))
- return error;
- if ((thread_mask & SLAVE_SQL) &&
- (error=start_slave_thread(handle_slave_sql,lock_sql,lock_cond_sql,
- cond_sql,
- &mi->rli.slave_running,mi)))
- return error;
- return 0;
+
+ if (thread_mask & SLAVE_IO)
+ error=start_slave_thread(handle_slave_io,lock_io,lock_cond_io,
+ cond_io,
+ &mi->slave_running, &mi->slave_run_id,
+ mi);
+ if (!error && (thread_mask & SLAVE_SQL))
+ {
+ error=start_slave_thread(handle_slave_sql,lock_sql,lock_cond_sql,
+ cond_sql,
+ &mi->rli.slave_running, &mi->rli.slave_run_id,
+ mi);
+ if (error)
+ terminate_slave_threads(mi, thread_mask & SLAVE_IO, 0);
+ }
+ DBUG_RETURN(error);
}
+
void init_table_rule_hash(HASH* h, bool* h_inited)
{
hash_init(h, system_charset_info,TABLE_RULE_HASH_SIZE,0,0,
@@ -568,9 +614,10 @@ int tables_ok(THD* thd, TABLE_LIST* tables)
return 0;
}
- // if no explicit rule found
- // and there was a do list, do not replicate. If there was
- // no do list, go ahead
+ /*
+ If no explicit rule found and there was a do list, do not replicate.
+ If there was no do list, go ahead
+ */
return !do_table_inited && !wild_do_table_inited;
}
@@ -578,12 +625,12 @@ int tables_ok(THD* thd, TABLE_LIST* tables)
int add_table_rule(HASH* h, const char* table_spec)
{
const char* dot = strchr(table_spec, '.');
- if(!dot) return 1;
+ if (!dot) return 1;
// len is always > 0 because we know the there exists a '.'
uint len = (uint)strlen(table_spec);
TABLE_RULE_ENT* e = (TABLE_RULE_ENT*)my_malloc(sizeof(TABLE_RULE_ENT)
+ len, MYF(MY_WME));
- if(!e) return 1;
+ if (!e) return 1;
e->db = (char*)e + sizeof(TABLE_RULE_ENT);
e->tbl_name = e->db + (dot - table_spec) + 1;
e->key_len = len;
@@ -595,11 +642,11 @@ int add_table_rule(HASH* h, const char* table_spec)
int add_wild_table_rule(DYNAMIC_ARRAY* a, const char* table_spec)
{
const char* dot = strchr(table_spec, '.');
- if(!dot) return 1;
+ if (!dot) return 1;
uint len = (uint)strlen(table_spec);
TABLE_RULE_ENT* e = (TABLE_RULE_ENT*)my_malloc(sizeof(TABLE_RULE_ENT)
+ len, MYF(MY_WME));
- if(!e) return 1;
+ if (!e) return 1;
e->db = (char*)e + sizeof(TABLE_RULE_ENT);
e->tbl_name = e->db + (dot - table_spec) + 1;
e->key_len = len;
@@ -611,7 +658,7 @@ int add_wild_table_rule(DYNAMIC_ARRAY* a, const char* table_spec)
static void free_string_array(DYNAMIC_ARRAY *a)
{
uint i;
- for(i = 0; i < a->elements; i++)
+ for (i = 0; i < a->elements; i++)
{
char* p;
get_dynamic(a, (gptr) &p, i);
@@ -620,17 +667,22 @@ static void free_string_array(DYNAMIC_ARRAY *a)
delete_dynamic(a);
}
+#ifdef NOT_USED_YET
+
static int end_slave_on_walk(MASTER_INFO* mi, gptr /*unused*/)
{
end_master_info(mi);
return 0;
}
+#endif
void end_slave()
{
- // TODO: replace the line below with
- // list_walk(&master_list, (list_walk_action)end_slave_on_walk,0);
- // once multi-master code is ready
+ /*
+ TODO: replace the line below with
+ list_walk(&master_list, (list_walk_action)end_slave_on_walk,0);
+ once multi-master code is ready.
+ */
terminate_slave_threads(active_mi,SLAVE_FORCE_ALL);
end_master_info(active_mi);
if (do_table_inited)
@@ -643,6 +695,7 @@ void end_slave()
free_string_array(&replicate_wild_ignore_table);
}
+
static bool io_slave_killed(THD* thd, MASTER_INFO* mi)
{
DBUG_ASSERT(mi->io_thd == thd);
@@ -650,6 +703,7 @@ static bool io_slave_killed(THD* thd, MASTER_INFO* mi)
return mi->abort_slave || abort_loop || thd->killed;
}
+
static bool sql_slave_killed(THD* thd, RELAY_LOG_INFO* rli)
{
DBUG_ASSERT(rli->sql_thd == thd);
@@ -657,6 +711,7 @@ static bool sql_slave_killed(THD* thd, RELAY_LOG_INFO* rli)
return rli->abort_slave || abort_loop || thd->killed;
}
+
void slave_print_error(RELAY_LOG_INFO* rli, int err_code, const char* msg, ...)
{
va_list args;
@@ -668,69 +723,74 @@ void slave_print_error(RELAY_LOG_INFO* rli, int err_code, const char* msg, ...)
rli->last_slave_errno = err_code;
}
+
void skip_load_data_infile(NET* net)
{
(void)my_net_write(net, "\xfb/dev/null", 10);
(void)net_flush(net);
- (void)my_net_read(net); // discard response
- send_ok(net); // the master expects it
+ (void)my_net_read(net); // discard response
+ send_ok(net); // the master expects it
}
+
char* rewrite_db(char* db)
{
- if(replicate_rewrite_db.is_empty() || !db) return db;
+ if (replicate_rewrite_db.is_empty() || !db)
+ return db;
I_List_iterator<i_string_pair> it(replicate_rewrite_db);
i_string_pair* tmp;
- while((tmp=it++))
- {
- if(!strcmp(tmp->key, db))
- return tmp->val;
- }
-
+ while ((tmp=it++))
+ {
+ if (!strcmp(tmp->key, db))
+ return tmp->val;
+ }
return db;
}
+
int db_ok(const char* db, I_List<i_string> &do_list,
I_List<i_string> &ignore_list )
{
if (do_list.is_empty() && ignore_list.is_empty())
return 1; // ok to replicate if the user puts no constraints
- // if the user has specified restrictions on which databases to replicate
- // and db was not selected, do not replicate
- if(!db)
+ /*
+ If the user has specified restrictions on which databases to replicate
+ and db was not selected, do not replicate.
+ */
+ if (!db)
return 0;
- if(!do_list.is_empty()) // if the do's are not empty
- {
- I_List_iterator<i_string> it(do_list);
- i_string* tmp;
+ if (!do_list.is_empty()) // if the do's are not empty
+ {
+ I_List_iterator<i_string> it(do_list);
+ i_string* tmp;
- while((tmp=it++))
- {
- if(!strcmp(tmp->ptr, db))
- return 1; // match
- }
- return 0;
+ while ((tmp=it++))
+ {
+ if (!strcmp(tmp->ptr, db))
+ return 1; // match
}
+ return 0;
+ }
else // there are some elements in the don't, otherwise we cannot get here
- {
- I_List_iterator<i_string> it(ignore_list);
- i_string* tmp;
+ {
+ I_List_iterator<i_string> it(ignore_list);
+ i_string* tmp;
- while((tmp=it++))
- {
- if(!strcmp(tmp->ptr, db))
- return 0; // match
- }
-
- return 1;
+ while ((tmp=it++))
+ {
+ if (!strcmp(tmp->ptr, db))
+ return 0; // match
}
+ return 1;
+ }
}
-static int init_strvar_from_file(char* var, int max_size, IO_CACHE* f,
- char* default_val)
+
+static int init_strvar_from_file(char *var, int max_size, IO_CACHE *f,
+ const char *default_val)
{
uint length;
if ((length=my_b_gets(f,var, max_size)))
@@ -740,10 +800,12 @@ static int init_strvar_from_file(char* var, int max_size, IO_CACHE* f,
*last_p = 0; // if we stopped on newline, kill it
else
{
- // if we truncated a line or stopped on last char, remove all chars
- // up to and including newline
+ /*
+ If we truncated a line or stopped on last char, remove all chars
+ up to and including newline.
+ */
int c;
- while( ((c=my_b_get(f)) != '\n' && c != my_b_EOF));
+ while (((c=my_b_get(f)) != '\n' && c != my_b_EOF));
}
return 0;
}
@@ -755,6 +817,7 @@ static int init_strvar_from_file(char* var, int max_size, IO_CACHE* f,
return 1;
}
+
static int init_intvar_from_file(int* var, IO_CACHE* f, int default_val)
{
char buf[32];
@@ -764,7 +827,7 @@ static int init_intvar_from_file(int* var, IO_CACHE* f, int default_val)
*var = atoi(buf);
return 0;
}
- else if(default_val)
+ else if (default_val)
{
*var = default_val;
return 0;
@@ -772,46 +835,24 @@ static int init_intvar_from_file(int* var, IO_CACHE* f, int default_val)
return 1;
}
+
static int check_master_version(MYSQL* mysql, MASTER_INFO* mi)
{
- MYSQL_RES* res;
- MYSQL_ROW row;
- const char* version;
- const char* errmsg = 0;
+ const char* errmsg= 0;
- if (mc_mysql_query(mysql, "SELECT VERSION()", 0)
- || !(res = mc_mysql_store_result(mysql)))
- {
- sql_print_error("Error checking master version: %s",
- mc_mysql_error(mysql));
- return 1;
- }
- if (!(row = mc_mysql_fetch_row(res)))
- {
- errmsg = "Master returned no rows for SELECT VERSION()";
- goto err;
- }
- if (!(version = row[0]))
- {
- errmsg = "Master reported NULL for the version";
- goto err;
- }
-
- switch (*version)
- {
+ switch (*mysql->server_version) {
case '3':
mi->old_format = 1;
break;
case '4':
+ case '5':
mi->old_format = 0;
break;
default:
errmsg = "Master reported unrecognized MySQL version";
- goto err;
+ break;
}
-err:
- if (res)
- mc_mysql_free_result(res);
+
if (errmsg)
{
sql_print_error(errmsg);
@@ -830,7 +871,7 @@ static int create_table_from_dump(THD* thd, NET* net, const char* db,
TABLE_LIST tables;
int error= 1;
handler *file;
- uint save_options;
+ ulong save_options;
if (packet_len == packet_error)
{
@@ -859,7 +900,7 @@ static int create_table_from_dump(THD* thd, NET* net, const char* db,
/* we do not want to log create table statement */
save_options = thd->options;
- thd->options &= ~OPTION_BIN_LOG;
+ thd->options &= ~(ulong) (OPTION_BIN_LOG);
thd->proc_info = "Creating table from master dump";
// save old db in case we are creating in a different database
char* save_db = thd->db;
@@ -896,9 +937,11 @@ static int create_table_from_dump(THD* thd, NET* net, const char* db,
check_opt.init();
check_opt.flags|= T_VERY_SILENT | T_CALC_CHECKSUM | T_QUICK;
thd->proc_info = "Rebuilding the index on master dump table";
- // we do not want repair() to spam us with messages
- // just send them to the error log, and report the failure in case of
- // problems
+ /*
+ We do not want repair() to spam us with messages
+ just send them to the error log, and report the failure in case of
+ problems.
+ */
save_vio = thd->net.vio;
thd->net.vio = 0;
error=file->repair(thd,&check_opt) != 0;
@@ -912,82 +955,84 @@ err:
return error;
}
-int fetch_master_table(THD* thd, const char* db_name, const char* table_name,
- MASTER_INFO* mi, MYSQL* mysql)
+int fetch_master_table(THD *thd, const char *db_name, const char *table_name,
+ MASTER_INFO *mi, MYSQL *mysql)
{
- int error = 1;
- int fetch_errno = 0;
- bool called_connected = (mysql != NULL);
- if (!called_connected && !(mysql = mc_mysql_init(NULL)))
- {
- sql_print_error("fetch_master_table: Error in mysql_init()");
- fetch_errno = ER_GET_ERRNO;
- goto err;
- }
+ int error= 1;
+ const char *errmsg=0;
+ bool called_connected= (mysql != NULL);
+ DBUG_ENTER("fetch_master_table");
+ DBUG_PRINT("enter", ("db_name: '%s' table_name: '%s'",
+ db_name,table_name));
if (!called_connected)
- {
+ {
+ if (!(mysql = mc_mysql_init(NULL)))
+ {
+ send_error(&thd->net); // EOM
+ DBUG_RETURN(1);
+ }
if (connect_to_master(thd, mysql, mi))
{
- sql_print_error("Could not connect to master while fetching table\
- '%-64s.%-64s'", db_name, table_name);
- fetch_errno = ER_CONNECT_TO_MASTER;
- goto err;
+ net_printf(&thd->net, ER_CONNECT_TO_MASTER, mc_mysql_error(mysql));
+ mc_mysql_close(mysql);
+ DBUG_RETURN(1);
}
+ if (thd->killed)
+ goto err;
}
- if (thd->killed)
- goto err;
if (request_table_dump(mysql, db_name, table_name))
{
- fetch_errno = ER_GET_ERRNO;
- sql_print_error("fetch_master_table: failed on table dump request ");
+ error= ER_UNKNOWN_ERROR;
+ errmsg= "Failed on table dump request";
goto err;
}
-
if (create_table_from_dump(thd, &mysql->net, db_name,
table_name))
- {
- // create_table_from_dump will have sent the error alread
- sql_print_error("fetch_master_table: failed on create table ");
- goto err;
- }
+ goto err; // create_table_from_dump will have sent the error already
error = 0;
+
err:
- if (mysql && !called_connected)
- mc_mysql_close(mysql);
- if (fetch_errno && thd->net.vio)
- send_error(&thd->net, fetch_errno, "Error in fetch_master_table");
thd->net.no_send_ok = 0; // Clear up garbage after create_table_from_dump
- return error;
+ if (!called_connected)
+ mc_mysql_close(mysql);
+ if (errmsg && thd->net.vio)
+ send_error(&thd->net, error, errmsg);
+ DBUG_RETURN(test(error)); // Return 1 on error
}
+
void end_master_info(MASTER_INFO* mi)
{
+ DBUG_ENTER("end_master_info");
+
if (!mi->inited)
- return;
+ DBUG_VOID_RETURN;
end_relay_log_info(&mi->rli);
if (mi->fd >= 0)
- {
- end_io_cache(&mi->file);
- (void)my_close(mi->fd, MYF(MY_WME));
- mi->fd = -1;
- }
+ {
+ end_io_cache(&mi->file);
+ (void)my_close(mi->fd, MYF(MY_WME));
+ mi->fd = -1;
+ }
mi->inited = 0;
+
+ DBUG_VOID_RETURN;
}
+
int init_relay_log_info(RELAY_LOG_INFO* rli, const char* info_fname)
{
- DBUG_ENTER("init_relay_log_info");
- if (rli->inited)
- DBUG_RETURN(0);
- MY_STAT stat_area;
char fname[FN_REFLEN+128];
int info_fd;
const char* msg = 0;
int error = 0;
- fn_format(fname, info_fname,
- mysql_data_home, "", 4+32);
+ DBUG_ENTER("init_relay_log_info");
+
+ if (rli->inited) // Set if this function called
+ DBUG_RETURN(0);
+ fn_format(fname, info_fname, mysql_data_home, "", 4+32);
pthread_mutex_lock(&rli->data_lock);
info_fd = rli->info_fd;
rli->pending = 0;
@@ -998,105 +1043,119 @@ int init_relay_log_info(RELAY_LOG_INFO* rli, const char* info_fname)
rli->skip_log_purge=0;
rli->log_space_limit = relay_log_space_limit;
rli->log_space_total = 0;
+
// TODO: make this work with multi-master
if (!opt_relay_logname)
{
char tmp[FN_REFLEN];
- /* TODO: The following should be using fn_format(); We just need to
- first change fn_format() to cut the file name if it's too long.
+ /*
+ TODO: The following should be using fn_format(); We just need to
+ first change fn_format() to cut the file name if it's too long.
*/
strmake(tmp,glob_hostname,FN_REFLEN-5);
strmov(strcend(tmp,'.'),"-relay-bin");
opt_relay_logname=my_strdup(tmp,MYF(MY_WME));
}
- rli->relay_log.set_index_file_name(opt_relaylog_index_name);
- open_log(&rli->relay_log, glob_hostname, opt_relay_logname, "-relay-bin",
- LOG_BIN, 1 /* read_append cache */,
- 1 /* no auto events*/);
-
+ if (open_log(&rli->relay_log, glob_hostname, opt_relay_logname,
+ "-relay-bin", opt_relaylog_index_name,
+ LOG_BIN, 1 /* read_append cache */,
+ 1 /* no auto events */))
+ DBUG_RETURN(1);
+
/* if file does not exist */
- if (!my_stat(fname, &stat_area, MYF(0)))
+ if (access(fname,F_OK))
{
- // if someone removed the file from underneath our feet, just close
- // the old descriptor and re-create the old file
+ /*
+ If someone removed the file from underneath our feet, just close
+ the old descriptor and re-create the old file
+ */
if (info_fd >= 0)
my_close(info_fd, MYF(MY_WME));
- if ((info_fd = my_open(fname, O_CREAT|O_RDWR|O_BINARY, MYF(MY_WME))) < 0
- || init_io_cache(&rli->info_file, info_fd, IO_SIZE*2, READ_CACHE, 0L,0,
- MYF(MY_WME)))
+ if ((info_fd = my_open(fname, O_CREAT|O_RDWR|O_BINARY, MYF(MY_WME))) < 0 ||
+ init_io_cache(&rli->info_file, info_fd, IO_SIZE*2, READ_CACHE, 0L,0,
+ MYF(MY_WME)))
{
- if(info_fd >= 0)
- my_close(info_fd, MYF(0));
- rli->info_fd=-1;
- pthread_mutex_unlock(&rli->data_lock);
- DBUG_RETURN(1);
+ msg= current_thd->net.last_error;
+ goto err;
}
- if (init_relay_log_pos(rli,"",4,0/*no data mutex*/,&msg))
+
+ /* Init relay log with first entry in the relay index file */
+ if (init_relay_log_pos(rli,NullS,BIN_LOG_HEADER_SIZE,0 /* no data lock */,
+ &msg))
goto err;
rli->master_log_pos = 0; // uninitialized
rli->info_fd = info_fd;
}
else // file exists
{
- if(info_fd >= 0)
+ if (info_fd >= 0)
reinit_io_cache(&rli->info_file, READ_CACHE, 0L,0,0);
- else if((info_fd = my_open(fname, O_RDWR|O_BINARY, MYF(MY_WME))) < 0
- || init_io_cache(&rli->info_file, info_fd,
- IO_SIZE*2, READ_CACHE, 0L,
- 0, MYF(MY_WME)))
+ else if ((info_fd = my_open(fname, O_RDWR|O_BINARY, MYF(MY_WME))) < 0 ||
+ init_io_cache(&rli->info_file, info_fd,
+ IO_SIZE*2, READ_CACHE, 0L, 0, MYF(MY_WME)))
{
if (info_fd >= 0)
my_close(info_fd, MYF(0));
- rli->info_fd=-1;
+ rli->info_fd= -1;
+ rli->relay_log.close(1);
pthread_mutex_unlock(&rli->data_lock);
DBUG_RETURN(1);
}
rli->info_fd = info_fd;
+ int relay_log_pos, master_log_pos;
if (init_strvar_from_file(rli->relay_log_name,
- sizeof(rli->relay_log_name), &rli->info_file,
- (char*)"") ||
- init_intvar_from_file((int*)&rli->relay_log_pos,
- &rli->info_file, 4) ||
+ sizeof(rli->relay_log_name), &rli->info_file,
+ "") ||
+ init_intvar_from_file(&relay_log_pos,
+ &rli->info_file, BIN_LOG_HEADER_SIZE) ||
init_strvar_from_file(rli->master_log_name,
sizeof(rli->master_log_name), &rli->info_file,
- (char*)"") ||
- init_intvar_from_file((int*)&rli->master_log_pos,
- &rli->info_file, 0))
+ "") ||
+ init_intvar_from_file(&master_log_pos, &rli->info_file, 0))
{
msg="Error reading slave log configuration";
goto err;
}
- if (init_relay_log_pos(rli,0 /*log already inited*/,
- 0 /*pos already inited*/,
+ rli->relay_log_pos= relay_log_pos;
+ rli->master_log_pos= master_log_pos;
+
+ if (init_relay_log_pos(rli,
+ rli->relay_log_name,
+ rli->relay_log_pos,
0 /* no data lock*/,
&msg))
- goto err;
+ goto err;
}
- DBUG_ASSERT(rli->relay_log_pos >= 4);
+ DBUG_ASSERT(rli->relay_log_pos >= BIN_LOG_HEADER_SIZE);
DBUG_ASSERT(my_b_tell(rli->cur_log) == rli->relay_log_pos);
- rli->inited = 1;
- // now change the cache from READ to WRITE - must do this
- // before flush_relay_log_info
+ /*
+ Now change the cache from READ to WRITE - must do this
+ before flush_relay_log_info
+ */
reinit_io_cache(&rli->info_file, WRITE_CACHE,0L,0,1);
- error=test(flush_relay_log_info(rli));
+ error= flush_relay_log_info(rli);
if (count_relay_log_space(rli))
{
msg="Error counting relay log space";
goto err;
}
+ rli->inited= 1;
pthread_mutex_unlock(&rli->data_lock);
DBUG_RETURN(error);
err:
sql_print_error(msg);
end_io_cache(&rli->info_file);
- my_close(info_fd, MYF(0));
- rli->info_fd=-1;
+ if (info_fd >= 0)
+ my_close(info_fd, MYF(0));
+ rli->info_fd= -1;
+ rli->relay_log.close(1);
pthread_mutex_unlock(&rli->data_lock);
DBUG_RETURN(1);
}
+
static inline int add_relay_log(RELAY_LOG_INFO* rli,LOG_INFO* linfo)
{
MY_STAT s;
@@ -1110,11 +1169,12 @@ static inline int add_relay_log(RELAY_LOG_INFO* rli,LOG_INFO* linfo)
rli->log_space_total += s.st_size;
#ifndef DBUG_OFF
char buf[22];
-#endif
DBUG_PRINT("info",("log_space_total: %s", llstr(rli->log_space_total,buf)));
+#endif
DBUG_RETURN(0);
}
+
static bool wait_for_relay_log_space(RELAY_LOG_INFO* rli)
{
bool slave_killed=0;
@@ -1138,41 +1198,39 @@ static bool wait_for_relay_log_space(RELAY_LOG_INFO* rli)
DBUG_RETURN(slave_killed);
}
+
static int count_relay_log_space(RELAY_LOG_INFO* rli)
{
LOG_INFO linfo;
DBUG_ENTER("count_relay_log_space");
rli->log_space_total = 0;
- if (rli->relay_log.find_first_log(&linfo,""))
+ if (rli->relay_log.find_log_pos(&linfo, NullS, 1))
{
sql_print_error("Could not find first log while counting relay log space");
DBUG_RETURN(1);
}
- if (add_relay_log(rli,&linfo))
- DBUG_RETURN(1);
- while (!rli->relay_log.find_next_log(&linfo))
+ do
{
if (add_relay_log(rli,&linfo))
DBUG_RETURN(1);
- }
+ } while (!rli->relay_log.find_next_log(&linfo, 1));
DBUG_RETURN(0);
}
+
int init_master_info(MASTER_INFO* mi, const char* master_info_fname,
- const char* slave_info_fname)
+ const char* slave_info_fname,
+ bool abort_if_no_master_info_file)
{
+ int fd,error;
+ char fname[FN_REFLEN+128];
+ DBUG_ENTER("init_master_info");
+
if (mi->inited)
- return 0;
- if (init_relay_log_info(&mi->rli, slave_info_fname))
- return 1;
- mi->rli.mi = mi;
+ DBUG_RETURN(0);
mi->mysql=0;
mi->file_id=1;
mi->ignore_stop_event=0;
- int fd,error;
- MY_STAT stat_area;
- char fname[FN_REFLEN+128];
- const char *msg;
fn_format(fname, master_info_fname, mysql_data_home, "", 4+32);
/*
@@ -1183,26 +1241,26 @@ int init_master_info(MASTER_INFO* mi, const char* master_info_fname,
pthread_mutex_lock(&mi->data_lock);
fd = mi->fd;
- // we do not want any messages if the file does not exist
- if (!my_stat(fname, &stat_area, MYF(0)))
+ if (access(fname,F_OK))
{
- // if someone removed the file from underneath our feet, just close
- // the old descriptor and re-create the old file
- if (fd >= 0)
- my_close(fd, MYF(MY_WME));
- if ((fd = my_open(fname, O_CREAT|O_RDWR|O_BINARY, MYF(MY_WME))) < 0
- || init_io_cache(&mi->file, fd, IO_SIZE*2, READ_CACHE, 0L,0,
- MYF(MY_WME)))
+ if (abort_if_no_master_info_file)
{
- if(fd >= 0)
- my_close(fd, MYF(0));
- mi->fd=-1;
- end_relay_log_info(&mi->rli);
pthread_mutex_unlock(&mi->data_lock);
- return 1;
+ DBUG_RETURN(0);
}
+ /*
+ if someone removed the file from underneath our feet, just close
+ the old descriptor and re-create the old file
+ */
+ if (fd >= 0)
+ my_close(fd, MYF(MY_WME));
+ if ((fd = my_open(fname, O_CREAT|O_RDWR|O_BINARY, MYF(MY_WME))) < 0 ||
+ init_io_cache(&mi->file, fd, IO_SIZE*2, READ_CACHE, 0L,0,
+ MYF(MY_WME)))
+ goto err;
+
mi->master_log_name[0] = 0;
- mi->master_log_pos = 4; // skip magic number
+ mi->master_log_pos = BIN_LOG_HEADER_SIZE; // skip magic number
mi->fd = fd;
if (master_host)
@@ -1216,58 +1274,68 @@ int init_master_info(MASTER_INFO* mi, const char* master_info_fname,
}
else // file exists
{
- if(fd >= 0)
+ if (fd >= 0)
reinit_io_cache(&mi->file, READ_CACHE, 0L,0,0);
- else if((fd = my_open(fname, O_RDWR|O_BINARY, MYF(MY_WME))) < 0
- || init_io_cache(&mi->file, fd, IO_SIZE*2, READ_CACHE, 0L,
- 0, MYF(MY_WME)))
- {
- if(fd >= 0)
- my_close(fd, MYF(0));
- mi->fd=-1;
- end_relay_log_info(&mi->rli);
- pthread_mutex_unlock(&mi->data_lock);
- return 1;
- }
+ else if ((fd = my_open(fname, O_RDWR|O_BINARY, MYF(MY_WME))) < 0 ||
+ init_io_cache(&mi->file, fd, IO_SIZE*2, READ_CACHE, 0L,
+ 0, MYF(MY_WME)))
+ goto err;
mi->fd = fd;
+ int port, connect_retry, master_log_pos;
+
if (init_strvar_from_file(mi->master_log_name,
sizeof(mi->master_log_name), &mi->file,
- (char*)"") ||
- init_intvar_from_file((int*)&mi->master_log_pos, &mi->file, 4) ||
+ "") ||
+ init_intvar_from_file(&master_log_pos, &mi->file, 4) ||
init_strvar_from_file(mi->host, sizeof(mi->host), &mi->file,
master_host) ||
init_strvar_from_file(mi->user, sizeof(mi->user), &mi->file,
master_user) ||
init_strvar_from_file(mi->password, HASH_PASSWORD_LENGTH+1, &mi->file,
master_password) ||
- init_intvar_from_file((int*)&mi->port, &mi->file, master_port) ||
- init_intvar_from_file((int*)&mi->connect_retry, &mi->file,
+ init_intvar_from_file(&port, &mi->file, master_port) ||
+ init_intvar_from_file(&connect_retry, &mi->file,
master_connect_retry))
{
- msg="Error reading master configuration";
+ sql_print_error("Error reading master configuration");
goto err;
}
+ /*
+ This has to be handled here as init_intvar_from_file can't handle
+ my_off_t types
+ */
+ mi->master_log_pos= (my_off_t) master_log_pos;
+ mi->port= (uint) port;
+ mi->connect_retry= (uint) connect_retry;
}
-
+ DBUG_PRINT("master_info",("log_file_name: %s position: %ld",
+ mi->master_log_name,
+ (ulong) mi->master_log_pos));
+
+ if (init_relay_log_info(&mi->rli, slave_info_fname))
+ goto err;
+ mi->rli.mi = mi;
+
mi->inited = 1;
// now change cache READ -> WRITE - must do this before flush_master_info
reinit_io_cache(&mi->file, WRITE_CACHE,0L,0,1);
error=test(flush_master_info(mi));
pthread_mutex_unlock(&mi->data_lock);
- return error;
+ DBUG_RETURN(error);
err:
- sql_print_error(msg);
- end_io_cache(&mi->file);
- end_relay_log_info(&mi->rli);
- DBUG_ASSERT(fd>=0);
- my_close(fd, MYF(0));
- mi->fd=-1;
+ if (fd >= 0)
+ {
+ my_close(fd, MYF(0));
+ end_io_cache(&mi->file);
+ }
+ mi->fd= -1;
pthread_mutex_unlock(&mi->data_lock);
- return 1;
+ DBUG_RETURN(1);
}
+
int register_slave_on_master(MYSQL* mysql)
{
String packet;
@@ -1285,7 +1353,7 @@ int register_slave_on_master(MYSQL* mysql)
else
packet.append((char)0);
- if(report_password)
+ if (report_password)
net_store_data(&packet, report_user);
else
packet.append((char)0);
@@ -1300,7 +1368,8 @@ int register_slave_on_master(MYSQL* mysql)
if (mc_simple_command(mysql, COM_REGISTER_SLAVE, (char*)packet.ptr(),
packet.length(), 0))
{
- sql_print_error("Error on COM_REGISTER_SLAVE: '%s'",
+ sql_print_error("Error on COM_REGISTER_SLAVE: %d '%s'",
+ mc_mysql_errno(mysql),
mc_mysql_error(mysql));
return 1;
}
@@ -1336,48 +1405,53 @@ int show_master_info(THD* thd, MASTER_INFO* mi)
field_list.push_back(new Item_empty_string("Skip_counter", 12));
field_list.push_back(new Item_empty_string("Exec_master_log_pos", 12));
field_list.push_back(new Item_empty_string("Relay_log_space", 12));
- if(send_fields(thd, field_list, 1))
+ if (send_fields(thd, field_list, 1))
DBUG_RETURN(-1);
- String* packet = &thd->packet;
- packet->length(0);
+ if (mi->host[0])
+ {
+ String *packet= &thd->packet;
+ packet->length(0);
- pthread_mutex_lock(&mi->data_lock);
- pthread_mutex_lock(&mi->rli.data_lock);
- net_store_data(packet, mi->host);
- net_store_data(packet, mi->user);
- net_store_data(packet, (uint32) mi->port);
- net_store_data(packet, (uint32) mi->connect_retry);
- net_store_data(packet, mi->master_log_name);
- net_store_data(packet, (longlong) mi->master_log_pos);
- net_store_data(packet, mi->rli.relay_log_name +
- dirname_length(mi->rli.relay_log_name));
- net_store_data(packet, (longlong) mi->rli.relay_log_pos);
- net_store_data(packet, mi->rli.master_log_name);
- net_store_data(packet, mi->slave_running ? "Yes":"No");
- net_store_data(packet, mi->rli.slave_running ? "Yes":"No");
- net_store_data(packet, &replicate_do_db);
- net_store_data(packet, &replicate_ignore_db);
- net_store_data(packet, (uint32)mi->rli.last_slave_errno);
- net_store_data(packet, mi->rli.last_slave_error);
- net_store_data(packet, mi->rli.slave_skip_counter);
- net_store_data(packet, (longlong) mi->rli.master_log_pos);
- net_store_data(packet, (longlong) mi->rli.log_space_total);
- pthread_mutex_unlock(&mi->rli.data_lock);
- pthread_mutex_unlock(&mi->data_lock);
+ pthread_mutex_lock(&mi->data_lock);
+ pthread_mutex_lock(&mi->rli.data_lock);
+ net_store_data(packet, mi->host);
+ net_store_data(packet, mi->user);
+ net_store_data(packet, (uint32) mi->port);
+ net_store_data(packet, (uint32) mi->connect_retry);
+ net_store_data(packet, mi->master_log_name);
+ net_store_data(packet, (longlong) mi->master_log_pos);
+ net_store_data(packet, mi->rli.relay_log_name +
+ dirname_length(mi->rli.relay_log_name));
+ net_store_data(packet, (longlong) mi->rli.relay_log_pos);
+ net_store_data(packet, mi->rli.master_log_name);
+ net_store_data(packet, mi->slave_running ? "Yes":"No");
+ net_store_data(packet, mi->rli.slave_running ? "Yes":"No");
+ net_store_data(packet, &replicate_do_db);
+ net_store_data(packet, &replicate_ignore_db);
+ net_store_data(packet, (uint32)mi->rli.last_slave_errno);
+ net_store_data(packet, mi->rli.last_slave_error);
+ net_store_data(packet, mi->rli.slave_skip_counter);
+ net_store_data(packet, (longlong) mi->rli.master_log_pos);
+ net_store_data(packet, (longlong) mi->rli.log_space_total);
+ pthread_mutex_unlock(&mi->rli.data_lock);
+ pthread_mutex_unlock(&mi->data_lock);
- if (my_net_write(&thd->net, (char*)thd->packet.ptr(), packet->length()))
- DBUG_RETURN(-1);
-
+ if (my_net_write(&thd->net, (char*)thd->packet.ptr(), packet->length()))
+ DBUG_RETURN(-1);
+ }
send_eof(&thd->net);
DBUG_RETURN(0);
}
-int flush_master_info(MASTER_INFO* mi)
+
+bool flush_master_info(MASTER_INFO* mi)
{
IO_CACHE* file = &mi->file;
char lbuf[22];
-
+ DBUG_ENTER("flush_master_info");
+ 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",
mi->master_log_name, llstr(mi->master_log_pos, lbuf),
@@ -1385,43 +1459,43 @@ int flush_master_info(MASTER_INFO* mi)
mi->password, mi->port, mi->connect_retry
);
flush_io_cache(file);
- return 0;
+ DBUG_RETURN(0);
}
+
int st_relay_log_info::wait_for_pos(THD* thd, String* log_name,
ulonglong log_pos)
{
- if (!inited) return -1;
- bool pos_reached = 0;
+ if (!inited)
+ return -1;
int event_count = 0;
+ ulong init_abort_pos_wait;
+ DBUG_ENTER("wait_for_pos");
+
pthread_mutex_lock(&data_lock);
- abort_pos_wait=0; // abort only if master info changes during wait
- while (!thd->killed || !abort_pos_wait)
+ // abort only if master info changes during wait
+ init_abort_pos_wait= abort_pos_wait;
+
+ while (!thd->killed &&
+ init_abort_pos_wait == abort_pos_wait &&
+ mi->slave_running)
{
- int cmp_result;
- if (abort_pos_wait)
- {
- abort_pos_wait=0;
- pthread_mutex_unlock(&data_lock);
- return -1;
- }
+ bool pos_reached;
+ int cmp_result= 0;
DBUG_ASSERT(*master_log_name || master_log_pos == 0);
if (*master_log_name)
{
/*
- We should use dirname_length() here when we have a version of
- this that doesn't modify the argument */
- char *basename = strrchr(master_log_name, FN_LIBCHAR);
- if (basename)
- ++basename;
- else
- basename = master_log_name;
+ TODO:
+ Replace strncmp() with a comparison function that
+ can handle comparison of the following files:
+ mysqlbin.999
+ mysqlbin.1000
+ */
+ char *basename= master_log_name + dirname_length(master_log_name);
cmp_result = strncmp(basename, log_name->ptr(),
log_name->length());
}
- else
- cmp_result = 0;
-
pos_reached = ((!cmp_result && master_log_pos >= log_pos) ||
cmp_result > 0);
if (pos_reached || thd->killed)
@@ -1434,17 +1508,23 @@ int st_relay_log_info::wait_for_pos(THD* thd, String* log_name,
event_count++;
}
pthread_mutex_unlock(&data_lock);
- return thd->killed ? -1 : event_count;
+ DBUG_PRINT("exit",("killed: %d abort: %d slave_running: %d",
+ (int) thd->killed,
+ (int) (init_abort_pos_wait != abort_pos_wait),
+ (int) mi->slave_running));
+ DBUG_RETURN((thd->killed || init_abort_pos_wait != abort_pos_wait ||
+ !mi->slave_running) ?
+ -1 : event_count);
}
+
static int init_slave_thread(THD* thd, SLAVE_THD_TYPE thd_type)
{
DBUG_ENTER("init_slave_thread");
thd->system_thread = thd->bootstrap = 1;
thd->client_capabilities = 0;
my_net_init(&thd->net, 0);
- thd->net.timeout = slave_net_timeout;
- thd->max_packet_length=thd->net.max_packet;
+ thd->net.read_timeout = slave_net_timeout;
thd->master_access= ~0;
thd->priv_user = 0;
thd->slave_thread = 1;
@@ -1470,45 +1550,39 @@ static int init_slave_thread(THD* thd, SLAVE_THD_TYPE thd_type)
VOID(pthread_sigmask(SIG_UNBLOCK,&set,&thd->block_signals));
#endif
- if (thd->max_join_size == (ulong) ~0L)
+ if ((ulong) thd->variables.max_join_size == (ulong) HA_POS_ERROR)
thd->options |= OPTION_BIG_SELECTS;
if (thd_type == SLAVE_THD_SQL)
- {
- thd->proc_info = "Waiting for the next event in slave queue";
- }
+ thd->proc_info= "Waiting for the next event in slave queue";
else
- {
- thd->proc_info="Waiting for master update";
- }
+ thd->proc_info= "Waiting for master update";
thd->version=refresh_version;
thd->set_time();
DBUG_RETURN(0);
}
+
static int safe_sleep(THD* thd, int sec, CHECK_KILLED_FUNC thread_killed,
void* thread_killed_arg)
{
+ int nap_time;
thr_alarm_t alarmed;
thr_alarm_init(&alarmed);
time_t start_time= time((time_t*) 0);
time_t end_time= start_time+sec;
- ALARM alarm_buff;
- while (start_time < end_time)
+ while ((nap_time= (int) (end_time - start_time)) > 0)
{
- int nap_time = (int) (end_time - start_time);
+ ALARM alarm_buff;
/*
- the only reason we are asking for alarm is so that
+ The only reason we are asking for alarm is so that
we will be woken up in case of murder, so if we do not get killed,
set the alarm so it goes off after we wake up naturally
*/
- thr_alarm(&alarmed, 2 * nap_time,&alarm_buff);
+ thr_alarm(&alarmed, 2 * nap_time, &alarm_buff);
sleep(nap_time);
- // if we wake up before the alarm goes off, hit the button
- // so it will not wake up the wife and kids :-)
- if (thr_alarm_in_use(&alarmed))
- thr_end_alarm(&alarmed);
+ thr_end_alarm(&alarmed);
if ((*thread_killed)(thd,thread_killed_arg))
return 1;
@@ -1517,12 +1591,16 @@ static int safe_sleep(THD* thd, int sec, CHECK_KILLED_FUNC thread_killed,
return 0;
}
-static int request_dump(MYSQL* mysql, MASTER_INFO* mi)
+
+static int request_dump(MYSQL* mysql, MASTER_INFO* mi,
+ bool *suppress_warnings)
{
char buf[FN_REFLEN + 10];
int len;
int binlog_flags = 0; // for now
char* logname = mi->master_log_name;
+ DBUG_ENTER("request_dump");
+
// TODO if big log files: Change next to int8store()
int4store(buf, (longlong) mi->master_log_pos);
int2store(buf + 4, binlog_flags);
@@ -1531,28 +1609,35 @@ static int request_dump(MYSQL* mysql, MASTER_INFO* mi)
memcpy(buf + 10, logname,len);
if (mc_simple_command(mysql, COM_BINLOG_DUMP, buf, len + 10, 1))
{
- // something went wrong, so we will just reconnect and retry later
- // in the future, we should do a better error analysis, but for
- // now we just fill up the error log :-)
- sql_print_error("Error on COM_BINLOG_DUMP: %s, will retry in %d secs",
- mc_mysql_error(mysql), master_connect_retry);
- return 1;
+ /*
+ Something went wrong, so we will just reconnect and retry later
+ in the future, we should do a better error analysis, but for
+ now we just fill up the error log :-)
+ */
+ if (mc_mysql_errno(mysql) == ER_NET_READ_INTERRUPTED)
+ *suppress_warnings= 1; // Suppress reconnect warning
+ else
+ sql_print_error("Error on COM_BINLOG_DUMP: %d %s, will retry in %d secs",
+ mc_mysql_errno(mysql), mc_mysql_error(mysql),
+ master_connect_retry);
+ DBUG_RETURN(1);
}
- return 0;
+ DBUG_RETURN(0);
}
+
static int request_table_dump(MYSQL* mysql, const char* db, const char* table)
{
char buf[1024];
char * p = buf;
uint table_len = (uint) strlen(table);
uint db_len = (uint) strlen(db);
- if(table_len + db_len > sizeof(buf) - 2)
- {
- sql_print_error("request_table_dump: Buffer overrun");
- return 1;
- }
+ if (table_len + db_len > sizeof(buf) - 2)
+ {
+ sql_print_error("request_table_dump: Buffer overrun");
+ return 1;
+ }
*p++ = db_len;
memcpy(p, db, db_len);
@@ -1570,24 +1655,57 @@ command");
return 0;
}
-static ulong read_event(MYSQL* mysql, MASTER_INFO *mi)
+
+/*
+ read one event from the master
+
+ SYNOPSIS
+ read_event()
+ mysql MySQL connection
+ mi Master connection information
+ suppress_warnings TRUE when a normal net read timeout has caused us to
+ try a reconnect. We do not want to print anything to
+ the error log in this case because this a anormal
+ event in an idle server.
+
+ RETURN VALUES
+ 'packet_error' Error
+ number Length of packet
+
+*/
+
+static ulong read_event(MYSQL* mysql, MASTER_INFO *mi, bool* suppress_warnings)
{
- ulong len = packet_error;
+ ulong len;
+
+ *suppress_warnings= 0;
+ /*
+ my_real_read() will time us out
+ We check if we were told to die, and if not, try reading again
- // my_real_read() will time us out
- // we check if we were told to die, and if not, try reading again
+ TODO: Move 'events_till_disconnect' to the MASTER_INFO structure
+ */
#ifndef DBUG_OFF
if (disconnect_slave_event_count && !(events_till_disconnect--))
return packet_error;
#endif
len = mc_net_safe_read(mysql);
-
if (len == packet_error || (long) len < 1)
{
- sql_print_error("Error reading packet from server: %s (\
+ if (mc_mysql_errno(mysql) == ER_NET_READ_INTERRUPTED)
+ {
+ /*
+ We are trying a normal reconnect after a read timeout;
+ we suppress prints to .err file as long as the reconnect
+ happens without problems
+ */
+ *suppress_warnings= TRUE;
+ }
+ else
+ sql_print_error("Error reading packet from server: %s (\
server_errno=%d)",
- mc_mysql_error(mysql), mc_mysql_errno(mysql));
+ mc_mysql_error(mysql), mc_mysql_errno(mysql));
return packet_error;
}
@@ -1604,28 +1722,29 @@ server_errno=%d)",
return len - 1;
}
+
int check_expected_error(THD* thd, RELAY_LOG_INFO* rli, int expected_error)
{
- switch (expected_error)
- {
- case ER_NET_READ_ERROR:
- case ER_NET_ERROR_ON_WRITE:
- case ER_SERVER_SHUTDOWN:
- case ER_NEW_ABORTING_CONNECTION:
- my_snprintf(rli->last_slave_error, sizeof(rli->last_slave_error),
- "Slave: query '%s' partially completed on the master \
+ switch (expected_error) {
+ case ER_NET_READ_ERROR:
+ case ER_NET_ERROR_ON_WRITE:
+ case ER_SERVER_SHUTDOWN:
+ case ER_NEW_ABORTING_CONNECTION:
+ my_snprintf(rli->last_slave_error, sizeof(rli->last_slave_error),
+ "Slave: query '%s' partially completed on the master \
and was aborted. There is a chance that your master is inconsistent at this \
point. If you are sure that your master is ok, run this query manually on the\
slave and then restart the slave with SET SQL_SLAVE_SKIP_COUNTER=1;\
SLAVE START;", thd->query);
- rli->last_slave_errno = expected_error;
- sql_print_error("%s",rli->last_slave_error);
- return 1;
- default:
- return 0;
- }
+ rli->last_slave_errno = expected_error;
+ sql_print_error("%s",rli->last_slave_error);
+ return 1;
+ default:
+ return 0;
+ }
}
+
static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli)
{
DBUG_ASSERT(rli->sql_thd==thd);
@@ -1638,7 +1757,15 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli)
int type_code = ev->get_type_code();
int exec_res;
pthread_mutex_lock(&rli->data_lock);
- if (ev->server_id == ::server_id ||
+
+ /*
+ Skip queries originating from this server or number of
+ queries specified by the user in slave_skip_counter
+ We can't however skip event's that has something to do with the
+ log files themselves.
+ */
+
+ if (ev->server_id == (uint32) ::server_id ||
(rli->slave_skip_counter && type_code != ROTATE_EVENT))
{
/* TODO: I/O thread should not even log events with the same server id */
@@ -1646,12 +1773,14 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli)
type_code != STOP_EVENT ? ev->log_pos : LL(0),
1/* skip lock*/);
flush_relay_log_info(rli);
- if (rli->slave_skip_counter && /* protect against common user error of
- setting the counter to 1 instead of 2
- while recovering from an failed
- auto-increment insert */
- !((type_code == INTVAR_EVENT || type_code == STOP_EVENT) &&
- rli->slave_skip_counter == 1))
+
+ /*
+ Protect against common user error of setting the counter to 1
+ instead of 2 while recovering from an failed auto-increment insert
+ */
+ if (rli->slave_skip_counter &&
+ !((type_code == INTVAR_EVENT || type_code == STOP_EVENT) &&
+ rli->slave_skip_counter == 1))
--rli->slave_skip_counter;
pthread_mutex_unlock(&rli->data_lock);
delete ev;
@@ -1680,28 +1809,35 @@ This may also be a network problem, or just a bug in the master or slave code.\
}
}
+
/* slave I/O thread */
pthread_handler_decl(handle_slave_io,arg)
{
+ THD *thd; // needs to be first for thread_stack
+ MYSQL *mysql;
+ MASTER_INFO *mi = (MASTER_INFO*)arg;
+ char llbuff[22];
+ uint retry_count;
+
+ // needs to call my_thread_init(), otherwise we get a coredump in DBUG_ stuff
+ my_thread_init();
+
#ifndef DBUG_OFF
slave_begin:
#endif
- THD *thd; // needs to be first for thread_stack
- MYSQL *mysql = NULL ;
- MASTER_INFO* mi = (MASTER_INFO*)arg;
- char llbuff[22];
- bool retried_once = 0;
- ulonglong last_failed_pos = 0; // TODO: see if last_failed_pos is needed
DBUG_ASSERT(mi->inited);
-
+ mysql= NULL ;
+ retry_count= 0;
+
pthread_mutex_lock(&mi->run_lock);
+ /* Inform waiting threads that slave has started */
+ mi->slave_run_id++;
+
#ifndef DBUG_OFF
mi->events_till_abort = abort_slave_event_count;
#endif
- // needs to call my_thread_init(), otherwise we get a coredump in DBUG_ stuff
- my_thread_init();
- thd = new THD; // note that contructor of THD uses DBUG_ !
+ thd= new THD; // note that contructor of THD uses DBUG_ !
DBUG_ENTER("handle_slave_io");
THD_CHECK_SENTRY(thd);
@@ -1715,14 +1851,17 @@ slave_begin:
}
mi->io_thd = thd;
thd->thread_stack = (char*)&thd; // remember where our stack is
+ pthread_mutex_lock(&LOCK_thread_count);
threads.append(thd);
+ pthread_mutex_unlock(&LOCK_thread_count);
mi->slave_running = 1;
mi->abort_slave = 0;
- pthread_cond_broadcast(&mi->start_cond);
pthread_mutex_unlock(&mi->run_lock);
+ pthread_cond_broadcast(&mi->start_cond);
- DBUG_PRINT("info",("master info: log_file_name=%s, position=%s",
- mi->master_log_name, llstr(mi->master_log_pos,llbuff)));
+ DBUG_PRINT("master_info",("log_file_name: '%s' position: %s",
+ mi->master_log_name,
+ llstr(mi->master_log_pos,llbuff)));
if (!(mi->mysql = mysql = mc_mysql_init(NULL)))
{
@@ -1730,10 +1869,8 @@ slave_begin:
goto err;
}
+
thd->proc_info = "connecting to master";
-#ifndef DBUG_OFF
- sql_print_error("Slave I/O thread initialized");
-#endif
// we can get killed during safe_connect
if (!safe_connect(thd, mysql, mi))
sql_print_error("Slave I/O thread: connected to master '%s@%s:%d',\
@@ -1765,13 +1902,15 @@ connected:
goto err;
}
+ DBUG_PRINT("info",("Starting reading binary log from master"));
while (!io_slave_killed(thd,mi))
{
+ bool suppress_warnings= 0;
thd->proc_info = "Requesting binlog dump";
- if (request_dump(mysql, mi))
+ if (request_dump(mysql, mi, &suppress_warnings))
{
sql_print_error("Failed on request_dump()");
- if(io_slave_killed(thd,mi))
+ if (io_slave_killed(thd,mi))
{
sql_print_error("Slave I/O thread killed while requesting master \
dump");
@@ -1785,12 +1924,13 @@ dump");
right away - if first time fails, sleep between re-tries
hopefuly the admin can fix the problem sometime
*/
- if (retried_once)
+ if (retry_count++)
+ {
+ if (retry_count > master_retry_count)
+ goto err; // Don't retry forever
safe_sleep(thd,mi->connect_retry,(CHECK_KILLED_FUNC)io_slave_killed,
(void*)mi);
- else
- retried_once = 1;
-
+ }
if (io_slave_killed(thd,mi))
{
sql_print_error("Slave I/O thread killed while retrying master \
@@ -1799,10 +1939,12 @@ dump");
}
thd->proc_info = "Reconnecting after a failed dump request";
- sql_print_error("Slave I/O thread: failed dump request, \
+ if (!suppress_warnings)
+ sql_print_error("Slave I/O thread: failed dump request, \
reconnecting to try again, log '%s' at postion %s", IO_RPL_LOG_NAME,
- llstr(mi->master_log_pos,llbuff));
- if (safe_reconnect(thd, mysql, mi) || io_slave_killed(thd,mi))
+ llstr(mi->master_log_pos,llbuff));
+ if (safe_reconnect(thd, mysql, mi, suppress_warnings) ||
+ io_slave_killed(thd,mi))
{
sql_print_error("Slave I/O thread killed during or \
after reconnect");
@@ -1814,58 +1956,72 @@ after reconnect");
while (!io_slave_killed(thd,mi))
{
+ bool suppress_warnings= 0;
thd->proc_info = "Reading master update";
- ulong event_len = read_event(mysql, mi);
+ ulong event_len = read_event(mysql, mi, &suppress_warnings);
if (io_slave_killed(thd,mi))
{
- sql_print_error("Slave I/O thread killed while reading event");
+ if (global_system_variables.log_warnings)
+ sql_print_error("Slave I/O thread killed while reading event");
goto err;
}
if (event_len == packet_error)
{
- if (mc_mysql_errno(mysql) == ER_NET_PACKET_TOO_LARGE)
+ uint mysql_error_number= mc_mysql_errno(mysql);
+ if (mysql_error_number == ER_NET_PACKET_TOO_LARGE)
+ {
+ sql_print_error("\
+Log entry on master is longer than max_allowed_packet (%ld) on \
+slave. If the entry is correct, restart the server with a higher value of \
+max_allowed_packet",
+ thd->variables.max_allowed_packet);
+ goto err;
+ }
+ if (mysql_error_number == ER_MASTER_FATAL_ERROR_READING_BINLOG)
{
- sql_print_error("Log entry on master is longer than \
-max_allowed_packet (%ld) on slave. Slave thread will be aborted. If the entry \
-is correct, restart the server with a higher value of max_allowed_packet",
- max_allowed_packet);
+ sql_print_error(ER(mysql_error_number), mysql_error_number,
+ mc_mysql_error(mysql));
goto err;
}
-
thd->proc_info = "Waiting to reconnect after a failed read";
mc_end_server(mysql);
- if (retried_once) // punish repeat offender with sleep
+ if (retry_count++)
+ {
+ if (retry_count > master_retry_count)
+ goto err; // Don't retry forever
safe_sleep(thd,mi->connect_retry,(CHECK_KILLED_FUNC)io_slave_killed,
- (void*)mi);
- else
- retried_once = 1;
-
+ (void*) mi);
+ }
if (io_slave_killed(thd,mi))
{
- sql_print_error("Slave I/O thread killed while waiting to \
+ if (global_system_variables.log_warnings)
+ sql_print_error("Slave I/O thread killed while waiting to \
reconnect after a failed read");
goto err;
}
thd->proc_info = "Reconnecting after a failed read";
- sql_print_error("Slave I/O thread: Failed reading log event, \
+ if (!suppress_warnings)
+ sql_print_error("Slave I/O thread: Failed reading log event, \
reconnecting to retry, log '%s' position %s", IO_RPL_LOG_NAME,
- llstr(mi->master_log_pos, llbuff));
- if (safe_reconnect(thd, mysql, mi) || io_slave_killed(thd,mi))
+ llstr(mi->master_log_pos, llbuff));
+ if (safe_reconnect(thd, mysql, mi, suppress_warnings) ||
+ io_slave_killed(thd,mi))
{
- sql_print_error("Slave I/O thread killed during or after a \
+ if (global_system_variables.log_warnings)
+ sql_print_error("Slave I/O thread killed during or after a \
reconnect done to recover from failed read");
goto err;
}
goto connected;
- } // if(event_len == packet_error)
+ } // if (event_len == packet_error)
+ retry_count=0; // ok event, reset retry counter
thd->proc_info = "Queueing event from master";
if (queue_event(mi,(const char*)mysql->net.read_pos + 1,
event_len))
{
- sql_print_error("Slave I/O thread could not queue event \
-from master");
+ sql_print_error("Slave I/O thread could not queue event from master");
goto err;
}
flush_master_info(mi);
@@ -1884,9 +2040,9 @@ log space");
sql_print_error("Slave I/O thread: debugging abort");
goto err;
}
-#endif
+#endif
}
- }
+ }
// error = 0;
err:
@@ -1912,11 +2068,11 @@ err:
THD_CHECK_SENTRY(thd);
delete thd;
pthread_mutex_unlock(&LOCK_thread_count);
- my_thread_end(); // clean-up before broadcast
- pthread_cond_broadcast(&mi->stop_cond); // tell the world we are done
+ my_thread_end(); // clean-up before broadcast
+ pthread_cond_broadcast(&mi->stop_cond); // tell the world we are done
pthread_mutex_unlock(&mi->run_lock);
#ifndef DBUG_OFF
- if(abort_slave_event_count && !events_till_abort)
+ if (abort_slave_event_count && !events_till_abort)
goto slave_begin;
#endif
pthread_exit(0);
@@ -1928,30 +2084,32 @@ err:
pthread_handler_decl(handle_slave_sql,arg)
{
+ THD *thd; /* needs to be first for thread_stack */
+ char llbuff[22],llbuff1[22];
+ RELAY_LOG_INFO* rli = &((MASTER_INFO*)arg)->rli;
+ const char *errmsg;
+
+ // needs to call my_thread_init(), otherwise we get a coredump in DBUG_ stuff
+ my_thread_init();
+
#ifndef DBUG_OFF
slave_begin:
#endif
- THD *thd; /* needs to be first for thread_stack */
- MYSQL *mysql = NULL ;
- bool retried_once = 0;
- ulonglong last_failed_pos = 0; // TODO: see if this can be removed
- char llbuff[22],llbuff1[22];
- RELAY_LOG_INFO* rli = &((MASTER_INFO*)arg)->rli;
- const char* errmsg=0;
+
DBUG_ASSERT(rli->inited);
pthread_mutex_lock(&rli->run_lock);
DBUG_ASSERT(!rli->slave_running);
+ errmsg= 0;
#ifndef DBUG_OFF
rli->events_till_abort = abort_slave_event_count;
#endif
-
-
- // needs to call my_thread_init(), otherwise we get a coredump in DBUG_ stuff
- my_thread_init();
- thd = new THD; // note that contructor of THD uses DBUG_ !
DBUG_ENTER("handle_slave_sql");
+
+ thd = new THD; // note that contructor of THD uses DBUG_ !
THD_CHECK_SENTRY(thd);
-
+ /* Inform waiting threads that slave has started */
+ rli->slave_run_id++;
+
pthread_detach_this_thread();
if (init_slave_thread(thd, SLAVE_THD_SQL))
{
@@ -1964,33 +2122,43 @@ slave_begin:
sql_print_error("Failed during slave thread initialization");
goto err;
}
- THD_CHECK_SENTRY(thd);
- thd->thread_stack = (char*)&thd; // remember where our stack is
+ rli->sql_thd= thd;
thd->temporary_tables = rli->save_temporary_tables; // restore temp tables
+ thd->thread_stack = (char*)&thd; // remember where our stack is
+ pthread_mutex_lock(&LOCK_thread_count);
threads.append(thd);
- rli->sql_thd = thd;
+ pthread_mutex_unlock(&LOCK_thread_count);
rli->slave_running = 1;
rli->abort_slave = 0;
- pthread_cond_broadcast(&rli->start_cond);
pthread_mutex_unlock(&rli->run_lock);
- rli->pending = 0; //this should always be set to 0 when the slave thread
- // is started
- if (init_relay_log_pos(rli,0,0,1/*need data lock*/,&errmsg))
+ pthread_cond_broadcast(&rli->start_cond);
+ // This should always be set to 0 when the slave thread is started
+ rli->pending = 0;
+ if (init_relay_log_pos(rli,
+ rli->relay_log_name,
+ rli->relay_log_pos,
+ 1 /*need data lock*/, &errmsg))
{
sql_print_error("Error initializing relay log position: %s",
errmsg);
goto err;
}
- DBUG_ASSERT(rli->relay_log_pos >= 4);
+ THD_CHECK_SENTRY(thd);
+ DBUG_ASSERT(rli->relay_log_pos >= BIN_LOG_HEADER_SIZE);
DBUG_ASSERT(my_b_tell(rli->cur_log) == rli->relay_log_pos);
-
- DBUG_PRINT("info",("master info: log_file_name=%s, position=%s",
- rli->master_log_name, llstr(rli->master_log_pos,llbuff)));
DBUG_ASSERT(rli->sql_thd == thd);
- sql_print_error("Slave SQL thread initialized, starting replication in \
-log '%s' at position %s,relay log: name='%s',pos='%s'", RPL_LOG_NAME,
- llstr(rli->master_log_pos,llbuff),rli->relay_log_name,
- llstr(rli->relay_log_pos,llbuff1));
+
+ DBUG_PRINT("master_info",("log_file_name: %s position: %s",
+ rli->master_log_name,
+ llstr(rli->master_log_pos,llbuff)));
+ if (global_system_variables.log_warnings)
+ sql_print_error("Slave SQL thread initialized, starting replication in \
+log '%s' at position %s, relay log '%s' position: %s", RPL_LOG_NAME,
+ llstr(rli->master_log_pos,llbuff),rli->relay_log_name,
+ llstr(rli->relay_log_pos,llbuff1));
+
+ /* Read queries from the IO/THREAD until this thread is killed */
+
while (!sql_slave_killed(thd,rli))
{
thd->proc_info = "Processing master log event";
@@ -2007,14 +2175,14 @@ the slave SQL thread with \"SLAVE START\". We stopped at log \
RPL_LOG_NAME, llstr(rli->master_log_pos, llbuff));
goto err;
}
- } // while(!sql_slave_killed(thd,rli)) - read/exec loop
+ }
- // error = 0;
- err:
- // print the current replication position
+ /* Thread stopped. Print the current replication position to the log */
sql_print_error("Slave SQL thread exiting, replication stopped in log \
'%s' at position %s",
RPL_LOG_NAME, llstr(rli->master_log_pos,llbuff));
+
+ err:
thd->query = thd->db = 0; // extra safety
thd->proc_info = "Waiting for slave mutex on exit";
pthread_mutex_lock(&rli->run_lock);
@@ -2032,7 +2200,7 @@ the slave SQL thread with \"SLAVE START\". We stopped at log \
net_end(&thd->net); // destructor will not free it, because we are weird
DBUG_ASSERT(rli->sql_thd == thd);
THD_CHECK_SENTRY(thd);
- rli->sql_thd = 0;
+ rli->sql_thd= 0;
pthread_mutex_lock(&LOCK_thread_count);
THD_CHECK_SENTRY(thd);
delete thd;
@@ -2056,16 +2224,17 @@ static int process_io_create_file(MASTER_INFO* mi, Create_file_log_event* cev)
bool cev_not_written;
THD* thd;
NET* net = &mi->mysql->net;
+ DBUG_ENTER("process_io_create_file");
if (unlikely(!cev->is_valid()))
- return 1;
+ DBUG_RETURN(1);
/*
TODO: fix to honor table rules, not only db rules
*/
if (!db_ok(cev->db, replicate_do_db, replicate_ignore_db))
{
skip_load_data_infile(net);
- return 0;
+ DBUG_RETURN(0);
}
DBUG_ASSERT(cev->inited_from_old);
thd = mi->io_thd;
@@ -2140,19 +2309,25 @@ relay log");
}
error=0;
err:
- return error;
+ DBUG_RETURN(error);
}
-// We assume we already locked mi->data_lock
+/*
+ We assume we already locked mi->data_lock
+*/
+
static int process_io_rotate(MASTER_INFO* mi, Rotate_log_event* rev)
{
+ DBUG_ENTER("process_io_rotate");
+
if (unlikely(!rev->is_valid()))
- return 1;
- DBUG_ASSERT(rev->ident_len<sizeof(mi->master_log_name));
+ DBUG_RETURN(1);
+ DBUG_ASSERT(rev->ident_len < sizeof(mi->master_log_name));
memcpy(mi->master_log_name,rev->new_log_ident,
rev->ident_len);
mi->master_log_name[rev->ident_len] = 0;
mi->master_log_pos = rev->pos;
+ DBUG_PRINT("info", ("master_log_pos: %d", (ulong) mi->master_log_pos));
#ifndef DBUG_OFF
/*
If we do not do this, we will be getting the first
@@ -2161,7 +2336,7 @@ static int process_io_rotate(MASTER_INFO* mi, Rotate_log_event* rev)
if (disconnect_slave_event_count)
events_till_disconnect++;
#endif
- return 0;
+ DBUG_RETURN(0);
}
/*
@@ -2178,6 +2353,8 @@ static int queue_old_event(MASTER_INFO *mi, const char *buf,
bool inc_pos = 1;
bool processed_stop_event = 0;
char* tmp_buf = 0;
+ DBUG_ENTER("queue_old_event");
+
/* if we get Load event, we need to pass a non-reusable buffer
to read_log_event, so we do a trick
*/
@@ -2186,7 +2363,7 @@ static int queue_old_event(MASTER_INFO *mi, const char *buf,
if (unlikely(!(tmp_buf=(char*)my_malloc(event_len+1,MYF(MY_WME)))))
{
sql_print_error("Slave I/O: out of memory for Load event");
- return 1;
+ DBUG_RETURN(1);
}
memcpy(tmp_buf,buf,event_len);
tmp_buf[event_len]=0; // Create_file constructor wants null-term buffer
@@ -2199,8 +2376,8 @@ static int queue_old_event(MASTER_INFO *mi, const char *buf,
sql_print_error("Read invalid event from master: '%s',\
master could be corrupt but a more likely cause of this is a bug",
errmsg);
- my_free((char*)tmp_buf, MYF(MY_ALLOW_ZERO_PTR));
- return 1;
+ my_free((char*) tmp_buf, MYF(MY_ALLOW_ZERO_PTR));
+ DBUG_RETURN(1);
}
pthread_mutex_lock(&mi->data_lock);
ev->log_pos = mi->master_log_pos;
@@ -2211,7 +2388,7 @@ static int queue_old_event(MASTER_INFO *mi, const char *buf,
delete ev;
pthread_mutex_unlock(&mi->data_lock);
DBUG_ASSERT(!tmp_buf);
- return 1;
+ DBUG_RETURN(1);
}
mi->ignore_stop_event=1;
inc_pos = 0;
@@ -2224,10 +2401,11 @@ static int queue_old_event(MASTER_INFO *mi, const char *buf,
int error = process_io_create_file(mi,(Create_file_log_event*)ev);
delete ev;
mi->master_log_pos += event_len;
+ DBUG_PRINT("info", ("master_log_pos: %d", (ulong) mi->master_log_pos));
pthread_mutex_unlock(&mi->data_lock);
DBUG_ASSERT(tmp_buf);
my_free((char*)tmp_buf, MYF(0));
- return error;
+ DBUG_RETURN(error);
}
default:
mi->ignore_stop_event=0;
@@ -2240,18 +2418,19 @@ static int queue_old_event(MASTER_INFO *mi, const char *buf,
delete ev;
pthread_mutex_unlock(&mi->data_lock);
DBUG_ASSERT(!tmp_buf);
- return 1;
+ DBUG_RETURN(1);
}
mi->rli.relay_log.harvest_bytes_written(&mi->rli.log_space_total);
}
delete ev;
if (likely(inc_pos))
mi->master_log_pos += event_len;
+ DBUG_PRINT("info", ("master_log_pos: %d", (ulong) mi->master_log_pos));
if (unlikely(processed_stop_event))
mi->ignore_stop_event=1;
pthread_mutex_unlock(&mi->data_lock);
DBUG_ASSERT(!tmp_buf);
- return 0;
+ DBUG_RETURN(0);
}
/*
@@ -2264,8 +2443,10 @@ int queue_event(MASTER_INFO* mi,const char* buf, ulong event_len)
int error=0;
bool inc_pos = 1;
bool processed_stop_event = 0;
+ DBUG_ENTER("queue_event");
+
if (mi->old_format)
- return queue_old_event(mi,buf,event_len);
+ DBUG_RETURN(queue_old_event(mi,buf,event_len));
pthread_mutex_lock(&mi->data_lock);
@@ -2281,7 +2462,7 @@ int queue_event(MASTER_INFO* mi,const char* buf, ulong event_len)
{
Rotate_log_event rev(buf,event_len,0);
if (unlikely(process_io_rotate(mi,&rev)))
- return 1;
+ DBUG_RETURN(1);
inc_pos=0;
mi->ignore_stop_event=1;
break;
@@ -2296,23 +2477,26 @@ int queue_event(MASTER_INFO* mi,const char* buf, ulong event_len)
{
if (likely(inc_pos))
mi->master_log_pos += event_len;
+ DBUG_PRINT("info", ("master_log_pos: %d", (ulong) mi->master_log_pos));
mi->rli.relay_log.harvest_bytes_written(&mi->rli.log_space_total);
}
if (unlikely(processed_stop_event))
mi->ignore_stop_event=1;
pthread_mutex_unlock(&mi->data_lock);
- return error;
+ DBUG_RETURN(error);
}
void end_relay_log_info(RELAY_LOG_INFO* rli)
{
+ DBUG_ENTER("end_relay_log_info");
+
if (!rli->inited)
- return;
+ DBUG_VOID_RETURN;
if (rli->info_fd >= 0)
{
end_io_cache(&rli->info_file);
- (void)my_close(rli->info_fd, MYF(MY_WME));
+ (void) my_close(rli->info_fd, MYF(MY_WME));
rli->info_fd = -1;
}
if (rli->cur_log_fd >= 0)
@@ -2324,12 +2508,13 @@ void end_relay_log_info(RELAY_LOG_INFO* rli)
rli->inited = 0;
rli->log_pos_current=0;
rli->relay_log.close(1);
+ DBUG_VOID_RETURN;
}
/* try to connect until successful or slave killed */
static int safe_connect(THD* thd, MYSQL* mysql, MASTER_INFO* mi)
{
- return connect_to_master(thd, mysql, mi, 0);
+ return connect_to_master(thd, mysql, mi, 0, 0);
}
@@ -2339,55 +2524,69 @@ static int safe_connect(THD* thd, MYSQL* mysql, MASTER_INFO* mi)
*/
static int connect_to_master(THD* thd, MYSQL* mysql, MASTER_INFO* mi,
- bool reconnect)
+ bool reconnect, bool suppress_warnings)
{
int slave_was_killed;
int last_errno= -2; // impossible error
ulong err_count=0;
char llbuff[22];
+ DBUG_ENTER("connect_to_master");
#ifndef DBUG_OFF
events_till_disconnect = disconnect_slave_event_count;
#endif
+ uint client_flag=0;
+ if (opt_slave_compressed_protocol)
+ client_flag=CLIENT_COMPRESS; /* We will use compression */
+
while (!(slave_was_killed = io_slave_killed(thd,mi)) &&
- (reconnect ? mc_mysql_reconnect(mysql) != 0 :
+ (reconnect ? mc_mysql_reconnect(mysql) != 0:
!mc_mysql_connect(mysql, mi->host, mi->user, mi->password, 0,
- mi->port, 0, 0)))
+ mi->port, 0, client_flag,
+ thd->variables.net_read_timeout)))
{
/* Don't repeat last error */
if (mc_mysql_errno(mysql) != last_errno)
{
- sql_print_error("Slave I/O thread: error connecting to master \
+ last_errno=mc_mysql_errno(mysql);
+ suppress_warnings= 0;
+ sql_print_error("Slave I/O thread: error %s to master \
'%s@%s:%d': \
-%s, last_errno=%d, retry in %d sec",mi->user,mi->host,mi->port,
- mc_mysql_error(mysql), last_errno=mc_mysql_errno(mysql),
- mi->connect_retry);
+Error: '%s' errno: %d retry-time: %d retries: %d",
+ (reconnect ? "reconnecting" : "connecting"),
+ mi->user,mi->host,mi->port,
+ mc_mysql_error(mysql), last_errno,
+ mi->connect_retry,
+ master_retry_count);
}
- safe_sleep(thd,mi->connect_retry,(CHECK_KILLED_FUNC)io_slave_killed,
- (void*)mi);
/*
By default we try forever. The reason is that failure will trigger
master election, so if the user did not set master_retry_count we
- do not want to have electioin triggered on the first failure to
+ do not want to have election triggered on the first failure to
connect
*/
- if (master_retry_count && err_count++ == master_retry_count)
+ if (++err_count == master_retry_count)
{
slave_was_killed=1;
if (reconnect)
change_rpl_status(RPL_ACTIVE_SLAVE,RPL_LOST_SOLDIER);
break;
}
+ safe_sleep(thd,mi->connect_retry,(CHECK_KILLED_FUNC)io_slave_killed,
+ (void*)mi);
}
if (!slave_was_killed)
{
if (reconnect)
- sql_print_error("Slave: connected to master '%s@%s:%d',\
+ {
+ if (!suppress_warnings && global_system_variables.log_warnings)
+ sql_print_error("Slave: connected to master '%s@%s:%d',\
replication resumed in log '%s' at position %s", mi->user,
- mi->host, mi->port,
- IO_RPL_LOG_NAME,
- llstr(mi->master_log_pos,llbuff));
+ mi->host, mi->port,
+ IO_RPL_LOG_NAME,
+ llstr(mi->master_log_pos,llbuff));
+ }
else
{
change_rpl_status(RPL_IDLE_SLAVE,RPL_ACTIVE_SLAVE);
@@ -2398,8 +2597,8 @@ replication resumed in log '%s' at position %s", mi->user,
thd->set_active_vio(mysql->net.vio);
#endif
}
-
- return slave_was_killed;
+ DBUG_PRINT("exit",("slave_was_killed: %d", slave_was_killed));
+ DBUG_RETURN(slave_was_killed);
}
@@ -2408,38 +2607,91 @@ replication resumed in log '%s' at position %s", mi->user,
master_retry_count times
*/
-static int safe_reconnect(THD* thd, MYSQL* mysql, MASTER_INFO* mi)
+static int safe_reconnect(THD* thd, MYSQL* mysql, MASTER_INFO* mi,
+ bool suppress_warnings)
{
- return connect_to_master(thd, mysql, mi, 1);
+ return connect_to_master(thd, mysql, mi, 1, suppress_warnings);
}
-int flush_relay_log_info(RELAY_LOG_INFO* rli)
+
+/*
+ Store the file and position where the execute-slave thread are in the
+ relay log.
+
+ SYNOPSIS
+ flush_relay_log_info()
+ rli Relay log information
+
+ NOTES
+ - As this is only called by the slave thread, we don't need to
+ have a lock on this.
+ - If there is an active transaction, then we don't update the position
+ in the relay log. This is to ensure that we re-execute statements
+ if we die in the middle of an transaction that was rolled back.
+ - As a transaction never spans binary logs, we don't have to handle the
+ case where we do a relay-log-rotation in the middle of the transaction.
+ If this would not be the case, we would have to ensure that we
+ don't delete the relay log file where the transaction started when
+ we switch to a new relay log file.
+
+ TODO
+ - Change the log file information to a binary format to avoid calling
+ longlong2str.
+
+ RETURN VALUES
+ 0 ok
+ 1 write error
+*/
+
+bool flush_relay_log_info(RELAY_LOG_INFO* rli)
{
- register IO_CACHE* file = &rli->info_file;
- char lbuf[22],lbuf1[22];
-
+ bool error=0;
+ IO_CACHE *file = &rli->info_file;
+ char buff[FN_REFLEN*2+22*2+4], *pos;
+
+ /* sql_thd is not set when calling from init_slave() */
+ if ((rli->sql_thd && rli->sql_thd->options & OPTION_BEGIN))
+ return 0; // Wait for COMMIT
+
my_b_seek(file, 0L);
- my_b_printf(file, "%s\n%s\n%s\n%s\n",
- rli->relay_log_name, llstr(rli->relay_log_pos, lbuf),
- rli->master_log_name, llstr(rli->master_log_pos, lbuf1)
- );
- flush_io_cache(file);
- flush_io_cache(rli->cur_log);
- return 0;
+ pos=strmov(buff, rli->relay_log_name);
+ *pos++='\n';
+ pos=longlong2str(rli->relay_log_pos, pos, 10);
+ *pos++='\n';
+ pos=strmov(pos, rli->master_log_name);
+ *pos++='\n';
+ pos=longlong2str(rli->master_log_pos, pos, 10);
+ *pos='\n';
+ if (my_b_write(file, (byte*) buff, (ulong) (pos-buff)+1))
+ error=1;
+ if (flush_io_cache(file))
+ error=1;
+ if (flush_io_cache(rli->cur_log)) // QQ Why this call ?
+ error=1;
+ return error;
}
-IO_CACHE* reopen_relay_log(RELAY_LOG_INFO* rli, const char** errmsg)
+
+/*
+ This function is called when we notice that the current "hot" log
+ got rotated under our feet.
+*/
+
+static IO_CACHE *reopen_relay_log(RELAY_LOG_INFO *rli, const char **errmsg)
{
DBUG_ASSERT(rli->cur_log != &rli->cache_buf);
- IO_CACHE* cur_log = rli->cur_log=&rli->cache_buf;
DBUG_ASSERT(rli->cur_log_fd == -1);
+ DBUG_ENTER("reopen_relay_log");
+
+ IO_CACHE *cur_log = rli->cur_log=&rli->cache_buf;
if ((rli->cur_log_fd=open_binlog(cur_log,rli->relay_log_name,
errmsg)) <0)
- return 0;
+ DBUG_RETURN(0);
my_b_seek(cur_log,rli->relay_log_pos);
- return cur_log;
+ DBUG_RETURN(cur_log);
}
+
Log_event* next_event(RELAY_LOG_INFO* rli)
{
Log_event* ev;
@@ -2448,6 +2700,7 @@ Log_event* next_event(RELAY_LOG_INFO* rli)
const char* errmsg=0;
THD* thd = rli->sql_thd;
bool was_killed;
+ DBUG_ENTER("next_event");
DBUG_ASSERT(thd != 0);
/*
@@ -2459,16 +2712,18 @@ Log_event* next_event(RELAY_LOG_INFO* rli)
*/
pthread_mutex_lock(&rli->data_lock);
- for (; !(was_killed=sql_slave_killed(thd,rli)) ;)
+ while (!sql_slave_killed(thd,rli))
{
/*
We can have two kinds of log reading:
- hot_log - rli->cur_log points at the IO_CACHE of relay_log, which
- is actively being updated by the I/O thread. We need to be careful
- in this case and make sure that we are not looking at a stale log that
- has already been rotated. If it has been, we reopen the log
- the other case is much simpler - we just have a read only log that
- nobody else will be updating.
+ hot_log:
+ rli->cur_log points at the IO_CACHE of relay_log, which
+ is actively being updated by the I/O thread. We need to be careful
+ in this case and make sure that we are not looking at a stale log that
+ has already been rotated. If it has been, we reopen the log.
+
+ The other case is much simpler:
+ We just have a read only log that nobody else will be updating.
*/
bool hot_log;
if ((hot_log = (cur_log != &rli->cache_buf)))
@@ -2477,43 +2732,43 @@ Log_event* next_event(RELAY_LOG_INFO* rli)
pthread_mutex_lock(log_lock);
/*
- Reading cur_log->init_count here is safe because the log will only
+ Reading xxx_file_id is safe because the log will only
be rotated when we hold relay_log.LOCK_log
*/
- if (cur_log->init_count != rli->cur_log_init_count)
+ if (rli->relay_log.get_open_count() != rli->cur_log_old_open_count)
{
- if (!(cur_log=reopen_relay_log(rli,&errmsg)))
- {
- pthread_mutex_unlock(log_lock);
+ // The master has switched to a new log file; Reopen the old log file
+ cur_log=reopen_relay_log(rli, &errmsg);
+ pthread_mutex_unlock(log_lock);
+ if (!cur_log) // No more log files
goto err;
- }
- pthread_mutex_unlock(log_lock);
- hot_log=0;
+ hot_log=0; // Using old binary log
}
}
- DBUG_ASSERT(my_b_tell(cur_log) >= 4);
+ DBUG_ASSERT(my_b_tell(cur_log) >= BIN_LOG_HEADER_SIZE);
DBUG_ASSERT(my_b_tell(cur_log) == rli->relay_log_pos + rli->pending);
- /* relay log is always in new format - if the master is 3.23, the
- I/O thread will convert the format for us
+ /*
+ Relay log is always in new format - if the master is 3.23, the
+ I/O thread will convert the format for us
*/
- if ((ev=Log_event::read_log_event(cur_log,0,(bool)0/*new format*/)))
+ if ((ev=Log_event::read_log_event(cur_log,0,(bool)0 /* new format */)))
{
DBUG_ASSERT(thd==rli->sql_thd);
if (hot_log)
pthread_mutex_unlock(log_lock);
pthread_mutex_unlock(&rli->data_lock);
- return ev;
+ DBUG_RETURN(ev);
}
DBUG_ASSERT(thd==rli->sql_thd);
- if (opt_reckless_slave)
+ if (opt_reckless_slave) // For mysql-test
cur_log->error = 0;
- if ( cur_log->error < 0)
+ if (cur_log->error < 0)
{
errmsg = "slave SQL thread aborted because of I/O error";
+ if (hot_log)
+ pthread_mutex_unlock(log_lock);
goto err;
}
-
-
if (!cur_log->error) /* EOF */
{
/*
@@ -2523,119 +2778,121 @@ Log_event* next_event(RELAY_LOG_INFO* rli)
*/
if (hot_log)
{
- DBUG_ASSERT(cur_log->init_count == rli->cur_log_init_count);
+ DBUG_ASSERT(rli->relay_log.get_open_count() == rli->cur_log_old_open_count);
/*
We can, and should release data_lock while we are waiting for
update. If we do not, show slave status will block
*/
pthread_mutex_unlock(&rli->data_lock);
-
- /*
- IMPORTANT: note that wait_for_update will unlock LOCK_log, but
- expects the caller to lock it
- */
+ /* Note that wait_for_update unlocks lock_log ! */
rli->relay_log.wait_for_update(rli->sql_thd);
// re-acquire data lock since we released it earlier
pthread_mutex_lock(&rli->data_lock);
continue;
}
+ /*
+ If the log was not hot, we need to move to the next log in
+ sequence. The next log could be hot or cold, we deal with both
+ cases separately after doing some common initialization
+ */
+ end_io_cache(cur_log);
+ DBUG_ASSERT(rli->cur_log_fd >= 0);
+ my_close(rli->cur_log_fd, MYF(MY_WME));
+ rli->cur_log_fd = -1;
+
+ /*
+ TODO: make skip_log_purge a start-up option. At this point this
+ is not critical priority
+ */
+ if (!rli->skip_log_purge)
+ {
+ // purge_first_log will properly set up relay log coordinates in rli
+ if (rli->relay_log.purge_first_log(rli))
+ {
+ errmsg = "Error purging processed log";
+ goto err;
+ }
+ }
else
{
/*
- If the log was not hot, we need to move to the next log in
- sequence. The next log could be hot or cold, we deal with both
- cases separately after doing some common initialization
+ If hot_log is set, then we already have a lock on
+ LOCK_log. If not, we have to get the lock.
+
+ According to Sasha, the only time this code will ever be executed
+ is if we are recovering from a bug.
*/
- end_io_cache(cur_log);
- DBUG_ASSERT(rli->cur_log_fd >= 0);
- my_close(rli->cur_log_fd, MYF(MY_WME));
- rli->cur_log_fd = -1;
-
- // TODO: make skip_log_purge a start-up option. At this point this
- // is not critical priority
- if (!rli->skip_log_purge)
- {
- // purge_first_log will properly set up relay log coordinates in rli
- if (rli->relay_log.purge_first_log(rli))
- {
- errmsg = "Error purging processed log";
- goto err;
- }
- }
- else
+ if (rli->relay_log.find_next_log(&rli->linfo, !hot_log))
{
- // TODO: verify that no lock is ok here. At this point, if we
- // get this wrong, this is actually no big deal - the only time
- // this code will ever be executed is if we are recovering from
- // a bug when a full reload of the slave is not feasible or
- // desirable.
- if (rli->relay_log.find_next_log(&rli->linfo,0/*no lock*/))
- {
- errmsg = "error switching to the next log";
- goto err;
- }
- rli->relay_log_pos = 4;
- rli->pending=0;
- strnmov(rli->relay_log_name,rli->linfo.log_file_name,
- sizeof(rli->relay_log_name));
- flush_relay_log_info(rli);
+ errmsg = "error switching to the next log";
+ goto err;
}
+ rli->relay_log_pos = BIN_LOG_HEADER_SIZE;
+ rli->pending=0;
+ strmake(rli->relay_log_name,rli->linfo.log_file_name,
+ sizeof(rli->relay_log_name)-1);
+ flush_relay_log_info(rli);
+ }
- // next log is hot
- if (rli->relay_log.is_active(rli->linfo.log_file_name))
- {
+ // next log is hot
+ if (rli->relay_log.is_active(rli->linfo.log_file_name))
+ {
#ifdef EXTRA_DEBUG
- sql_print_error("next log '%s' is currently active",
- rli->linfo.log_file_name);
+ sql_print_error("next log '%s' is currently active",
+ rli->linfo.log_file_name);
#endif
- rli->cur_log = cur_log = rli->relay_log.get_log_file();
- rli->cur_log_init_count = cur_log->init_count;
- DBUG_ASSERT(rli->cur_log_fd == -1);
+ rli->cur_log= cur_log= rli->relay_log.get_log_file();
+ rli->cur_log_old_open_count= rli->relay_log.get_open_count();
+ DBUG_ASSERT(rli->cur_log_fd == -1);
- /*
- Read pointer has to be at the start since we are the only
- reader
- */
- if (check_binlog_magic(cur_log,&errmsg))
- goto err;
- continue;
- }
/*
- if we get here, the log was not hot, so we will have to
- open it ourselves
+ Read pointer has to be at the start since we are the only
+ reader
*/
-#ifdef EXTRA_DEBUG
- sql_print_error("next log '%s' is not active",
- rli->linfo.log_file_name);
-#endif
- // open_binlog() will check the magic header
- if ((rli->cur_log_fd=open_binlog(cur_log,rli->linfo.log_file_name,
- &errmsg)) <0)
+ if (check_binlog_magic(cur_log,&errmsg))
goto err;
+ continue;
}
+ /*
+ if we get here, the log was not hot, so we will have to
+ open it ourselves
+ */
+#ifdef EXTRA_DEBUG
+ sql_print_error("next log '%s' is not active",
+ rli->linfo.log_file_name);
+#endif
+ // open_binlog() will check the magic header
+ if ((rli->cur_log_fd=open_binlog(cur_log,rli->linfo.log_file_name,
+ &errmsg)) <0)
+ goto err;
}
- else // read failed with a non-EOF error
+ else
{
- // TODO: come up with something better to handle this error
+ /*
+ Read failed with a non-EOF error.
+ TODO: come up with something better to handle this error
+ */
+ if (hot_log)
+ pthread_mutex_unlock(log_lock);
sql_print_error("Slave SQL thread: I/O error reading \
-event(errno=%d,cur_log->error=%d)",
+event(errno: %d cur_log->error: %d)",
my_errno,cur_log->error);
// set read position to the beginning of the event
my_b_seek(cur_log,rli->relay_log_pos+rli->pending);
/* otherwise, we have had a partial read */
- /* TODO; see if there is a way to do this without this goto */
errmsg = "Aborting slave SQL thread because of partial event read";
- goto err;
+ break; // To end of function
}
-
}
- if (!errmsg && was_killed)
+ if (!errmsg && global_system_variables.log_warnings)
errmsg = "slave SQL thread was killed";
+
err:
pthread_mutex_unlock(&rli->data_lock);
- sql_print_error("Error reading relay log event: %s", errmsg);
- return 0;
+ if (errmsg)
+ sql_print_error("Error reading relay log event: %s", errmsg);
+ DBUG_RETURN(0);
}
diff --git a/sql/slave.h b/sql/slave.h
index 16735891815..b527aceb432 100644
--- a/sql/slave.h
+++ b/sql/slave.h
@@ -30,8 +30,9 @@ extern bool use_slave_mask;
extern char* slave_load_tmpdir;
extern my_string master_info_file,relay_log_info_file;
extern my_string opt_relay_logname, opt_relaylog_index_name;
-extern bool opt_skip_slave_start, opt_reckless_slave;
-extern ulong relay_log_space_limit;
+extern my_bool opt_skip_slave_start, opt_reckless_slave;
+extern my_bool opt_log_slave_updates;
+extern ulonglong relay_log_space_limit;
struct st_master_info;
/*
@@ -70,39 +71,31 @@ struct st_master_info;
typedef struct st_relay_log_info
{
/*** The following variables can only be read when protect by data lock ****/
+
/*
info_fd - file descriptor of the info file. set only during
initialization or clean up - safe to read anytime
cur_log_fd - file descriptor of the current read relay log
*/
File info_fd,cur_log_fd;
- // name of current read relay log
+ /* name of current read relay log */
char relay_log_name[FN_REFLEN];
- // master log name corresponding to current read position
+ /* master log name corresponding to current read position */
char master_log_name[FN_REFLEN];
- // original log position of last processed event
+ /* original log position of last processed event */
volatile my_off_t master_log_pos;
/*
- current offset in the relay log.
- pending - in some cases we do not increment offset immediately after
- processing an event, because the following event needs to be processed
- atomically together with this one ( so far, there is only one type of
- such event - Intvar_event that sets auto_increment value). However, once
- both events have been processed, we need to increment by the cumulative
- offset. pending stored the extra offset to be added to the position.
+ Protected with internal locks.
+ Must get data_lock when resetting the logs.
*/
- ulonglong relay_log_pos, pending;
-
- // protected with internal locks
- // must get data_lock when resetting the logs
MYSQL_LOG relay_log;
LOG_INFO linfo;
IO_CACHE cache_buf,*cur_log;
- /*** The following variables are safe to read any time ***/
+ /* The following variables are safe to read any time */
- // IO_CACHE of the info file - set only during init or end
+ /* IO_CACHE of the info file - set only during init or end */
IO_CACHE info_file;
/*
@@ -125,19 +118,34 @@ typedef struct st_relay_log_info
*/
pthread_cond_t start_cond, stop_cond, data_cond;
- // if not set, the value of other members of the structure are undefined
- bool inited;
-
- // parent master info structure
+ /* parent master info structure */
struct st_master_info *mi;
/*
Needed to deal properly with cur_log getting closed and re-opened with
a different log under our feet
*/
- int cur_log_init_count;
+ uint32 cur_log_old_open_count;
- volatile bool abort_slave, slave_running;
+ /*
+ Current offset in the relay log.
+ pending - in some cases we do not increment offset immediately after
+ processing an event, because the following event needs to be processed
+ atomically together with this one ( so far, there is only one type of
+ such event - Intvar_event that sets auto_increment value). However, once
+ both events have been processed, we need to increment by the cumulative
+ offset. pending stored the extra offset to be added to the position.
+ */
+ ulonglong relay_log_pos, pending;
+ ulonglong log_space_limit,log_space_total;
+
+ /*
+ InnoDB internally stores the master log position it has processed
+ so far; the position to store is really the sum of
+ pos + pending + event_len here since we must store the pos of the
+ END of the current log event
+ */
+ int event_len;
/*
Needed for problems when slave stops and we want to restart it
@@ -145,50 +153,54 @@ typedef struct st_relay_log_info
errors, and have been manually applied by DBA already.
*/
volatile uint32 slave_skip_counter;
+ volatile ulong abort_pos_wait; /* Incremented on change master */
+ volatile ulong slave_run_id; /* Incremented on slave start */
+ pthread_mutex_t log_space_lock;
+ pthread_cond_t log_space_cond;
+ THD * sql_thd;
+ int last_slave_errno;
#ifndef DBUG_OFF
int events_till_abort;
#endif
- int last_slave_errno;
char last_slave_error[MAX_SLAVE_ERRMSG];
- THD* sql_thd;
+
+ /* if not set, the value of other members of the structure are undefined */
+ bool inited;
+ volatile bool abort_slave, slave_running;
bool log_pos_current;
- bool abort_pos_wait;
bool skip_log_purge;
- ulonglong log_space_limit,log_space_total;
- pthread_mutex_t log_space_lock;
- pthread_cond_t log_space_cond;
- st_relay_log_info():info_fd(-1),cur_log_fd(-1),inited(0),
- cur_log_init_count(0),
- abort_slave(0),slave_running(0),
- log_pos_current(0),abort_pos_wait(0),
- skip_log_purge(0)
- {
- relay_log_name[0] = master_log_name[0] = 0;
- bzero(&info_file,sizeof(info_file));
- pthread_mutex_init(&run_lock, MY_MUTEX_INIT_FAST);
- pthread_mutex_init(&data_lock, MY_MUTEX_INIT_FAST);
- pthread_mutex_init(&log_space_lock, MY_MUTEX_INIT_FAST);
- pthread_cond_init(&data_cond, NULL);
- pthread_cond_init(&start_cond, NULL);
- pthread_cond_init(&stop_cond, NULL);
- pthread_cond_init(&log_space_cond, NULL);
- }
+ st_relay_log_info()
+ :info_fd(-1),cur_log_fd(-1), cur_log_old_open_count(0), abort_pos_wait(0),
+ slave_run_id(0), inited(0), abort_slave(0), slave_running(0),
+ log_pos_current(0), skip_log_purge(0)
+ {
+ relay_log_name[0] = master_log_name[0] = 0;
+ bzero(&info_file,sizeof(info_file));
+ bzero(&cache_buf, sizeof(cache_buf));
+ pthread_mutex_init(&run_lock, MY_MUTEX_INIT_FAST);
+ pthread_mutex_init(&data_lock, MY_MUTEX_INIT_FAST);
+ pthread_mutex_init(&log_space_lock, MY_MUTEX_INIT_FAST);
+ pthread_cond_init(&data_cond, NULL);
+ pthread_cond_init(&start_cond, NULL);
+ pthread_cond_init(&stop_cond, NULL);
+ pthread_cond_init(&log_space_cond, NULL);
+ }
~st_relay_log_info()
- {
- pthread_mutex_destroy(&run_lock);
- pthread_mutex_destroy(&data_lock);
- pthread_mutex_destroy(&log_space_lock);
- pthread_cond_destroy(&data_cond);
- pthread_cond_destroy(&start_cond);
- pthread_cond_destroy(&stop_cond);
- pthread_cond_destroy(&log_space_cond);
- }
+ {
+ pthread_mutex_destroy(&run_lock);
+ pthread_mutex_destroy(&data_lock);
+ pthread_mutex_destroy(&log_space_lock);
+ pthread_cond_destroy(&data_cond);
+ pthread_cond_destroy(&start_cond);
+ pthread_cond_destroy(&stop_cond);
+ pthread_cond_destroy(&log_space_cond);
+ }
inline void inc_pending(ulonglong val)
{
pending += val;
}
- // TODO: this probably needs to be fixed
+ /* TODO: this probably needs to be fixed */
inline void inc_pos(ulonglong val, ulonglong log_pos, bool skip_lock=0)
{
if (!skip_lock)
@@ -203,7 +215,7 @@ typedef struct st_relay_log_info
}
/*
thread safe read of position - not needed if we are in the slave thread,
- but required otherwise
+ but required otherwise as var is a longlong
*/
inline void read_pos(ulonglong& var)
{
@@ -215,40 +227,34 @@ typedef struct st_relay_log_info
int wait_for_pos(THD* thd, String* log_name, ulonglong log_pos);
} RELAY_LOG_INFO;
-/*
- repopen_relay_log() is called when we notice that the current "hot" log
- got rotated under our feet
-*/
-IO_CACHE* reopen_relay_log(RELAY_LOG_INFO* rli, const char** errmsg);
Log_event* next_event(RELAY_LOG_INFO* rli);
-
/*
st_master_info contains information about how to connect to a master,
- current master log name, and current log offset, as well as misc
- control variables
+ current master log name, and current log offset, as well as misc
+ control variables
- st_master_info is initialized once from the master.info file if such
- exists. Otherwise, data members corresponding to master.info fields are
- initialized with defaults specified by master-* options. The initialization
- is done through init_master_info() call.
+ st_master_info is initialized once from the master.info file if such
+ exists. Otherwise, data members corresponding to master.info fields
+ are initialized with defaults specified by master-* options. The
+ initialization is done through init_master_info() call.
- The format of master.info file:
+ The format of master.info file:
- log_name
- log_pos
- master_host
- master_user
- master_pass
- master_port
- master_connect_retry
+ log_name
+ log_pos
+ master_host
+ master_user
+ master_pass
+ master_port
+ master_connect_retry
- To write out the contents of master.info file to disk ( needed every
- time we read and queue data from the master ), a call to
- flush_master_info() is required.
+ To write out the contents of master.info file to disk ( needed every
+ time we read and queue data from the master ), a call to
+ flush_master_info() is required.
- To clean up, call end_master_info()
+ To clean up, call end_master_info()
*/
@@ -257,10 +263,10 @@ typedef struct st_master_info
char master_log_name[FN_REFLEN];
my_off_t master_log_pos;
- File fd;
+ File fd; // we keep the file open, so we need to remember the file pointer
IO_CACHE file;
- // the variables below are needed because we can change masters on the fly
+ /* the variables below are needed because we can change masters on the fly */
char host[HOSTNAME_LENGTH+1];
char user[USERNAME_LENGTH+1];
char password[HASH_PASSWORD_LENGTH+1];
@@ -268,7 +274,7 @@ typedef struct st_master_info
pthread_cond_t data_cond,start_cond,stop_cond;
THD *io_thd;
MYSQL* mysql;
- uint32 file_id; // for 3.23 load data infile
+ uint32 file_id; /* for 3.23 load data infile */
RELAY_LOG_INFO rli;
uint port;
uint connect_retry;
@@ -276,16 +282,18 @@ typedef struct st_master_info
int events_till_abort;
#endif
bool inited;
- bool old_format; // master binlog is in 3.23 format
+ bool old_format; /* master binlog is in 3.23 format */
volatile bool abort_slave, slave_running;
+ volatile ulong slave_run_id;
bool ignore_stop_event;
- st_master_info():fd(-1), io_thd(0), inited(0), old_format(0),abort_slave(0),
- slave_running(0)
+ st_master_info()
+ :fd(-1), io_thd(0), inited(0), old_format(0),abort_slave(0),
+ slave_running(0), slave_run_id(0)
{
host[0] = 0; user[0] = 0; password[0] = 0;
- bzero(&file,sizeof(file));
+ bzero(&file, sizeof(file));
pthread_mutex_init(&run_lock, MY_MUTEX_INIT_FAST);
pthread_mutex_init(&data_lock, MY_MUTEX_INIT_FAST);
pthread_cond_init(&data_cond, NULL);
@@ -334,8 +342,8 @@ typedef struct st_table_rule_ent
int init_slave();
void init_slave_skip_errors(const char* arg);
-int flush_master_info(MASTER_INFO* mi);
-int flush_relay_log_info(RELAY_LOG_INFO* rli);
+bool flush_master_info(MASTER_INFO* mi);
+bool flush_relay_log_info(RELAY_LOG_INFO* rli);
int register_slave_on_master(MYSQL* mysql);
int terminate_slave_threads(MASTER_INFO* mi, int thread_mask,
bool skip_lock = 0);
@@ -355,21 +363,22 @@ int start_slave_threads(bool need_slave_mutex, bool wait_for_start,
int start_slave_thread(pthread_handler h_func, pthread_mutex_t* start_lock,
pthread_mutex_t *cond_lock,
pthread_cond_t* start_cond,
- volatile bool* slave_running,
+ volatile bool *slave_running,
+ volatile ulong *slave_run_id,
MASTER_INFO* mi);
-// If fd is -1, dump to NET
+/* If fd is -1, dump to NET */
int mysql_table_dump(THD* thd, const char* db,
const char* tbl_name, int fd = -1);
-// retrieve non-exitent table from master
+/* retrieve non-exitent table from master */
int fetch_master_table(THD* thd, const char* db_name, const char* table_name,
MASTER_INFO* mi, MYSQL* mysql);
int show_master_info(THD* thd, MASTER_INFO* mi);
int show_binlog_info(THD* thd);
-// See if the query uses any tables that should not be replicated
+/* See if the query uses any tables that should not be replicated */
int tables_ok(THD* thd, TABLE_LIST* tables);
/*
@@ -388,9 +397,10 @@ int check_expected_error(THD* thd, RELAY_LOG_INFO* rli, int error_code);
void skip_load_data_infile(NET* net);
void slave_print_error(RELAY_LOG_INFO* rli,int err_code, const char* msg, ...);
-void end_slave(); // clean up
+void end_slave(); /* clean up */
int init_master_info(MASTER_INFO* mi, const char* master_info_fname,
- const char* slave_info_fname);
+ const char* slave_info_fname,
+ bool abort_if_no_master_info_file);
void end_master_info(MASTER_INFO* mi);
int init_relay_log_info(RELAY_LOG_INFO* rli, const char* info_fname);
void end_relay_log_info(RELAY_LOG_INFO* rli);
@@ -400,13 +410,13 @@ void init_thread_mask(int* mask,MASTER_INFO* mi,bool inverse);
int init_relay_log_pos(RELAY_LOG_INFO* rli,const char* log,ulonglong pos,
bool need_data_lock, const char** errmsg);
-int purge_relay_logs(RELAY_LOG_INFO* rli,bool just_reset,const char** errmsg);
+int purge_relay_logs(RELAY_LOG_INFO* rli, THD *thd, bool just_reset,
+ const char** errmsg);
-extern bool opt_log_slave_updates ;
pthread_handler_decl(handle_slave_io,arg);
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 MASTER_INFO main_mi, *active_mi; /* active_mi for multi-master */
extern volatile int active_mi_in_use;
extern LIST master_list;
extern HASH replicate_do_table, replicate_ignore_table;
@@ -417,7 +427,7 @@ extern bool table_rules_on;
extern int disconnect_slave_event_count, abort_slave_event_count ;
-// the master variables are defaults read from my.cnf or command line
+/* the master variables are defaults read from my.cnf or command line */
extern uint master_port, master_connect_retry, report_port;
extern my_string master_user, master_password, master_host,
master_info_file, relay_log_info_file, report_user, report_host,
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 724af69bdca..1069e779e86 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -29,24 +29,25 @@
#include "sql_acl.h"
#include "hash_filo.h"
#include <m_ctype.h>
+#include <assert.h>
#include <stdarg.h>
-/*
- ACL_HOST is used if no host is specified
- */
-
struct acl_host_and_ip
{
char *hostname;
long ip,ip_mask; // Used with masked ip:s
};
+
class ACL_ACCESS {
public:
ulong sort;
- uint access;
+ ulong access;
};
+
+/* ACL_HOST is used if no host is specified */
+
class ACL_HOST :public ACL_ACCESS
{
public:
@@ -54,6 +55,7 @@ public:
char *db;
};
+
class ACL_USER :public ACL_ACCESS
{
public:
@@ -68,6 +70,7 @@ public:
#endif /* HAVE_OPENSSL */
};
+
class ACL_DB :public ACL_ACCESS
{
public:
@@ -75,14 +78,16 @@ public:
char *user,*db;
};
+
class acl_entry :public hash_filo_element
{
public:
- uint access;
+ ulong access;
uint16 length;
char key[1]; // Key will be stored here
};
+
static byte* acl_entry_get_key(acl_entry *entry,uint *length,
my_bool not_used __attribute__((unused)))
{
@@ -100,7 +105,7 @@ static HASH acl_check_hosts, hash_tables;
static DYNAMIC_ARRAY acl_wild_hosts;
static hash_filo *acl_cache;
static uint grant_version=0;
-static uint get_access(TABLE *form,uint fieldnr);
+static ulong get_access(TABLE *form,uint fieldnr);
static int acl_compare(ACL_ACCESS *a,ACL_ACCESS *b);
static ulong get_sort(uint count,...);
static void init_check_host(void);
@@ -195,10 +200,10 @@ int acl_init(bool dont_read_acl_tables)
{
ACL_HOST host;
update_hostname(&host.host,get_field(&mem, table,0));
- host.db=get_field(&mem, table,1);
- host.access=get_access(table,2);
- host.access=fix_rights_for_db(host.access);
- host.sort=get_sort(2,host.host.hostname,host.db);
+ host.db= get_field(&mem, table,1);
+ host.access= get_access(table,2);
+ host.access= fix_rights_for_db(host.access);
+ host.sort= get_sort(2,host.host.hostname,host.db);
#ifndef TO_BE_REMOVED
if (table->fields == 8)
{ // Without grant
@@ -223,6 +228,7 @@ int acl_init(bool dont_read_acl_tables)
protocol_version=9; /* purecov: tested */
}
+ DBUG_PRINT("info",("user table fields: %d",table->fields));
allow_all_hosts=0;
while (!(read_record_info.read_record(&read_record_info)))
{
@@ -231,31 +237,11 @@ int acl_init(bool dont_read_acl_tables)
update_hostname(&user.host,get_field(&mem, table,0));
user.user=get_field(&mem, table,1);
user.password=get_field(&mem, table,2);
-#ifdef HAVE_OPENSSL
- DBUG_PRINT("info",("table->fields=%d",table->fields));
- if (table->fields >= 21) /* From 4.0.0 we have more fields */
- {
- char *ssl_type=get_field(&mem, table,17);
- if (!strcmp(ssl_type, "ANY"))
- user.ssl_type=SSL_TYPE_ANY;
- else if (!strcmp(ssl_type, "X509"))
- user.ssl_type=SSL_TYPE_X509;
- else if (!strcmp(ssl_type, "SPECIFIED"))
- user.ssl_type=SSL_TYPE_SPECIFIED;
- else
- user.ssl_type=SSL_TYPE_NONE;
- user.ssl_cipher=get_field(&mem, table, 18);
- user.x509_issuer=get_field(&mem, table, 19);
- user.x509_subject=get_field(&mem, table, 20);
- }
- else
- user.ssl_type=SSL_TYPE_NONE;
-#endif /* HAVE_OPENSSL */
if (user.password && (length=(uint) strlen(user.password)) == 8 &&
protocol_version == PROTOCOL_VERSION)
{
sql_print_error(
- "Found old style password for user '%s'. Ignoring user. (You may want to restart using --old-protocol)",
+ "Found old style password for user '%s'. Ignoring user. (You may want to restart mysqld using --old-protocol)",
user.user ? user.user : ""); /* purecov: tested */
}
else if (length % 8) // This holds true for passwords
@@ -264,33 +250,60 @@ int acl_init(bool dont_read_acl_tables)
"Found invalid password for user: '%s@%s'; Ignoring user",
user.user ? user.user : "",
user.host.hostname ? user.host.hostname : ""); /* purecov: tested */
- continue; /* purecov: tested */
+ continue; /* purecov: tested */
}
get_salt_from_password(user.salt,user.password);
- user.access=get_access(table,3);
+ user.access=get_access(table,3) & GLOBAL_ACLS;
user.sort=get_sort(2,user.host.hostname,user.user);
- user.hostname_length=user.host.hostname ? (uint) strlen(user.host.hostname) : 0;
- if (table->fields >=23)
+ user.hostname_length= (user.host.hostname ?
+ (uint) strlen(user.host.hostname) : 0);
+ if (table->fields >= 31) /* Starting from 4.0.2 we have more fields */
{
- /* Table has new MySQL usage limits */
- char *ptr = get_field(&mem, table, 21);
+#ifdef HAVE_OPENSSL
+ char *ssl_type=get_field(&mem, table, 24);
+ if (!ssl_type)
+ user.ssl_type=SSL_TYPE_NONE;
+ else if (!strcmp(ssl_type, "ANY"))
+ user.ssl_type=SSL_TYPE_ANY;
+ else if (!strcmp(ssl_type, "X509"))
+ user.ssl_type=SSL_TYPE_X509;
+ else /* !strcmp(ssl_type, "SPECIFIED") */
+ user.ssl_type=SSL_TYPE_SPECIFIED;
+
+ user.ssl_cipher= get_field(&mem, table, 25);
+ user.x509_issuer= get_field(&mem, table, 26);
+ user.x509_subject= get_field(&mem, table, 27);
+#endif
+ char *ptr = get_field(&mem, table, 28);
user.user_resource.questions=atoi(ptr);
- ptr = get_field(&mem, table, 22);
+ ptr = get_field(&mem, table, 29);
user.user_resource.updates=atoi(ptr);
- ptr = get_field(&mem, table, 23);
+ ptr = get_field(&mem, table, 30);
user.user_resource.connections=atoi(ptr);
- if (user.user_resource.questions || user.user_resource.updates || user.user_resource.connections)
+ if (user.user_resource.questions || user.user_resource.updates ||
+ user.user_resource.connections)
mqh_used=1;
}
else
+ {
+#ifdef HAVE_OPENSSL
+ user.ssl_type=SSL_TYPE_NONE;
+#endif
bzero(&(user.user_resource),sizeof(user.user_resource));
#ifndef TO_BE_REMOVED
- if (table->fields <= 13)
- { // Without grant
- if (user.access & CREATE_ACL)
- user.access|=REFERENCES_ACL | INDEX_ACL | ALTER_ACL;
- }
+ if (table->fields <= 13)
+ { // Without grant
+ if (user.access & CREATE_ACL)
+ user.access|=REFERENCES_ACL | INDEX_ACL | ALTER_ACL;
+ }
+ /* Convert old privileges */
+ user.access|= LOCK_TABLES_ACL | CREATE_TMP_ACL | SHOW_DB_ACL;
+ if (user.access & FILE_ACL)
+ user.access|= REPL_CLIENT_ACL | REPL_SLAVE_ACL;
+ if (user.access & PROCESS_ACL)
+ user.access|= SUPER_ACL | EXECUTE_ACL;
#endif
+ }
VOID(push_dynamic(&acl_users,(gptr) &user));
if (!user.host.hostname || user.host.hostname[0] == wild_many &&
!user.host.hostname[1])
@@ -308,6 +321,11 @@ int acl_init(bool dont_read_acl_tables)
ACL_DB db;
update_hostname(&db.host,get_field(&mem, table,0));
db.db=get_field(&mem, table,1);
+ if (!db.db)
+ {
+ sql_print_error("Found an entry in the 'db' table with empty database name; Skipped");
+ continue;
+ }
db.user=get_field(&mem, table,2);
db.access=get_access(table,3);
db.access=fix_rights_for_db(db.access);
@@ -401,31 +419,38 @@ void acl_reload(void)
}
-/* Get all access bits from table after fieldnr */
+/*
+ Get all access bits from table after fieldnr
+ We know that the access privileges ends when there is no more fields
+ or the field is not an enum with two elements.
+*/
-static uint get_access(TABLE *form,uint fieldnr)
+static ulong get_access(TABLE *form, uint fieldnr)
{
- uint access_bits=0,bit;
+ ulong access_bits=0,bit;
char buff[2];
String res(buff,sizeof(buff),default_charset_info);
Field **pos;
- for (pos=form->field+fieldnr,bit=1 ; *pos ; pos++ , bit<<=1)
+ for (pos=form->field+fieldnr, bit=1;
+ *pos && (*pos)->real_type() == FIELD_TYPE_ENUM &&
+ ((Field_enum*) (*pos))->typelib->count == 2 ;
+ pos++ , bit<<=1)
{
(*pos)->val_str(&res,&res);
if (my_toupper(system_charset_info, res[0]) == 'Y')
- access_bits|=bit;
+ access_bits|= bit;
}
return access_bits;
}
/*
- return a number which, if sorted 'desc', puts strings in this order:
- no wildcards
- wildcards
- empty string
- */
+ Return a number which, if sorted 'desc', puts strings in this order:
+ no wildcards
+ wildcards
+ empty string
+*/
static ulong get_sort(uint count,...)
{
@@ -470,17 +495,20 @@ static int acl_compare(ACL_ACCESS *a,ACL_ACCESS *b)
Required before connecting to MySQL
*/
-uint acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
- const char *password,const char *message,char **priv_user,
- bool old_ver, USER_RESOURCES *mqh)
+ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
+ const char *password,const char *message,char **priv_user,
+ bool old_ver, USER_RESOURCES *mqh)
{
- uint user_access=NO_ACCESS;
+ ulong user_access=NO_ACCESS;
*priv_user=(char*) user;
- char *ptr=0;
+ DBUG_ENTER("acl_getroot");
bzero(mqh,sizeof(USER_RESOURCES));
if (!initialized)
- return (uint) ~NO_ACCESS; // If no data allow anything /* purecov: tested */
+ {
+ // If no data allow anything
+ DBUG_RETURN((ulong) ~NO_ACCESS); /* purecov: tested */
+ }
VOID(pthread_mutex_lock(&acl_cache->lock));
/*
@@ -507,7 +535,7 @@ uint acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
we check if SSL is required, if user is using SSL and
if X509 certificate attributes are OK
*/
- switch(acl_user->ssl_type) {
+ switch (acl_user->ssl_type) {
case SSL_TYPE_NONE: /* SSL is not required to connect */
user_access=acl_user->access;
break;
@@ -549,40 +577,33 @@ uint acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
if (acl_user->x509_issuer)
{
DBUG_PRINT("info",("checkpoint 3"));
- ptr = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
+ char *ptr = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
DBUG_PRINT("info",("comparing issuers: '%s' and '%s'",
acl_user->x509_issuer, ptr));
- if (!strcmp(acl_user->x509_issuer,ptr))
- user_access=acl_user->access;
- else
+ if (strcmp(acl_user->x509_issuer, ptr))
{
user_access=NO_ACCESS;
free(ptr);
break;
}
+ user_access=acl_user->access;
free(ptr);
}
DBUG_PRINT("info",("checkpoint 4"));
/* X509 subject is specified, we check it .. */
if (acl_user->x509_subject)
{
- ptr = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
+ char *ptr= X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
DBUG_PRINT("info",("comparing subjects: '%s' and '%s'",
acl_user->x509_subject, ptr));
- if (!strcmp(acl_user->x509_subject,ptr))
- user_access=acl_user->access;
- else
- {
+ if (strcmp(acl_user->x509_subject,ptr))
user_access=NO_ACCESS;
- free(ptr);
- break;
- }
+ else
+ user_access=acl_user->access;
free(ptr);
}
- DBUG_PRINT("info",("checkpoint 5"));
break;
}
- DBUG_PRINT("info",("checkpoint 6"));
#else /* HAVE_OPENSSL */
user_access=acl_user->access;
#endif /* HAVE_OPENSSL */
@@ -598,7 +619,7 @@ uint acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
}
}
VOID(pthread_mutex_unlock(&acl_cache->lock));
- return user_access;
+ DBUG_RETURN(user_access);
}
@@ -621,7 +642,7 @@ static void acl_update_user(const char *user, const char *host,
const char *x509_issuer,
const char *x509_subject,
USER_RESOURCES *mqh,
- uint privileges)
+ ulong privileges)
{
for (uint i=0 ; i < acl_users.elements ; i++)
{
@@ -634,7 +655,12 @@ static void acl_update_user(const char *user, const char *host,
acl_user->host.hostname && !strcmp(host,acl_user->host.hostname))
{
acl_user->access=privileges;
- acl_user->user_resource=*mqh;
+ if (mqh->bits & 1)
+ acl_user->user_resource.questions=mqh->questions;
+ if (mqh->bits & 2)
+ acl_user->user_resource.updates=mqh->updates;
+ if (mqh->bits & 4)
+ acl_user->user_resource.connections=mqh->connections;
#ifdef HAVE_OPENSSL
acl_user->ssl_type=ssl_type;
acl_user->ssl_cipher=ssl_cipher;
@@ -665,7 +691,7 @@ static void acl_insert_user(const char *user, const char *host,
const char *x509_issuer,
const char *x509_subject,
USER_RESOURCES *mqh,
- uint privileges)
+ ulong privileges)
{
ACL_USER acl_user;
acl_user.user=strdup_root(&mem,user);
@@ -702,7 +728,7 @@ static void acl_insert_user(const char *user, const char *host,
static void acl_update_db(const char *user, const char *host, const char *db,
- uint privileges)
+ ulong privileges)
{
for (uint i=0 ; i < acl_dbs.elements ; i++)
{
@@ -729,7 +755,7 @@ static void acl_update_db(const char *user, const char *host, const char *db,
static void acl_insert_db(const char *user, const char *host, const char *db,
- uint privileges)
+ ulong privileges)
{
ACL_DB acl_db;
/* The acl_cache mutex is locked by mysql_grant */
@@ -748,13 +774,15 @@ static void acl_insert_db(const char *user, const char *host, const char *db,
** Get privilege for a host, user and db combination
*****************************************************************************/
-uint acl_get(const char *host, const char *ip, const char *bin_ip,
+ulong acl_get(const char *host, const char *ip, const char *bin_ip,
const char *user, const char *db)
{
- uint host_access,db_access,i,key_length;
+ ulong host_access,db_access;
+ uint i,key_length;
db_access=0; host_access= ~0;
char key[ACL_KEY_LENGTH],*tmp_db,*end;
acl_entry *entry;
+ THD *thd= current_thd;
VOID(pthread_mutex_lock(&acl_cache->lock));
memcpy_fixed(&key,bin_ip,sizeof(struct in_addr));
@@ -829,7 +857,7 @@ int wild_case_compare(CHARSET_INFO *cs, const char *str,const char *wildstr)
{
reg3 int flag;
DBUG_ENTER("wild_case_compare");
- DBUG_PRINT("enter",("str='%s', wildstr='%s'",str,wildstr));
+ DBUG_PRINT("enter",("str: '%s' wildstr: '%s'",str,wildstr));
while (*wildstr)
{
while (*wildstr && *wildstr != wild_many && *wildstr != wild_one)
@@ -947,40 +975,63 @@ bool acl_check_host(const char *host, const char *ip)
}
/*****************************************************************************
-** Change password for the user if it's not an anonymous user
-** Note: This should write the error directly to the client!
+ Change password for the user if it's not an anonymous user
+ Note: This should write the error directly to the client!
*****************************************************************************/
-bool change_password(THD *thd, const char *host, const char *user,
- char *new_password)
-{
- uint length=0;
- DBUG_ENTER("change_password");
- DBUG_PRINT("enter",("thd=%x, host='%s', user='%s', new_password='%s'",thd,host,user,new_password));
+/*
+ Check if the user is allowed to change password
+
+ SYNOPSIS:
+ check_change_password()
+ thd THD
+ host hostname for the user
+ user user name
+ RETURN VALUE
+ 0 OK
+ 1 ERROR ; In this case the error is sent to the client.
+*/
+
+bool check_change_password(THD *thd, const char *host, const char *user)
+{
if (!initialized)
{
send_error(&thd->net, ER_PASSWORD_NOT_ALLOWED); /* purecov: inspected */
- DBUG_RETURN(1); /* purecov: inspected */
+ return(1); /* purecov: inspected */
}
- if (!host)
- host=thd->ip; /* purecov: tested */
- /* password should always be 0 or 16 chars; simple hack to avoid cracking */
- length=(uint) strlen(new_password);
- new_password[length & 16]=0;
-
if (!thd->slave_thread &&
(strcmp(thd->user,user) ||
my_strcasecmp(system_charset_info, host,thd->host_or_ip)))
{
if (check_access(thd, UPDATE_ACL, "mysql",0,1))
- DBUG_RETURN(1);
+ return(1);
}
if (!thd->slave_thread && !thd->user[0])
{
send_error(&thd->net, ER_PASSWORD_ANONYMOUS_USER);
- DBUG_RETURN(1);
+ return(1);
}
+ return(0);
+}
+
+
+bool change_password(THD *thd, const char *host, const char *user,
+ char *new_password)
+{
+ uint length=0;
+ DBUG_ENTER("change_password");
+ DBUG_PRINT("enter",("host: '%s' user: '%s' new_password: '%s'",
+ host,user,new_password));
+ DBUG_ASSERT(host != 0); // Ensured by parent
+
+ if (check_change_password(thd, host, user))
+ DBUG_RETURN(1);
+
+ /* password should always be 0 or 16 chars; simple hack to avoid cracking */
+ length=(uint) strlen(new_password);
+ new_password[length & 16]=0;
+
VOID(pthread_mutex_lock(&acl_cache->lock));
ACL_USER *acl_user;
if (!(acl_user= find_acl_user(host,user)))
@@ -1007,15 +1058,14 @@ bool change_password(THD *thd, const char *host, const char *user,
VOID(pthread_mutex_unlock(&acl_cache->lock));
char buff[460];
-
- Query_log_event qinfo(thd, buff);
- qinfo.q_len =
+ ulong query_length=
my_sprintf(buff,
(buff,"SET PASSWORD FOR \"%-.120s\"@\"%-.120s\"=\"%-.120s\"",
acl_user->user ? acl_user->user : "",
acl_user->host.hostname ? acl_user->host.hostname : "",
new_password));
- mysql_update_log.write(thd,buff,qinfo.q_len);
+ mysql_update_log.write(thd, buff, query_length);
+ Query_log_event qinfo(thd, buff, query_length);
mysql_bin_log.write(&qinfo);
DBUG_RETURN(0);
}
@@ -1029,7 +1079,7 @@ static ACL_USER *
find_acl_user(const char *host, const char *user)
{
DBUG_ENTER("find_acl_user");
- DBUG_PRINT("enter",("host='%s', user='%s'",host,user));
+ DBUG_PRINT("enter",("host: '%s' user: '%s'",host,user));
for (uint i=0 ; i < acl_users.elements ; i++)
{
ACL_USER *acl_user=dynamic_element(&acl_users,i,ACL_USER*);
@@ -1104,7 +1154,7 @@ static bool compare_hostname(const acl_host_and_ip *host, const char *hostname,
/****************************************************************************
-** Code to update grants in the user and database privilege tables
+ Code to update grants in the user and database privilege tables
****************************************************************************/
static bool update_user_table(THD *thd, const char *host, const char *user,
@@ -1154,10 +1204,10 @@ static bool test_if_create_new_users(THD *thd)
if (opt_safe_user_create && !(thd->master_access & INSERT_ACL))
{
TABLE_LIST tl;
- uint db_access;
+ ulong db_access;
bzero((char*) &tl,sizeof(tl));
tl.db= (char*) "mysql";
- tl.real_name= (char*) "user";
+ tl.real_name= (char*) "user";
db_access=acl_get(thd->host, thd->ip, (char*) &thd->remote.sin_addr,
thd->priv_user, tl.db);
if (!(db_access & INSERT_ACL))
@@ -1175,12 +1225,13 @@ static bool test_if_create_new_users(THD *thd)
****************************************************************************/
static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
- uint rights, char what, bool create_user)
+ ulong rights, bool revoke_grant,
+ bool create_user)
{
int error = -1;
- uint i,j;
bool old_row_exists=0;
char *password,empty_string[1];
+ char what= (revoke_grant) ? 'N' : 'Y';
DBUG_ENTER("replace_user_table");
password=empty_string;
@@ -1231,55 +1282,58 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
table->field[2]->store(password,(uint) strlen(password), system_charset_info);
}
- for (i = 3, j = SELECT_ACL; // starting from reload
- i < table->fields;
- i++, j <<= 1)
+ /* Update table columns with new privileges */
+
+ Field **tmp_field;
+ ulong priv;
+ for (tmp_field= table->field+3, priv = SELECT_ACL;
+ *tmp_field && (*tmp_field)->real_type() == FIELD_TYPE_ENUM &&
+ ((Field_enum*) (*tmp_field))->typelib->count == 2 ;
+ tmp_field++, priv <<= 1)
{
- if (j & rights) // set requested privileges
- table->field[i]->store(&what,1, system_charset_info);
+ if (priv & rights) // set requested privileges
+ (*tmp_field)->store(&what, 1, system_charset_info);
}
rights=get_access(table,3);
-#ifdef HAVE_OPENSSL
- /* We write down SSL related ACL stuff */
- DBUG_PRINT("info",("table->fields=%d",table->fields));
- if (table->fields >= 21) /* From 4.0.0 we have more fields */
+ DBUG_PRINT("info",("table->fields: %d",table->fields));
+ if (table->fields >= 31) /* From 4.0.0 we have more fields */
{
- table->field[18]->store("",0, system_charset_info);
- table->field[19]->store("",0, system_charset_info);
- table->field[20]->store("",0, system_charset_info);
+#ifdef HAVE_OPENSSL
+ /* We write down SSL related ACL stuff */
+ table->field[25]->store("", 0, system_charset_info);
+ table->field[26]->store("", 0, system_charset_info);
+ table->field[27]->store("", 0, system_charset_info);
switch (thd->lex.ssl_type) {
case SSL_TYPE_ANY:
- table->field[17]->store("ANY",3, system_charset_info);
+ table->field[24]->store("ANY",3, system_charset_info);
break;
case SSL_TYPE_X509:
- table->field[17]->store("X509",4, system_charset_info);
+ table->field[24]->store("X509",4, system_charset_info);
break;
case SSL_TYPE_SPECIFIED:
- table->field[17]->store("SPECIFIED",9, system_charset_info);
+ table->field[24]->store("SPECIFIED",9, system_charset_info);
if (thd->lex.ssl_cipher)
- table->field[18]->store(thd->lex.ssl_cipher,
+ table->field[25]->store(thd->lex.ssl_cipher,
strlen(thd->lex.ssl_cipher), system_charset_info);
if (thd->lex.x509_issuer)
- table->field[19]->store(thd->lex.x509_issuer,
+ table->field[26]->store(thd->lex.x509_issuer,
strlen(thd->lex.x509_issuer), system_charset_info);
if (thd->lex.x509_subject)
- table->field[20]->store(thd->lex.x509_subject,
+ table->field[27]->store(thd->lex.x509_subject,
strlen(thd->lex.x509_subject), system_charset_info);
break;
default:
- table->field[17]->store("NONE",4, system_charset_info);
+ table->field[24]->store("", 0, system_charset_info);
}
- }
#endif /* HAVE_OPENSSL */
- if (table->fields >= 23)
- {
+
USER_RESOURCES mqh = thd->lex.mqh;
- if (mqh.questions)
- table->field[21]->store((longlong) mqh.questions);
- if (mqh.updates)
- table->field[22]->store((longlong) mqh.updates);
- if (mqh.connections)
- table->field[23]->store((longlong) mqh.connections);
+ if (mqh.bits & 1)
+ table->field[28]->store((longlong) mqh.questions);
+ if (mqh.bits & 2)
+ table->field[29]->store((longlong) mqh.updates);
+ if (mqh.bits & 4)
+ table->field[30]->store((longlong) mqh.connections);
mqh_used = mqh_used || mqh.questions || mqh.updates || mqh.connections;
}
if (old_row_exists)
@@ -1337,16 +1391,18 @@ end:
/*
-** change grants in the mysql.db table
+ change grants in the mysql.db table
*/
static int replace_db_table(TABLE *table, const char *db,
const LEX_USER &combo,
- uint rights, char what)
+ ulong rights, bool revoke_grant)
{
- uint i,j,store_rights;
+ uint i;
+ ulong priv,store_rights;
bool old_row_exists=0;
int error;
+ char what= (revoke_grant) ? 'N' : 'Y';
DBUG_ENTER("replace_db_table");
// is there such a user in user table in memory ????
@@ -1382,9 +1438,9 @@ static int replace_db_table(TABLE *table, const char *db,
}
store_rights=get_rights_for_db(rights);
- for (i = 3, j = 1; i < table->fields; i++, j <<= 1)
+ for (i= 3, priv= 1; i < table->fields; i++, priv <<= 1)
{
- if (j & store_rights) // do it if priv is chosen
+ if (priv & store_rights) // do it if priv is chosen
table->field [i]->store(&what,1, system_charset_info);// set requested privileges
}
rights=get_access(table,3);
@@ -1432,13 +1488,15 @@ class GRANT_COLUMN :public Sql_alloc
{
public:
char *column;
- uint rights, key_length;
- GRANT_COLUMN(String &c, uint y) :rights (y)
+ ulong rights;
+ uint key_length;
+ GRANT_COLUMN(String &c, ulong y) :rights (y)
{
- column= memdup_root(&memex,c.ptr(),key_length=c.length());
+ column= memdup_root(&memex,c.ptr(), key_length=c.length());
}
};
+
static byte* get_key_column(GRANT_COLUMN *buff,uint *length,
my_bool not_used __attribute__((unused)))
{
@@ -1446,14 +1504,16 @@ static byte* get_key_column(GRANT_COLUMN *buff,uint *length,
return (byte*) buff->column;
}
+
class GRANT_TABLE :public Sql_alloc
{
public:
char *host,*db,*user,*tname, *hash_key;
- uint privs, cols, key_length;
+ ulong privs, cols;
+ uint key_length;
HASH hash_columns;
GRANT_TABLE (const char *h, const char *d,const char *u, const char *t,
- uint p,uint c)
+ ulong p, ulong c)
: privs(p), cols(c)
{
host = strdup_root(&memex,h);
@@ -1479,7 +1539,9 @@ public:
host = get_field(&memex,form,0);
db = get_field(&memex,form,1);
- user = get_field(&memex,form,2); if (!user) user=(char*) "";
+ user = get_field(&memex,form,2);
+ if (!user)
+ user=(char*) "";
tname = get_field(&memex,form,3);
if (!host || !db || !tname)
{
@@ -1496,8 +1558,8 @@ public:
(uint) strlen(tname) + 3);
hash_key = (char*) alloc_root(&memex,key_length);
strmov(strmov(strmov(hash_key,user)+1,db)+1,tname);
- privs = (uint) form->field[6]->val_int();
- cols = (uint) form->field[7]->val_int();
+ privs = (ulong) form->field[6]->val_int();
+ cols = (ulong) form->field[7]->val_int();
privs = fix_rights_for_table(privs);
cols = fix_rights_for_column(cols);
@@ -1531,7 +1593,7 @@ public:
GRANT_COLUMN *mem_check;
/* As column name is a string, we don't have to supply a buffer */
res=col_privs->field[4]->val_str(&column_name,&column_name);
- uint priv= (uint) col_privs->field[6]->val_int();
+ ulong priv= (ulong) col_privs->field[6]->val_int();
if (!(mem_check = new GRANT_COLUMN(*res,
fix_rights_for_column(priv))))
{
@@ -1547,6 +1609,7 @@ public:
bool ok() { return privs != 0 || cols != 0; }
};
+
static byte* get_grant_table(GRANT_TABLE *buff,uint *length,
my_bool not_used __attribute__((unused)))
{
@@ -1554,11 +1617,13 @@ static byte* get_grant_table(GRANT_TABLE *buff,uint *length,
return (byte*) buff->hash_key;
}
+
void free_grant_table(GRANT_TABLE *grant_table)
{
hash_free(&grant_table->hash_columns);
}
+
/* Search after a matching grant. Prefer exact grants before not exact ones */
static GRANT_TABLE *table_hash_search(const char *host,const char* ip,
@@ -1597,8 +1662,7 @@ static GRANT_TABLE *table_hash_search(const char *host,const char* ip,
inline GRANT_COLUMN *
-column_hash_search(GRANT_TABLE *t, const char *cname,
- uint length)
+column_hash_search(GRANT_TABLE *t, const char *cname, uint length)
{
return (GRANT_COLUMN*) hash_search(&t->hash_columns, (byte*) cname,length);
}
@@ -1608,7 +1672,7 @@ static int replace_column_table(GRANT_TABLE *g_t,
TABLE *table, const LEX_USER &combo,
List <LEX_COLUMN> &columns,
const char *db, const char *table_name,
- uint rights, bool revoke_grant)
+ ulong rights, bool revoke_grant)
{
int error=0,result=0;
uint key_length;
@@ -1632,7 +1696,7 @@ static int replace_column_table(GRANT_TABLE *g_t,
table->file->index_init(0);
while ((xx=iter++))
{
- uint privileges = xx->rights;
+ ulong privileges = xx->rights;
bool old_row_exists=0;
key_restore(table,key,0,key_length);
table->field[4]->store(xx->column.ptr(),xx->column.length(),system_charset_info);
@@ -1655,7 +1719,7 @@ static int replace_column_table(GRANT_TABLE *g_t,
}
else
{
- uint tmp= (uint) table->field[6]->val_int();
+ ulong tmp= (ulong) table->field[6]->val_int();
tmp=fix_rights_for_column(tmp);
if (revoke_grant)
@@ -1715,7 +1779,7 @@ static int replace_column_table(GRANT_TABLE *g_t,
// Scan trough all rows with the same host,db,user and table
do
{
- uint privileges = (uint) table->field[6]->val_int();
+ ulong privileges = (ulong) table->field[6]->val_int();
privileges=fix_rights_for_column(privileges);
store_record(table,1);
@@ -1771,18 +1835,21 @@ static int replace_column_table(GRANT_TABLE *g_t,
static int replace_table_table(THD *thd, GRANT_TABLE *grant_table,
TABLE *table, const LEX_USER &combo,
const char *db, const char *table_name,
- uint rights, uint kolone, bool revoke_grant)
+ ulong rights, ulong col_rights,
+ bool revoke_grant)
{
char grantor[HOSTNAME_LENGTH+1+USERNAME_LENGTH];
int old_row_exists = 1;
int error=0;
- uint store_table_rights,store_col_rights;
+ ulong store_table_rights, store_col_rights;
DBUG_ENTER("replace_table_table");
strxmov(grantor, thd->user, "@", thd->host_or_ip, NullS);
- // The following should always succeed as new users are created before
- // this function is called!
+ /*
+ The following should always succeed as new users are created before
+ this function is called!
+ */
if (!find_acl_user(combo.host.str,combo.user.str))
{
my_error(ER_PASSWORD_NO_MATCH,MYF(0)); /* purecov: deadcode */
@@ -1817,14 +1884,14 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table,
restore_record(table,1); // Get saved record
}
- store_table_rights=get_rights_for_table(rights);
- store_col_rights=get_rights_for_column(kolone);
+ store_table_rights= get_rights_for_table(rights);
+ store_col_rights= get_rights_for_column(col_rights);
if (old_row_exists)
{
- uint j,k;
+ ulong j,k;
store_record(table,1);
- j = (uint) table->field[6]->val_int();
- k = (uint) table->field[7]->val_int();
+ j = (ulong) table->field[6]->val_int();
+ k = (ulong) table->field[7]->val_int();
if (revoke_grant)
{
@@ -1833,8 +1900,8 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table,
}
else
{
- store_table_rights|=j;
- store_col_rights|=k;
+ store_table_rights|= j;
+ store_col_rights|= k;
}
}
@@ -1842,7 +1909,7 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table,
table->field[6]->store((longlong) store_table_rights);
table->field[7]->store((longlong) store_col_rights);
rights=fix_rights_for_table(store_table_rights);
- kolone=fix_rights_for_column(store_col_rights);
+ col_rights=fix_rights_for_column(store_col_rights);
if (old_row_exists)
{
@@ -1861,10 +1928,10 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table,
goto table_error; /* purecov: deadcode */
}
- if (rights | kolone)
+ if (rights | col_rights)
{
- grant_table->privs = rights;
- grant_table->cols = kolone;
+ grant_table->privs= rights;
+ grant_table->cols= col_rights;
}
else
{
@@ -1881,18 +1948,15 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table,
int mysql_table_grant (THD *thd, TABLE_LIST *table_list,
List <LEX_USER> &user_list,
- List <LEX_COLUMN> &columns, uint rights,
+ List <LEX_COLUMN> &columns, ulong rights,
bool revoke_grant)
{
- uint column_priv = 0;
+ ulong column_priv = 0;
List_iterator <LEX_USER> str_list (user_list);
LEX_USER *Str;
TABLE_LIST tables[3];
bool create_new_users=0;
DBUG_ENTER("mysql_table_grant");
- DBUG_PRINT("info",("ssl_cipher=%s",thd->lex.ssl_cipher));
- DBUG_PRINT("info",("x509_issuer=%s",thd->lex.x509_issuer));
- DBUG_PRINT("info",("x509_subject=%s",thd->lex.x509_subject));
if (!initialized)
{
@@ -1982,12 +2046,8 @@ int mysql_table_grant (THD *thd, TABLE_LIST *table_list,
continue;
}
/* Create user if needed */
- if (replace_user_table(thd,
- tables[0].table,
- *Str,
- 0,
- revoke_grant ? 'N' : 'Y',
- create_new_users))
+ if (replace_user_table(thd, tables[0].table, *Str,
+ 0, revoke_grant, create_new_users))
{
result= -1; // Remember error
continue; // Add next user
@@ -2083,12 +2143,12 @@ int mysql_table_grant (THD *thd, TABLE_LIST *table_list,
}
-int mysql_grant (THD *thd, const char *db, List <LEX_USER> &list, uint rights,
- bool revoke_grant)
+int mysql_grant (THD *thd, const char *db, List <LEX_USER> &list,
+ ulong rights, bool revoke_grant)
{
List_iterator <LEX_USER> str_list (list);
LEX_USER *Str;
- char what,tmp_db[NAME_LEN+1];
+ char tmp_db[NAME_LEN+1];
bool create_new_users=0;
TABLE_LIST tables[2];
DBUG_ENTER("mysql_grant");
@@ -2099,7 +2159,6 @@ int mysql_grant (THD *thd, const char *db, List <LEX_USER> &list, uint rights,
return 1; /* purecov: tested */
}
- what = (revoke_grant) ? 'N' : 'Y';
if (lower_case_table_names && db)
{
strmov(tmp_db,db);
@@ -2148,12 +2207,13 @@ int mysql_grant (THD *thd, const char *db, List <LEX_USER> &list, uint rights,
if ((replace_user_table(thd,
tables[0].table,
*Str,
- (!db ? rights : 0), what, create_new_users)))
+ (!db ? rights : 0), revoke_grant,
+ create_new_users)))
result= -1;
else
{
if (db && replace_db_table(tables[1].table, db, *Str, rights & DB_ACLS,
- what))
+ revoke_grant))
result= -1;
}
}
@@ -2166,7 +2226,8 @@ int mysql_grant (THD *thd, const char *db, List <LEX_USER> &list, uint rights,
DBUG_RETURN(result);
}
- /* Free grant array if possible */
+
+/* Free grant array if possible */
void grant_free(void)
{
@@ -2304,11 +2365,11 @@ void grant_reload(void)
/****************************************************************************
-** Check grants
-** All errors are written directly to the client if command name is given !
+ Check grants
+ All errors are written directly to the client if command name is given !
****************************************************************************/
-bool check_grant(THD *thd, uint want_access, TABLE_LIST *tables,
+bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
uint show_table, bool no_errors)
{
TABLE_LIST *table;
@@ -2394,7 +2455,7 @@ bool check_grant_column (THD *thd,TABLE *table, const char *name,
GRANT_TABLE *grant_table;
GRANT_COLUMN *grant_column;
- uint want_access=table->grant.want_privilege;
+ ulong want_access=table->grant.want_privilege;
if (!want_access)
return 0; // Already checked
@@ -2432,13 +2493,8 @@ bool check_grant_column (THD *thd,TABLE *table, const char *name,
pthread_mutex_unlock(&LOCK_grant);
if (!show_tables)
{
- const char *command="";
- if (want_access & SELECT_ACL)
- command ="select";
- else if (want_access & INSERT_ACL)
- command = "insert";
- else if (want_access & UPDATE_ACL)
- command = "update";
+ char command[128];
+ get_privilege_desc(command, sizeof(command), want_access);
my_printf_error(ER_COLUMNACCESS_DENIED_ERROR,
ER(ER_COLUMNACCESS_DENIED_ERROR),
MYF(0),
@@ -2452,7 +2508,7 @@ bool check_grant_column (THD *thd,TABLE *table, const char *name,
}
-bool check_grant_all_columns(THD *thd,uint want_access, TABLE *table)
+bool check_grant_all_columns(THD *thd, ulong want_access, TABLE *table)
{
GRANT_TABLE *grant_table;
GRANT_COLUMN *grant_column;
@@ -2510,9 +2566,9 @@ bool check_grant_all_columns(THD *thd,uint want_access, TABLE *table)
/****************************************************************************
-** Check if a user has the right to access a database
-** Access is accepted if he has a grant for any table in the database
-** Return 1 if access is denied
+ Check if a user has the right to access a database
+ Access is accepted if he has a grant for any table in the database
+ Return 1 if access is denied
****************************************************************************/
bool check_grant_db(THD *thd,const char *db)
@@ -2543,10 +2599,10 @@ bool check_grant_db(THD *thd,const char *db)
}
/*****************************************************************************
-** Functions to retrieve the grant for a table/column (for SHOW functions)
+ Functions to retrieve the grant for a table/column (for SHOW functions)
*****************************************************************************/
-uint get_table_grant(THD *thd, TABLE_LIST *table)
+ulong get_table_grant(THD *thd, TABLE_LIST *table)
{
char *user = thd->priv_user;
const char *db = table->db ? table->db : thd->db;
@@ -2564,11 +2620,11 @@ uint get_table_grant(THD *thd, TABLE_LIST *table)
}
-uint get_column_grant(THD *thd, TABLE_LIST *table, Field *field)
+ulong get_column_grant(THD *thd, TABLE_LIST *table, Field *field)
{
GRANT_TABLE *grant_table;
GRANT_COLUMN *grant_column;
- uint priv;
+ ulong priv;
pthread_mutex_lock(&LOCK_grant);
// reload table if someone has modified any grants
@@ -2598,20 +2654,28 @@ uint get_column_grant(THD *thd, TABLE_LIST *table, Field *field)
/*****************************************************************************
-** SHOW GRANTS : send to client grant-like strings depicting user@host
-** privileges
+ SHOW GRANTS : send to client grant-like strings depicting user@host
+ privileges
*****************************************************************************/
static const char *command_array[]=
-{"SELECT", "INSERT","UPDATE","DELETE","CREATE", "DROP","RELOAD","SHUTDOWN",
- "PROCESS","FILE","GRANT","REFERENCES","INDEX","ALTER"};
-static int command_lengths[]={6,6,6,6,6,4,6,8,7,4,5,10,5,5};
+{
+ "SELECT", "INSERT","UPDATE","DELETE","CREATE", "DROP", "RELOAD","SHUTDOWN",
+ "PROCESS","FILE","GRANT","REFERENCES","INDEX", "ALTER", "SHOW DATABASES",
+ "SUPER", "CREATE TEMPORARY TABLES", "LOCK TABLES", "EXECUTE",
+ "REPLICATION SLAVE", "REPLICATION CLIENT",
+};
+static uint command_lengths[]=
+{
+ 6,6,6,6,6,4,6,8,7,4,5,10,5,5,14,5,23,11,7,17,18
+};
+
int mysql_show_grants(THD *thd,LEX_USER *lex_user)
{
- uint counter, want_access,index;
+ ulong want_access;
+ uint counter,index;
int error = 0;
- int ssl_options = 0;
ACL_USER *acl_user; ACL_DB *acl_db;
char buff[1024];
DBUG_ENTER("mysql_show_grants");
@@ -2680,7 +2744,7 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
else
{
bool found=0;
- uint j,test_access= want_access & ~GRANT_ACL;
+ ulong j,test_access= want_access & ~GRANT_ACL;
for (counter=0, j = SELECT_ACL;j <= GLOBAL_ACLS;counter++,j <<= 1)
{
if (test_access & j)
@@ -2709,18 +2773,18 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
/* "show grants" SSL related stuff */
if (acl_user->ssl_type == SSL_TYPE_ANY)
global.append(" REQUIRE SSL",12);
- else if (acl_user->ssl_type==SSL_TYPE_X509)
+ else if (acl_user->ssl_type == SSL_TYPE_X509)
global.append(" REQUIRE X509",13);
- else if (acl_user->ssl_type==SSL_TYPE_SPECIFIED)
+ else if (acl_user->ssl_type == SSL_TYPE_SPECIFIED)
{
+ int ssl_options = 0;
global.append(" REQUIRE ",9);
if (acl_user->x509_issuer)
{
- if (ssl_options++)
- global.append(" AND ",5);
+ ssl_options++;
global.append("ISSUER \"",8);
global.append(acl_user->x509_issuer,strlen(acl_user->x509_issuer));
- global.append("\"",1);
+ global.append('\'');
}
if (acl_user->x509_subject)
{
@@ -2728,40 +2792,46 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
global.append(" AND ",5);
global.append("SUBJECT \"",9);
global.append(acl_user->x509_subject,strlen(acl_user->x509_subject));
- global.append("\"",1);
+ global.append('\'');
}
if (acl_user->ssl_cipher)
{
if (ssl_options++)
global.append(" AND ",5);
- global.append("CIPHER \"",8);
+ global.append("CIPHER '",8);
global.append(acl_user->ssl_cipher,strlen(acl_user->ssl_cipher));
- global.append("\"",1);
+ global.append('\'');
}
}
#endif /* HAVE_OPENSSL */
- if (want_access & GRANT_ACL)
- global.append(" WITH GRANT OPTION",18);
- if (acl_user->user_resource.questions)
+ if ((want_access & GRANT_ACL) ||
+ (acl_user->user_resource.questions | acl_user->user_resource.updates |
+ acl_user->user_resource.connections))
{
- char buff[65], *p; // just as in int2str
- global.append(" WITH MAX_QUERIES_PER_HOUR = ",29);
- p=int2str(acl_user->user_resource.questions,buff,10);
- global.append(buff,p-buff);
- }
- if (acl_user->user_resource.updates)
- {
- char buff[65], *p; // just as in int2str
- global.append(" WITH MAX_UPDATES_PER_HOUR = ",29);
- p=int2str(acl_user->user_resource.updates,buff,10);
- global.append(buff,p-buff);
- }
- if (acl_user->user_resource.connections)
- {
- char buff[65], *p; // just as in int2str
- global.append(" WITH MAX_CONNECTIONS_PER_HOUR = ",33);
- p=int2str(acl_user->user_resource.connections,buff,10);
- global.append(buff,p-buff);
+ global.append(" WITH",5);
+ if (want_access & GRANT_ACL)
+ global.append(" GRANT OPTION",13);
+ if (acl_user->user_resource.questions)
+ {
+ char buff[22], *p; // just as in int2str
+ global.append(" MAX_QUERIES_PER_HOUR ",22);
+ p=int10_to_str(acl_user->user_resource.questions,buff,10);
+ global.append(buff,p-buff);
+ }
+ if (acl_user->user_resource.updates)
+ {
+ char buff[22], *p; // just as in int2str
+ global.append(" MAX_UPDATES_PER_HOUR ",22);
+ p=int10_to_str(acl_user->user_resource.updates,buff,10);
+ global.append(buff,p-buff);
+ }
+ if (acl_user->user_resource.connections)
+ {
+ char buff[22], *p; // just as in int2str
+ global.append(" MAX_CONNECTIONS_PER_HOUR ",26);
+ p=int10_to_str(acl_user->user_resource.connections,buff,10);
+ global.append(buff,p-buff);
+ }
}
thd->packet.length(0);
net_store_data(&thd->packet,global.ptr(),global.length());
@@ -2798,7 +2868,7 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
else
{
int found=0, cnt;
- uint j,test_access= want_access & ~GRANT_ACL;
+ ulong j,test_access= want_access & ~GRANT_ACL;
for (cnt=0, j = SELECT_ACL; j <= DB_ACLS; cnt++,j <<= 1)
{
if (test_access & j)
@@ -2810,15 +2880,15 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
}
}
}
- db.append (" ON '",5);
+ db.append (" ON `",5);
db.append(acl_db->db);
- db.append ("'.* TO '",8);
+ db.append ("`.* TO '",8);
db.append(lex_user->user.str,lex_user->user.length);
db.append ("'@'",3);
db.append(lex_user->host.str, lex_user->host.length);
db.append ('\'');
if (want_access & GRANT_ACL)
- db.append(" WITH GRANT OPTION",18);
+ db.append(" WITH GRANT OPTION",18);
thd->packet.length(0);
net_store_data(&thd->packet,db.ptr(),db.length());
if (my_net_write(&thd->net,(char*) thd->packet.ptr(),
@@ -2857,7 +2927,7 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
else
{
int found=0;
- uint j,test_access= (want_access | grant_table->cols) & ~GRANT_ACL;
+ ulong j,test_access= (want_access | grant_table->cols) & ~GRANT_ACL;
for (counter=0, j = SELECT_ACL;j <= TABLE_ACLS; counter++,j <<= 1)
{
@@ -2925,6 +2995,34 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
}
+/*
+ Make a clear-text version of the requested privilege.
+*/
+
+void get_privilege_desc(char *to, uint max_length, ulong access)
+{
+ uint pos;
+ char *start=to;
+ DBUG_ASSERT(max_length >= 30); // For end ',' removal
+
+ if (access)
+ {
+ max_length--; // Reserve place for end-zero
+ for (pos=0 ; access ; pos++, access>>=1)
+ {
+ if ((access & 1) &&
+ command_lengths[pos] + (uint) (to-start) < max_length)
+ {
+ to= strmov(to, command_array[pos]);
+ *to++=',';
+ }
+ }
+ to--; // Remove end ','
+ }
+ *to=0;
+}
+
+
void get_mqh(const char *user, const char *host, USER_CONN *uc)
{
ACL_USER *acl_user;
@@ -2937,7 +3035,7 @@ void get_mqh(const char *user, const char *host, USER_CONN *uc)
/*****************************************************************************
-** Instantiate used templates
+ Instantiate used templates
*****************************************************************************/
#ifdef __GNUC__
diff --git a/sql/sql_acl.h b/sql/sql_acl.h
index 9ac3bc6ed74..d6cf320c978 100644
--- a/sql/sql_acl.h
+++ b/sql/sql_acl.h
@@ -15,33 +15,49 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-#define SELECT_ACL 1
-#define INSERT_ACL 2
-#define UPDATE_ACL 4
-#define DELETE_ACL 8
-#define CREATE_ACL 16
-#define DROP_ACL 32
-#define RELOAD_ACL 64
-#define SHUTDOWN_ACL 128
-#define PROCESS_ACL 256
-#define FILE_ACL 512
-#define GRANT_ACL 1024
-#define REFERENCES_ACL 2048
-#define INDEX_ACL 4096
-#define ALTER_ACL 8192
-#define EXTRA_ACL 16384
-#define DB_ACLS (UPDATE_ACL | SELECT_ACL | INSERT_ACL | \
- DELETE_ACL | CREATE_ACL | DROP_ACL | GRANT_ACL | \
- REFERENCES_ACL | INDEX_ACL | ALTER_ACL)
-#define TABLE_ACLS (SELECT_ACL | INSERT_ACL | UPDATE_ACL | \
- DELETE_ACL | CREATE_ACL | DROP_ACL | GRANT_ACL | \
- REFERENCES_ACL | INDEX_ACL | ALTER_ACL)
-#define COL_ACLS (SELECT_ACL | INSERT_ACL | UPDATE_ACL | REFERENCES_ACL)
-#define GLOBAL_ACLS (SELECT_ACL | INSERT_ACL | UPDATE_ACL | DELETE_ACL |\
- CREATE_ACL | DROP_ACL | RELOAD_ACL | SHUTDOWN_ACL |\
- PROCESS_ACL | FILE_ACL | GRANT_ACL | REFERENCES_ACL |\
- INDEX_ACL | ALTER_ACL)
-#define NO_ACCESS 32768
+#define SELECT_ACL (1L << 0)
+#define INSERT_ACL (1L << 1)
+#define UPDATE_ACL (1L << 2)
+#define DELETE_ACL (1L << 3)
+#define CREATE_ACL (1L << 4)
+#define DROP_ACL (1L << 5)
+#define RELOAD_ACL (1L << 6)
+#define SHUTDOWN_ACL (1L << 7)
+#define PROCESS_ACL (1L << 8)
+#define FILE_ACL (1L << 9)
+#define GRANT_ACL (1L << 10)
+#define REFERENCES_ACL (1L << 11)
+#define INDEX_ACL (1L << 12)
+#define ALTER_ACL (1L << 13)
+#define SHOW_DB_ACL (1L << 14)
+#define SUPER_ACL (1L << 15)
+#define CREATE_TMP_ACL (1L << 16)
+#define LOCK_TABLES_ACL (1L << 17)
+#define EXECUTE_ACL (1L << 18)
+#define REPL_SLAVE_ACL (1L << 19)
+#define REPL_CLIENT_ACL (1L << 20)
+
+
+#define DB_ACLS \
+(UPDATE_ACL | SELECT_ACL | INSERT_ACL | DELETE_ACL | CREATE_ACL | DROP_ACL | \
+ GRANT_ACL | REFERENCES_ACL | INDEX_ACL | ALTER_ACL)
+
+#define TABLE_ACLS \
+(SELECT_ACL | INSERT_ACL | UPDATE_ACL | DELETE_ACL | CREATE_ACL | DROP_ACL | \
+ GRANT_ACL | REFERENCES_ACL | INDEX_ACL | ALTER_ACL)
+
+#define COL_ACLS \
+(SELECT_ACL | INSERT_ACL | UPDATE_ACL | REFERENCES_ACL)
+
+#define GLOBAL_ACLS \
+(SELECT_ACL | INSERT_ACL | UPDATE_ACL | DELETE_ACL | CREATE_ACL | DROP_ACL | \
+ RELOAD_ACL | SHUTDOWN_ACL | PROCESS_ACL | FILE_ACL | GRANT_ACL | \
+ REFERENCES_ACL | INDEX_ACL | ALTER_ACL | SHOW_DB_ACL | SUPER_ACL | \
+ CREATE_TMP_ACL | LOCK_TABLES_ACL | REPL_SLAVE_ACL | REPL_CLIENT_ACL | \
+ EXECUTE_ACL)
+
+#define EXTRA_ACL (1L << 29)
+#define NO_ACCESS (1L << 30)
/* defines to change the above bits to how things are stored in tables */
@@ -57,29 +73,31 @@
int acl_init(bool dont_read_acl_tables);
void acl_reload(void);
void acl_free(bool end=0);
-uint acl_get(const char *host, const char *ip, const char *bin_ip,
- const char *user, const char *db);
-uint acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
- const char *password,const char *scramble,char **priv_user,
- bool old_ver, USER_RESOURCES *max);
+ulong acl_get(const char *host, const char *ip, const char *bin_ip,
+ const char *user, const char *db);
+ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
+ const char *password,const char *scramble,char **priv_user,
+ bool old_ver, USER_RESOURCES *max);
bool acl_check_host(const char *host, const char *ip);
+bool check_change_password(THD *thd, const char *host, const char *user);
bool change_password(THD *thd, const char *host, const char *user,
char *password);
int mysql_grant(THD *thd, const char *db, List <LEX_USER> &user_list,
- uint rights, bool revoke);
+ ulong rights, bool revoke);
int mysql_table_grant(THD *thd, TABLE_LIST *table, List <LEX_USER> &user_list,
- List <LEX_COLUMN> &column_list, uint rights,
+ List <LEX_COLUMN> &column_list, ulong rights,
bool revoke);
int grant_init(void);
void grant_free(void);
void grant_reload(void);
-bool check_grant(THD *thd, uint want_access, TABLE_LIST *tables,
+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,
+bool check_grant_column (THD *thd,TABLE *table, const char *name, uint length,
uint show_command=0);
-bool check_grant_all_columns(THD *thd, uint want_access, TABLE *table);
+bool check_grant_all_columns(THD *thd, ulong want_access, TABLE *table);
bool check_grant_db(THD *thd,const char *db);
-uint get_table_grant(THD *thd, TABLE_LIST *table);
-uint get_column_grant(THD *thd, TABLE_LIST *table, Field *field);
+ulong get_table_grant(THD *thd, TABLE_LIST *table);
+ulong get_column_grant(THD *thd, TABLE_LIST *table, Field *field);
int mysql_show_grants(THD *thd, LEX_USER *user);
+void get_privilege_desc(char *to, uint max_length, ulong access);
void get_mqh(const char *user, const char *host, USER_CONN *uc);
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 6185b031c2e..a8115c15412 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -19,7 +19,6 @@
#include "mysql_priv.h"
#include "sql_acl.h"
-#include <thr_alarm.h>
#include <m_ctype.h>
#include <my_dir.h>
#include <hash.h>
@@ -33,7 +32,7 @@ TABLE *unused_tables; /* Used by mysql_test */
HASH open_cache; /* Used by mysql_test */
static int open_unireg_entry(THD *thd,TABLE *entry,const char *db,
- const char *name, const char *alias, bool locked);
+ const char *name, const char *alias);
static void free_cache_entry(TABLE *entry);
static void mysql_rm_tmp_tables(void);
static key_map get_key_map_from_key_list(TABLE *table,
@@ -110,10 +109,27 @@ static void check_unused(void)
#define check_unused()
#endif
+/*
+ Create a list for all open tables matching SQL expression
+
+ SYNOPSIS
+ list_open_tables()
+ thd Thread THD
+ wild SQL like expression
+
+ NOTES
+ One gets only a list of tables for which one has any kind of privilege.
+ db and table names are allocated in result struct, so one doesn't need
+ a lock on LOCK_open when traversing the return list.
+
+ RETURN VALUES
+ NULL Error (Probably OOM)
+ # Pointer to list of names of open tables.
+*/
+
OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *wild)
{
int result = 0;
- uint col_access=thd->col_access;
OPEN_TABLE_LIST **start_list, *open_list;
TABLE_LIST table_list;
char name[NAME_LEN*2];
@@ -179,13 +195,25 @@ OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *wild)
DBUG_RETURN(open_list);
}
+
/*
- Send name and type of result to client.
- Sum fields has table name empty and field_name.
- flag is a bit mask with the following functions:
- 1 send number of rows
- 2 send default values
- 4 Don't convert field names
+ Send name and type of result to client converted to a given char set
+
+ SYNOPSIS
+ send_convert_fields()
+ THD Thread data object
+ list List of items to send to client
+ convert object used to convertation to another character set
+ flag Bit mask with the following functions:
+ 2 send default values
+ 4 Don't convert field names
+
+ DESCRIPTION
+ Sum fields has table name empty and field_name.
+
+ RETURN VALUES
+ 0 ok
+ 1 Error (Note that in this case the error is not sent to the client)
*/
bool
@@ -194,16 +222,15 @@ send_convert_fields(THD *thd,List<Item> &list,CONVERT *convert,uint flag)
List_iterator_fast<Item> it(list);
Item *item;
char buff[80];
-
String tmp((char*) buff,sizeof(buff),default_charset_info);
String *res,*packet= &thd->packet;
-
+ DBUG_ENTER("send_fields");
+
while ((item=it++))
{
char *pos;
Send_field field;
item->make_field(&field);
-
packet->length(0);
if (thd->client_capabilities & CLIENT_PROTOCOL_41)
@@ -219,7 +246,7 @@ send_convert_fields(THD *thd,List<Item> &list,CONVERT *convert,uint flag)
convert->store(packet,field.org_col_name,
(uint) strlen(field.org_col_name)) ||
packet->realloc(packet->length()+10))
- return 1;
+ goto err;
}
else
{
@@ -228,9 +255,8 @@ send_convert_fields(THD *thd,List<Item> &list,CONVERT *convert,uint flag)
convert->store(packet,field.col_name,
(uint) strlen(field.col_name)) ||
packet->realloc(packet->length()+10))
- return 1;
+ goto err;
}
-
pos= (char*) packet->ptr()+packet->length();
if (!(thd->client_capabilities & CLIENT_LONG_FLAG))
@@ -252,24 +278,38 @@ send_convert_fields(THD *thd,List<Item> &list,CONVERT *convert,uint flag)
if (!(res=item->val_str(&tmp)))
{
if (net_store_null(packet))
- return 1;
+ goto err;
}
- else if (net_store_data(packet,res->ptr(),res->length()))
- return 1;
+ else if (convert->store(packet,res->ptr(),res->length()))
+ goto err;
}
if (my_net_write(&thd->net, (char*) packet->ptr(),packet->length()))
break; /* purecov: inspected */
}
return 0;
+
+err:
+ return 1;
}
+
/*
- Send name and type of result to client.
- Sum fields has table name empty and field_name
- flag is a bit mask with the following functios:
- 1 send number of rows
- 2 send default values
- 4 Don't convert field names
+ Send name and type of result to client.
+
+ SYNOPSIS
+ send_non_convert_fields()
+ THD Thread data object
+ list List of items to send to client
+ flag Bit mask with the following functions:
+ 2 send default values
+ 4 Don't convert field names
+
+ DESCRIPTION
+ Sum fields has table name empty and field_name.
+
+ RETURN VALUES
+ 0 ok
+ 1 Error
*/
bool
@@ -278,16 +318,15 @@ send_non_convert_fields(THD *thd,List<Item> &list,uint flag)
List_iterator_fast<Item> it(list);
Item *item;
char buff[80];
-
+
String tmp((char*) buff,sizeof(buff),default_charset_info);
String *res,*packet= &thd->packet;
-
+
while ((item=it++))
{
char *pos;
Send_field field;
item->make_field(&field);
-
packet->length(0);
if (thd->client_capabilities & CLIENT_PROTOCOL_41)
@@ -307,7 +346,7 @@ send_non_convert_fields(THD *thd,List<Item> &list,uint flag)
packet->realloc(packet->length()+10))
return 1;
}
-
+
pos= (char*) packet->ptr()+packet->length();
if (!(thd->client_capabilities & CLIENT_LONG_FLAG))
@@ -340,23 +379,35 @@ send_non_convert_fields(THD *thd,List<Item> &list,uint flag)
return 0;
}
-/******************************************************************************
-** Send name and type of result to client.
-** Sum fields has table name empty and field_name.
-** flag is a bit mask with the following functions:
-** 1 send number of rows
-** 2 send default values
-** 4 Don't convert field names
-******************************************************************************/
+
+/*
+ Send name and type of result to client.
+
+ SYNOPSIS
+ send_fields()
+ THD Thread data object
+ list List of items to send to client
+ convert object used to convertation to another character set
+ flag Bit mask with the following functions:
+ 1 send number of rows
+ 2 send default values
+ 4 Don't convert field names
+
+ DESCRIPTION
+ Sum fields has table name empty and field_name.
+ Uses send_fields_convert() and send_fields() depending on
+ if we have an active character set convert or not.
+
+ RETURN VALUES
+ 0 ok
+ 1 Error (Note that in this case the error is not sent to the client)
+*/
bool
-send_fields(THD *thd,List<Item> &list,uint flag)
+send_fields(THD *thd, List<Item> &list, uint flag)
{
- List_iterator_fast<Item> it(list);
- char buff[80];
CONVERT *convert= (flag & 4) ? (CONVERT*) 0 : thd->convert_set;
-
- String tmp((char*) buff,sizeof(buff),default_charset_info);
+ DBUG_ENTER("send_fields");
if (thd->fatal_error) // We have got an error
goto err;
@@ -367,20 +418,24 @@ send_fields(THD *thd,List<Item> &list,uint flag)
(void) my_net_write(&thd->net, buff,(uint) (pos-buff));
}
- /* Avoid check conditions on convert() for each field
- by having two diffrent functions
+ /*
+ Avoid check conditions on convert() for each field
+ by having two different functions
*/
- if (convert && send_convert_fields(thd,list,convert,flag))
- goto err;
-
- else if(send_non_convert_fields(thd,list,flag))
+ if (convert)
+ {
+ if (send_convert_fields(thd, list, convert, flag))
+ goto err;
+ }
+ else if (send_non_convert_fields(thd, list, flag))
goto err;
send_eof(&thd->net);
return 0;
+
err:
send_error(&thd->net,ER_OUT_OF_RESOURCES); /* purecov: inspected */
- return 1; /* purecov: inspected */
+ DBUG_RETURN(1); /* purecov: inspected */
}
@@ -396,10 +451,21 @@ void intern_close_table(TABLE *table)
VOID(closefrm(table)); // close file
}
+/*
+ Remove table from the open table cache
+
+ SYNOPSIS
+ free_cache_entry()
+ table Table to remove
+
+ NOTE
+ We need to have a lock on LOCK_open when calling this
+*/
static void free_cache_entry(TABLE *table)
{
DBUG_ENTER("free_cache_entry");
+ safe_mutex_assert_owner(&LOCK_open);
intern_close_table(table);
if (!table->in_use)
@@ -546,6 +612,7 @@ void close_thread_tables(THD *thd, bool locked)
/* VOID(pthread_sigmask(SIG_SETMASK,&thd->block_signals,NULL)); */
if (!locked)
VOID(pthread_mutex_lock(&LOCK_open));
+ safe_mutex_assert_owner(&LOCK_open);
DBUG_PRINT("info", ("thd->open_tables=%p", thd->open_tables));
@@ -671,12 +738,10 @@ void close_temporary_tables(THD *thd)
}
if (query && found_user_tables && mysql_bin_log.is_open())
{
- uint save_query_len = thd->query_length;
- *--end = 0; // Remove last ','
- thd->query_length = (uint)(end-query);
- Query_log_event qinfo(thd, query);
+ /* The -1 is to remove last ',' */
+ Query_log_event qinfo(thd, query, (ulong)(end-query)-1);
+ qinfo.error_code=0;
mysql_bin_log.write(&qinfo);
- thd->query_length = save_query_len;
}
thd->temporary_tables=0;
}
@@ -789,11 +854,13 @@ TABLE *unlink_open_table(THD *thd, TABLE *list, TABLE *find)
/*
When we call the following function we must have a lock on
- LOCK_OPEN ; This lock will be unlocked on return.
+ LOCK_open ; This lock will be unlocked on return.
*/
void wait_for_refresh(THD *thd)
{
+ safe_mutex_assert_owner(&LOCK_open);
+
/* Wait until the current table is up to date */
const char *proc_info;
thd->mysys_var->current_mutex= &LOCK_open;
@@ -811,6 +878,7 @@ void wait_for_refresh(THD *thd)
pthread_mutex_unlock(&thd->mysys_var->mutex);
}
+
TABLE *reopen_name_locked_table(THD* thd, TABLE_LIST* table_list)
{
DBUG_ENTER("reopen_name_locked_table");
@@ -827,7 +895,7 @@ TABLE *reopen_name_locked_table(THD* thd, TABLE_LIST* table_list)
key_length=(uint) (strmov(strmov(key,db)+1,table_name)-key)+1;
pthread_mutex_lock(&LOCK_open);
- if (open_unireg_entry(thd, table, db, table_name, table_name, 1) ||
+ if (open_unireg_entry(thd, table, db, table_name, table_name) ||
!(table->table_cache_key =memdup_root(&table->mem_root,(char*) key,
key_length)))
{
@@ -849,7 +917,8 @@ TABLE *reopen_name_locked_table(THD* thd, TABLE_LIST* table_list)
table->const_table=0;
table->outer_join=table->null_row=table->maybe_null=0;
table->status=STATUS_NO_RECORD;
- table->keys_in_use_for_query=table->used_keys= table->keys_in_use;
+ table->keys_in_use_for_query= table->keys_in_use;
+ table->used_keys= table->keys_for_keyread;
DBUG_RETURN(table);
}
@@ -959,8 +1028,11 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name,
/* make a new table */
if (!(table=(TABLE*) my_malloc(sizeof(*table),MYF(MY_WME))))
+ {
+ VOID(pthread_mutex_unlock(&LOCK_open));
DBUG_RETURN(NULL);
- if (open_unireg_entry(thd, table,db,table_name,alias,1) ||
+ }
+ if (open_unireg_entry(thd, table,db,table_name,alias) ||
!(table->table_cache_key=memdup_root(&table->mem_root,(char*) key,
key_length)))
{
@@ -1003,7 +1075,8 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name,
table->const_table=0;
table->outer_join=table->null_row=table->maybe_null=0;
table->status=STATUS_NO_RECORD;
- table->keys_in_use_for_query=table->used_keys= table->keys_in_use;
+ table->keys_in_use_for_query= table->keys_in_use;
+ table->used_keys= table->keys_for_keyread;
DBUG_ASSERT(table->key_read == 0);
DBUG_RETURN(table);
}
@@ -1048,9 +1121,9 @@ bool reopen_table(TABLE *table,bool locked)
#endif
if (!locked)
VOID(pthread_mutex_lock(&LOCK_open));
+ safe_mutex_assert_owner(&LOCK_open);
- if (open_unireg_entry(current_thd,&tmp,db,table_name,table->table_name,
- locked))
+ if (open_unireg_entry(current_thd,&tmp,db,table_name,table->table_name))
goto end;
free_io_cache(table);
@@ -1069,7 +1142,8 @@ bool reopen_table(TABLE *table,bool locked)
tmp.null_row= table->null_row;
tmp.maybe_null= table->maybe_null;
tmp.status= table->status;
- tmp.keys_in_use_for_query=tmp.used_keys=tmp.keys_in_use;
+ tmp.keys_in_use_for_query= tmp.keys_in_use;
+ tmp.used_keys= tmp.keys_for_keyread;
/* Get state */
tmp.key_length= table->key_length;
@@ -1138,6 +1212,8 @@ bool close_data_tables(THD *thd,const char *db, const char *table_name)
bool reopen_tables(THD *thd,bool get_locks,bool in_refresh)
{
DBUG_ENTER("reopen_tables");
+ safe_mutex_assert_owner(&LOCK_open);
+
if (!thd->open_tables)
DBUG_RETURN(0);
@@ -1288,7 +1364,6 @@ bool wait_for_tables(THD *thd)
/* Now we can open all tables without any interference */
thd->proc_info="Reopen tables";
result=reopen_tables(thd,0,0);
-
}
pthread_mutex_unlock(&LOCK_open);
thd->proc_info=0;
@@ -1353,7 +1428,7 @@ void abort_locked_tables(THD *thd,const char *db, const char *table_name)
*/
static int open_unireg_entry(THD *thd, TABLE *entry, const char *db,
- const char *name, const char *alias, bool locked)
+ const char *name, const char *alias)
{
char path[FN_REFLEN];
int error;
@@ -1373,21 +1448,17 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db,
table_list.db=(char*) db;
table_list.name=(char*) name;
table_list.next=0;
- if (!locked)
- pthread_mutex_lock(&LOCK_open);
+ safe_mutex_assert_owner(&LOCK_open);
+
if ((error=lock_table_name(thd,&table_list)))
{
if (error < 0)
{
- if (!locked)
- pthread_mutex_unlock(&LOCK_open);
goto err;
}
if (wait_for_locked_table_names(thd,&table_list))
{
unlock_table_name(thd,&table_list);
- if (!locked)
- pthread_mutex_unlock(&LOCK_open);
goto err;
}
}
@@ -1417,9 +1488,9 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db,
thd->net.last_error[0]=0; // Clear error message
thd->net.last_errno=0;
}
- if (locked)
- pthread_mutex_lock(&LOCK_open); // Get back original lock
+ pthread_mutex_lock(&LOCK_open);
unlock_table_name(thd,&table_list);
+
if (error)
goto err;
}
@@ -1478,9 +1549,9 @@ int open_tables(THD *thd,TABLE_LIST *start)
}
}
*prev_table=0;
+ pthread_mutex_unlock(&LOCK_open);
if (found)
VOID(pthread_cond_broadcast(&COND_refresh)); // Signal to refresh
- pthread_mutex_unlock(&LOCK_open);
goto restart;
}
result= -1; // Fatal error
@@ -1698,7 +1769,7 @@ Field *find_field_in_table(THD *thd,TABLE *table,const char *name,uint length,
{
field->query_id=thd->query_id;
table->used_fields++;
- table->used_keys&=field->part_of_key;
+ table->used_keys&= field->part_of_key;
}
else
thd->dupp_field=field;
@@ -1905,7 +1976,8 @@ bool setup_tables(TABLE_LIST *tables)
table->const_table=0;
table->outer_join=table->null_row=0;
table->status=STATUS_NO_RECORD;
- table->keys_in_use_for_query=table->used_keys= table->keys_in_use;
+ table->keys_in_use_for_query= table->keys_in_use;
+ table->used_keys= table->keys_for_keyread;
table->maybe_null=test(table->outer_join=table_list->outer_join);
table->tablenr=tablenr;
table->map= (table_map) 1 << tablenr;
@@ -1995,7 +2067,7 @@ insert_fields(THD *thd,TABLE_LIST *tables, const char *db_name,
if (field->query_id == thd->query_id)
thd->dupp_field=field;
field->query_id=thd->query_id;
- table->used_keys&=field->part_of_key;
+ table->used_keys&= field->part_of_key;
}
/* All fields are used */
table->used_fields=table->fields;
@@ -2184,6 +2256,7 @@ int mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys)
DBUG_ENTER("mysql_create_index");
bzero((char*) &create_info,sizeof(create_info));
create_info.db_type=DB_TYPE_DEFAULT;
+ /* TODO: Fix to use database character set */
create_info.table_charset=default_charset_info;
DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->real_name,
&create_info, table_list,
@@ -2322,6 +2395,7 @@ int setup_ftfuncs(THD *thd)
return 0;
}
+
int init_ftfuncs(THD *thd, bool no_order)
{
if (thd->lex.select->ftfunc_list.elements)
@@ -2332,9 +2406,7 @@ int init_ftfuncs(THD *thd, bool no_order)
thd->proc_info="FULLTEXT initialization";
while ((ifm=li++))
- {
ifm->init_search(no_order);
- }
}
return 0;
}
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index c739b43debb..26fa0bb0481 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -299,11 +299,15 @@ TODO list:
pthread_mutex_lock(M);}
#define MUTEX_UNLOCK(M) {DBUG_PRINT("lock", ("mutex unlock 0x%lx",\
(ulong)(M))); pthread_mutex_unlock(M);}
-#define SEM_LOCK(M) { int val = 0; sem_getvalue (M, &val); \
- DBUG_PRINT("lock", ("sem lock 0x%lx (%d)", (ulong)(M), val)); \
- sem_wait(M); DBUG_PRINT("lock", ("sem lock ok")); }
-#define SEM_UNLOCK(M) {DBUG_PRINT("info", ("sem unlock 0x%lx", (ulong)(M))); \
- sem_post(M); DBUG_PRINT("info", ("sem unlock ok")); }
+#define RW_WLOCK(M) {DBUG_PRINT("lock", ("rwlock wlock 0x%lx",(ulong)(M))); \
+ if (!rw_wrlock(M)) DBUG_PRINT("lock", ("rwlock wlock ok")) \
+ else DBUG_PRINT("lock", ("rwlock wlock FAILED %d", errno)); }
+#define RW_RLOCK(M) {DBUG_PRINT("lock", ("rwlock rlock 0x%lx", (ulong)(M))); \
+ if (!rw_rdlock(M)) DBUG_PRINT("lock", ("rwlock rlock ok")) \
+ else DBUG_PRINT("lock", ("rwlock wlock FAILED %d", errno)); }
+#define RW_UNLOCK(M) {DBUG_PRINT("lock", ("rwlock unlock 0x%lx",(ulong)(M))); \
+ if (!rw_unlock(M)) DBUG_PRINT("lock", ("rwlock unlock ok")) \
+ else DBUG_PRINT("lock", ("rwlock unlock FAILED %d", errno)); }
#define STRUCT_LOCK(M) {DBUG_PRINT("lock", ("%d struct lock...",__LINE__)); \
pthread_mutex_lock(M);DBUG_PRINT("lock", ("struct lock OK"));}
#define STRUCT_UNLOCK(M) { \
@@ -326,8 +330,9 @@ TODO list:
#else
#define MUTEX_LOCK(M) pthread_mutex_lock(M)
#define MUTEX_UNLOCK(M) pthread_mutex_unlock(M)
-#define SEM_LOCK(M) sem_wait(M)
-#define SEM_UNLOCK(M) sem_post(M)
+#define RW_WLOCK(M) rw_wrlock(M)
+#define RW_RLOCK(M) rw_rdlock(M)
+#define RW_UNLOCK(M) rw_unlock(M)
#define STRUCT_LOCK(M) pthread_mutex_lock(M)
#define STRUCT_UNLOCK(M) pthread_mutex_unlock(M)
#define BLOCK_LOCK_WR(B) B->query()->lock_writing()
@@ -337,6 +342,12 @@ TODO list:
#define DUMP(C)
#endif
+const char *query_cache_type_names[]= { "OFF", "ON", "DEMAND",NullS };
+TYPELIB query_cache_type_typelib=
+{
+ array_elements(query_cache_type_names)-1,"", query_cache_type_names
+};
+
/*****************************************************************************
Query_cache_block_table method(s)
*****************************************************************************/
@@ -445,9 +456,7 @@ void Query_cache_query::init_n_lock()
{
DBUG_ENTER("Query_cache_query::init_n_lock");
res=0; wri = 0; len = 0;
- sem_init(&lock, 0, 1);
- pthread_mutex_init(&clients_guard,MY_MUTEX_INIT_FAST);
- clients = 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))));
@@ -465,8 +474,7 @@ void Query_cache_query::unlock_n_destroy()
active semaphore
*/
this->unlock_writing();
- sem_destroy(&lock);
- pthread_mutex_destroy(&clients_guard);
+ rwlock_destroy(&lock);
DBUG_VOID_RETURN;
}
@@ -479,9 +487,9 @@ void Query_cache_query::unlock_n_destroy()
Lock for read prevents only locking for write.
*/
-void Query_cache_query::lock_writing()
+inline void Query_cache_query::lock_writing()
{
- SEM_LOCK(&lock);
+ RW_WLOCK(&lock);
}
@@ -495,41 +503,31 @@ void Query_cache_query::lock_writing()
my_bool Query_cache_query::try_lock_writing()
{
DBUG_ENTER("Query_cache_block::try_lock_writing");
- if (sem_trywait(&lock)!=0 || clients != 0)
+ if (rw_trywrlock(&lock)!=0)
{
- DBUG_PRINT("info", ("can't lock semaphore"));
+ DBUG_PRINT("info", ("can't lock rwlock"));
DBUG_RETURN(0);
}
- DBUG_PRINT("info", ("mutex 'lock' 0x%lx locked", (ulong) &lock));
+ DBUG_PRINT("info", ("rwlock 0x%lx locked", (ulong) &lock));
DBUG_RETURN(1);
}
-void Query_cache_query::lock_reading()
+inline void Query_cache_query::lock_reading()
{
- MUTEX_LOCK(&clients_guard);
- if ( ++clients == 1 )
- SEM_LOCK(&lock);
- MUTEX_UNLOCK(&clients_guard);
+ RW_RLOCK(&lock);
}
-void Query_cache_query::unlock_writing()
+inline void Query_cache_query::unlock_writing()
{
- SEM_UNLOCK(&lock);
+ RW_UNLOCK(&lock);
}
-void Query_cache_query::unlock_reading()
+inline void Query_cache_query::unlock_reading()
{
- /*
- To avoid unlocking semaphore before unlocking mutex (that may cause
- destroying locked mutex), we use temporary boolean variable 'unlock'.
- */
- MUTEX_LOCK(&clients_guard);
- bool ulock = ((--clients) == 0);
- MUTEX_UNLOCK(&clients_guard);
- if (ulock) SEM_UNLOCK(&lock);
+ RW_UNLOCK(&lock);
}
extern "C"
@@ -704,28 +702,28 @@ Query_cache::Query_cache(ulong query_cache_limit,
query_cache_limit(query_cache_limit),
queries_in_cache(0), hits(0), inserts(0), refused(0),
total_blocks(0),
- min_allocation_unit(min_allocation_unit),
- min_result_data_size(min_result_data_size),
- def_query_hash_size(def_query_hash_size),
- def_table_hash_size(def_table_hash_size),
+ 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)),
initialized(0)
{
ulong min_needed=(ALIGN_SIZE(sizeof(Query_cache_block)) +
ALIGN_SIZE(sizeof(Query_cache_block_table)) +
ALIGN_SIZE(sizeof(Query_cache_query)) + 3);
set_if_bigger(min_allocation_unit,min_needed);
- this->min_allocation_unit = min_allocation_unit;
+ this->min_allocation_unit = ALIGN_SIZE(min_allocation_unit);
set_if_bigger(this->min_result_data_size,min_allocation_unit);
}
-ulong Query_cache::resize(ulong query_cache_size)
+ulong Query_cache::resize(ulong query_cache_size_arg)
{
DBUG_ENTER("Query_cache::resize");
- DBUG_PRINT("qcache", ("from %lu to %lu",this->query_cache_size,
- query_cache_size));
+ DBUG_PRINT("qcache", ("from %lu to %lu",query_cache_size,
+ query_cache_size_arg));
free_cache(0);
- this->query_cache_size=query_cache_size;
+ query_cache_size=query_cache_size_arg;
DBUG_RETURN(init_cache());
}
@@ -765,10 +763,10 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used)
most significant bit - CLIENT_LONG_FLAG,
other - charset number (0 no charset convertion)
*/
- if (thd->convert_set != 0)
+ if (thd->variables.convert_set != 0)
{
- flags|= (byte) thd->convert_set->number();
- DBUG_ASSERT(thd->convert_set->number() < 128);
+ flags|= (byte) thd->variables.convert_set->number();
+ DBUG_ASSERT(thd->variables.convert_set->number() < 128);
}
tot_length=thd->query_length+thd->db_length+2;
thd->query[tot_length-1] = (char) flags;
@@ -872,13 +870,10 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
it is not possible to check has_transactions() function of handler
because tables not opened yet
*/
- (thd->options & (OPTION_NOT_AUTO_COMMIT | OPTION_BEGIN)) ||
- thd->query_cache_type == 0)
+ (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) ||
+ thd->variables.query_cache_type == 0)
- {
- DBUG_PRINT("qcache", ("query cache disabled or not in autocommit mode"));
goto err;
- }
/* Check that we haven't forgot to reset the query cache variables */
DBUG_ASSERT(thd->net.query_cache_query == 0);
@@ -926,10 +921,10 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
Other - charset number (0 no charset convertion)
*/
flags = (thd->client_capabilities & CLIENT_LONG_FLAG ? 0x80 : 0);
- if (thd->convert_set != 0)
+ if (thd->variables.convert_set != 0)
{
- flags |= (byte) thd->convert_set->number();
- DBUG_ASSERT(thd->convert_set->number() < 128);
+ flags |= (byte) thd->variables.convert_set->number();
+ DBUG_ASSERT(thd->variables.convert_set->number() < 128);
}
sql[tot_length-1] = (char) flags;
query_block = (Query_cache_block *) hash_search(&queries, (byte*) sql,
@@ -962,7 +957,7 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
// Check access;
block_table= query_block->table(0);
block_table_end= block_table+query_block->n_tables;
- for ( ; block_table != block_table_end; block_table++)
+ for (; block_table != block_table_end; block_table++)
{
TABLE_LIST table_list;
bzero((char*) &table_list,sizeof(table_list));
@@ -1024,6 +1019,7 @@ err:
DBUG_RETURN(0); // Query was not cached
}
+
/*
Remove all cached queries that uses any of the tables in the list
*/
@@ -1040,8 +1036,8 @@ void Query_cache::invalidate(THD *thd, TABLE_LIST *tables_used,
DUMP(this);
using_transactions = using_transactions &&
- (thd->options & (OPTION_NOT_AUTO_COMMIT | OPTION_BEGIN));
- for ( ; tables_used; tables_used=tables_used->next)
+ (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN));
+ for (; tables_used; tables_used=tables_used->next)
{
DBUG_ASSERT(!using_transactions || tables_used->table!=0);
if (using_transactions &&
@@ -1070,11 +1066,12 @@ void Query_cache::invalidate(CHANGED_TABLE_LIST *tables_used)
if (query_cache_size > 0)
{
DUMP(this);
- for ( ; tables_used; tables_used=tables_used->next)
+ for (; tables_used; tables_used=tables_used->next)
{
invalidate_table((byte*) tables_used->key, tables_used->key_length);
DBUG_PRINT("qcache", (" db %s, table %s", tables_used->key,
- tables_used->table_name));
+ tables_used->key+
+ strlen(tables_used->key)+1));
}
}
STRUCT_UNLOCK(&structure_guard_mutex);
@@ -1097,7 +1094,7 @@ void Query_cache::invalidate(THD *thd, TABLE *table,
if (query_cache_size > 0)
{
using_transactions = using_transactions &&
- (thd->options & (OPTION_NOT_AUTO_COMMIT | OPTION_BEGIN));
+ (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN));
if (using_transactions && table->file->has_transactions())
thd->add_changed_table(table);
else
@@ -1188,15 +1185,17 @@ void Query_cache::pack(ulong join_limit, uint iteration_limit)
void Query_cache::destroy()
{
- if ( !initialized )
+ DBUG_ENTER("Query_cache::destroy");
+ if (!initialized)
{
DBUG_PRINT("qcache", ("Query Cache not initialized"));
- return;
}
- DBUG_ENTER("Query_cache::destroy");
- free_cache(1);
- pthread_mutex_destroy(&structure_guard_mutex);
- initialized = 0;
+ else
+ {
+ free_cache(1);
+ pthread_mutex_destroy(&structure_guard_mutex);
+ initialized = 0;
+ }
DBUG_VOID_RETURN;
}
@@ -1219,6 +1218,7 @@ ulong Query_cache::init_cache()
uint mem_bin_count, num, step;
ulong mem_bin_size, prev_size, inc;
ulong additional_data_size, max_mem_bin_size, approx_additional_data_size;
+ int align;
DBUG_ENTER("Query_cache::init_cache");
if (!initialized)
@@ -1229,7 +1229,13 @@ ulong Query_cache::init_cache()
if (query_cache_size < approx_additional_data_size)
goto err;
- query_cache_size -= approx_additional_data_size;
+ query_cache_size-= approx_additional_data_size;
+ align= query_cache_size % ALIGN_SIZE(1);
+ if (align)
+ {
+ query_cache_size-= align;
+ approx_additional_data_size+= align;
+ }
/*
Count memory bins number.
@@ -1269,10 +1275,11 @@ ulong Query_cache::init_cache()
query_cache_size -= additional_data_size;
STRUCT_LOCK(&structure_guard_mutex);
- if (query_cache_size <= min_allocation_unit)
+ if (max_mem_bin_size <= min_allocation_unit)
{
DBUG_PRINT("qcache",
- (" query_cache_size <= min_allocation_unit => cache disabled"));
+ (" max bin size (%lu) <= min_allocation_unit => cache disabled",
+ max_mem_bin_size));
STRUCT_UNLOCK(&structure_guard_mutex);
goto err;
}
@@ -1543,10 +1550,12 @@ Query_cache::write_block_data(ulong data_len, gptr data,
ALIGN_SIZE(ntab*sizeof(Query_cache_block_table)) +
header_len);
ulong len = data_len + all_headers_len;
+ ulong align_len= ALIGN_SIZE(len);
DBUG_ENTER("Query_cache::write_block_data");
DBUG_PRINT("qcache", ("data: %ld, header: %ld, all header: %ld",
data_len, header_len, all_headers_len));
- Query_cache_block *block = allocate_block(max(len, min_allocation_unit),
+ Query_cache_block *block = allocate_block(max(align_len,
+ min_allocation_unit),
1, 0, under_guard);
if (block != 0)
{
@@ -1741,7 +1750,8 @@ my_bool Query_cache::allocate_data_chain(Query_cache_block **result_block,
{
ulong all_headers_len = (ALIGN_SIZE(sizeof(Query_cache_block)) +
ALIGN_SIZE(sizeof(Query_cache_result)));
- ulong len = data_len + all_headers_len;
+ ulong len= data_len + all_headers_len;
+ ulong align_len= ALIGN_SIZE(len);
DBUG_ENTER("Query_cache::allocate_data_chain");
DBUG_PRINT("qcache", ("data_len %lu, all_headers_len %lu",
data_len, all_headers_len));
@@ -1749,7 +1759,7 @@ my_bool Query_cache::allocate_data_chain(Query_cache_block **result_block,
ulong min_size = (first_block ?
get_min_first_result_data_size():
get_min_append_result_data_size());
- *result_block = allocate_block(max(min_size,len),
+ *result_block = allocate_block(max(min_size, align_len),
min_result_data_size == 0,
all_headers_len + min_result_data_size,
1);
@@ -1985,7 +1995,7 @@ Query_cache_block *
Query_cache::allocate_block(ulong len, my_bool not_less, ulong min,
my_bool under_guard)
{
- DBUG_ENTER("Query_cache::allocate_n_lock_block");
+ DBUG_ENTER("Query_cache::allocate_block");
DBUG_PRINT("qcache", ("len %lu, not less %d, min %lu, uder_guard %d",
len, not_less,min,under_guard));
@@ -2033,7 +2043,6 @@ Query_cache::get_free_block(ulong len, my_bool not_less, ulong min)
if (bins[start].number != 0)
{
Query_cache_block *list = bins[start].free_blocks;
- ulong max_len = list->prev->length;
if (list->prev->length >= len) // check block with max size
{
first = list;
@@ -2128,8 +2137,10 @@ void Query_cache::split_block(Query_cache_block *block, ulong len)
new_block->pnext->pprev = new_block;
if (block->type == Query_cache_block::FREE)
+ {
// if block was free then it already joined with all free neighbours
insert_into_free_memory_list(new_block);
+ }
else
free_memory_block(new_block);
@@ -2325,7 +2336,7 @@ Query_cache::double_linked_list_simple_include(Query_cache_block *point,
*list_pointer=point->next=point->prev=point;
else
{
- // insert to and of list
+ // insert to the end of list
point->next = (*list_pointer);
point->prev = (*list_pointer)->prev;
point->prev->next = point;
@@ -2382,17 +2393,16 @@ TABLE_COUNTER_TYPE Query_cache::is_cacheable(THD *thd, uint32 query_len,
DBUG_ENTER("Query_cache::is_cacheable");
if (lex->sql_command == SQLCOM_SELECT &&
- thd->temporary_tables == 0 &&
- (thd->query_cache_type == 1 ||
- (thd->query_cache_type == 2 && (lex->select->options &
- OPTION_TO_QUERY_CACHE))) &&
+ (thd->variables.query_cache_type == 1 ||
+ (thd->variables.query_cache_type == 2 && (lex->select->options &
+ OPTION_TO_QUERY_CACHE))) &&
thd->safe_to_cache_query)
{
my_bool has_transactions = 0;
DBUG_PRINT("qcache", ("options %lx %lx, type %u",
OPTION_TO_QUERY_CACHE,
lex->select->options,
- (int) thd->query_cache_type));
+ (int) thd->variables.query_cache_type));
for (; tables_used; tables_used=tables_used->next)
{
@@ -2403,9 +2413,11 @@ TABLE_COUNTER_TYPE Query_cache::is_cacheable(THD *thd, uint32 query_len,
has_transactions = (has_transactions ||
tables_used->table->file->has_transactions());
- if (tables_used->table->db_type == DB_TYPE_MRG_ISAM)
+ if (tables_used->table->db_type == DB_TYPE_MRG_ISAM ||
+ tables_used->table->tmp_table != NO_TMP_TABLE)
{
- DBUG_PRINT("qcache", ("select not cacheable: used MRG_ISAM table(s)"));
+ DBUG_PRINT("qcache",
+ ("select not cacheable: used MRG_ISAM or temporary table(s)"));
DBUG_RETURN(0);
}
if (tables_used->table->db_type == DB_TYPE_MRG_MYISAM)
@@ -2416,7 +2428,7 @@ TABLE_COUNTER_TYPE Query_cache::is_cacheable(THD *thd, uint32 query_len,
}
}
- if ((thd->options & (OPTION_NOT_AUTO_COMMIT | OPTION_BEGIN)) &&
+ if ((thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) &&
has_transactions)
{
DBUG_PRINT("qcache", ("not in autocommin mode"));
@@ -2431,7 +2443,7 @@ TABLE_COUNTER_TYPE Query_cache::is_cacheable(THD *thd, uint32 query_len,
(int) lex->sql_command,
OPTION_TO_QUERY_CACHE,
lex->select->options,
- (int) thd->query_cache_type));
+ (int) thd->variables.query_cache_type));
DBUG_RETURN(0);
}
@@ -2620,8 +2632,7 @@ my_bool Query_cache::move_by_type(byte **border,
} while ( result_block != first_result_block );
}
Query_cache_query *new_query= ((Query_cache_query *) new_block->data());
- sem_init(&new_query->lock, 0, 1);
- pthread_mutex_init(&new_query->clients_guard,MY_MUTEX_INIT_FAST);
+ my_rwlock_init(&new_query->lock, NULL);
/*
If someone is writing to this block, inform the writer that the block
@@ -2670,14 +2681,17 @@ my_bool Query_cache::move_by_type(byte **border,
*border += len;
*before = new_block;
/* If result writing complete && we have free space in block */
- ulong free_space = new_block->length - new_block->used;
+ ulong free_space= new_block->length - new_block->used;
+ free_space-= free_space % ALIGN_SIZE(1);
if (query->result()->type == Query_cache_block::RESULT &&
new_block->length > new_block->used &&
*gap + free_space > min_allocation_unit &&
new_block->length - free_space > min_allocation_unit)
{
- *border -= free_space;
- *gap += free_space;
+ *border-= free_space;
+ *gap+= free_space;
+ DBUG_PRINT("qcache",
+ ("rest of result free space added to gap (%lu)", *gap));
new_block->length -= free_space;
}
BLOCK_UNLOCK_WR(query_block);
@@ -2738,7 +2752,7 @@ my_bool Query_cache::join_results(ulong join_limit)
header->length() > join_limit)
{
Query_cache_block *new_result_block =
- get_free_block(header->length() +
+ get_free_block(ALIGN_SIZE(header->length()) +
ALIGN_SIZE(sizeof(Query_cache_block)) +
ALIGN_SIZE(sizeof(Query_cache_result)), 1, 0);
if (new_result_block != 0)
@@ -2857,7 +2871,7 @@ void Query_cache::bins_dump()
{
uint i;
- if ( !initialized )
+ if (!initialized)
{
DBUG_PRINT("qcache", ("Query Cache not initialized"));
return;
@@ -2898,8 +2912,7 @@ void Query_cache::bins_dump()
void Query_cache::cache_dump()
{
-
- if ( !initialized )
+ if (!initialized)
{
DBUG_PRINT("qcache", ("Query Cache not initialized"));
return;
@@ -2926,7 +2939,7 @@ void Query_cache::cache_dump()
void Query_cache::queries_dump()
{
- if ( !initialized )
+ if (!initialized)
{
DBUG_PRINT("qcache", ("Query Cache not initialized"));
return;
@@ -2988,8 +3001,7 @@ void Query_cache::queries_dump()
void Query_cache::tables_dump()
{
-
- if ( !initialized )
+ if (!initialized)
{
DBUG_PRINT("qcache", ("Query Cache not initialized"));
return;
@@ -3047,11 +3059,20 @@ my_bool Query_cache::check_integrity(bool not_locked)
{
DBUG_PRINT("qcache", ("block 0x%lx, type %u...",
(ulong) block, (uint) block->type));
+ // Check allignment
+ if ((((long)block) % (long) ALIGN_SIZE(1)) !=
+ (((long)first_block) % (long)ALIGN_SIZE(1)))
+ {
+ DBUG_PRINT("error",
+ ("block 0x%lx do not aligned by %d", (ulong) block,
+ ALIGN_SIZE(1)));
+ result = 1;
+ }
// Check memory allocation
if (block->pnext == first_block) // Is it last block?
{
- if ( ((byte*)block) + block->length !=
- ((byte*)first_block) + query_cache_size )
+ if (((byte*)block) + block->length !=
+ ((byte*)first_block) + query_cache_size)
{
DBUG_PRINT("error",
("block 0x%lx, type %u, ended at 0x%lx, but cache ended at 0x%lx",
@@ -3071,16 +3092,16 @@ my_bool Query_cache::check_integrity(bool not_locked)
(ulong) ((byte*)block->pnext)));
}
if (block->type == Query_cache_block::FREE)
- free+=block->length;
+ free+= block->length;
else
- used+=block->length;
+ used+= block->length;
switch(block->type) {
case Query_cache_block::FREE:
{
Query_cache_memory_bin *bin = *((Query_cache_memory_bin **)
block->data());
//is it correct pointer?
- if ( ((byte*)bin) < ((byte*)bins) ||
+ if (((byte*)bin) < ((byte*)bins) ||
((byte*)bin) >= ((byte*)first_block))
{
DBUG_PRINT("error",
@@ -3131,7 +3152,7 @@ my_bool Query_cache::check_integrity(bool not_locked)
case Query_cache_block::RESULT:
{
Query_cache_block * query_block = block->result()->parent();
- if ( ((byte*)query_block) < ((byte*)first_block) ||
+ if (((byte*)query_block) < ((byte*)first_block) ||
((byte*)query_block) >= (((byte*)first_block) + query_cache_size))
{
DBUG_PRINT("error",
@@ -3283,7 +3304,7 @@ my_bool Query_cache::in_blocks(Query_cache_block * point)
(ulong) block->pprev->pnext,
(ulong) point));
//back trace
- for(; block != point; block = block->pnext)
+ for (; block != point; block = block->pnext)
DBUG_PRINT("error", ("back trace 0x%lx", (ulong) block));
result = 1;
goto err1;
@@ -3311,7 +3332,7 @@ err1:
(ulong) block->pnext->pprev,
(ulong) point));
//back trace
- for(; block != point; block = block->pprev)
+ for (; block != point; block = block->pprev)
DBUG_PRINT("error", ("back trace 0x%lx", (ulong) block));
result = 1;
goto err2;
@@ -3340,7 +3361,7 @@ my_bool Query_cache::in_list(Query_cache_block * root,
(ulong) block->prev->next,
(ulong) point));
//back trace
- for(; block != point; block = block->next)
+ for (; block != point; block = block->next)
DBUG_PRINT("error", ("back trace 0x%lx", (ulong) block));
result = 1;
goto err1;
@@ -3414,7 +3435,7 @@ my_bool Query_cache::in_table_list(Query_cache_block_table * root,
(ulong) table->prev->next->block(),
(ulong) point, (ulong) point->block()));
//back trace
- for(; table != point; table = table->next)
+ for (; table != point; table = table->next)
DBUG_PRINT("error", ("back trace 0x%lx(0x%lx)",
(ulong) table, (ulong) table->block()));
result = 1;
diff --git a/sql/sql_cache.h b/sql/sql_cache.h
index 81ea80669b8..3088331f19a 100644
--- a/sql/sql_cache.h
+++ b/sql/sql_cache.h
@@ -63,8 +63,6 @@
#define TABLE_COUNTER_TYPE uint8
-#include <my_semaphore.h>
-
struct Query_cache_block;
struct Query_cache_block_table;
struct Query_cache_table;
@@ -110,16 +108,13 @@ struct Query_cache_block
inline Query_cache_block_table *table(TABLE_COUNTER_TYPE n);
};
-
struct Query_cache_query
{
ulonglong limit_found_rows;
+ rw_lock_t lock;
Query_cache_block *res;
NET *wri;
ulong len;
- sem_t lock; // R/W lock of block
- pthread_mutex_t clients_guard;
- uint clients;
inline void init_n_lock();
void unlock_n_destroy();
@@ -194,10 +189,10 @@ struct Query_cache_memory_bin
uint number;
Query_cache_block *free_blocks;
- inline void init(ulong size)
+ inline void init(ulong size_arg)
{
#ifndef DBUG_OFF
- this->size = size;
+ size = size_arg;
#endif
number = 0;
free_blocks = 0;
@@ -209,11 +204,11 @@ struct Query_cache_memory_bin_step
ulong size;
ulong increment;
uint idx;
- inline void init(ulong size, uint idx, ulong increment)
+ inline void init(ulong size_arg, uint idx_arg, ulong increment_arg)
{
- this->size = size;
- this->idx = idx;
- this->increment = increment;
+ size = size_arg;
+ idx = idx_arg;
+ increment = increment_arg;
}
};
@@ -403,6 +398,7 @@ protected:
};
extern Query_cache query_cache;
+extern TYPELIB query_cache_type_typelib;
void query_cache_insert(NET *net, const char *packet, ulong length);
void query_cache_end_of_result(NET *net);
void query_cache_abort(NET *net);
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 9922eacdec1..41def4aa1b5 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -51,8 +51,6 @@ template class List<Alter_drop>;
template class List_iterator<Alter_drop>;
template class List<Alter_column>;
template class List_iterator<Alter_column>;
-template class List<Set_option>;
-template class List_iterator<Set_option>;
#endif
/****************************************************************************
@@ -87,6 +85,9 @@ THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0),
host_or_ip="unknown ip";
locked=killed=count_cuted_fields=some_tables_deleted=no_errors=password=
query_start_used=safe_to_cache_query=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;
@@ -102,7 +103,6 @@ THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0),
slave_proxy_id = 0;
file_id = 0;
cond_count=0;
- convert_set=0;
db_charset=default_charset_info;
mysys_var=0;
#ifndef DBUG_OFF
@@ -117,8 +117,8 @@ THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0),
#endif
#ifdef SIGNAL_WITH_VIO_CLOSE
active_vio = 0;
- pthread_mutex_init(&active_vio_lock, MY_MUTEX_INIT_FAST);
#endif
+ pthread_mutex_init(&LOCK_delete, MY_MUTEX_INIT_FAST);
/* Variables with default values */
proc_info="login";
@@ -127,23 +127,15 @@ THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0),
slave_net = 0;
log_pos = 0;
server_status= SERVER_STATUS_AUTOCOMMIT;
- update_lock_default= low_priority_updates ? TL_WRITE_LOW_PRIORITY : TL_WRITE;
+ update_lock_default= (variables.low_priority_updates ?
+ TL_WRITE_LOW_PRIORITY :
+ TL_WRITE);
options= thd_startup_options;
-#ifdef HAVE_QUERY_CACHE
- query_cache_type= (byte) query_cache_startup_type;
-#else
- query_cache_type= 0; //Safety
-#endif
sql_mode=(uint) opt_sql_mode;
- inactive_timeout=net_wait_timeout;
open_options=ha_open_options;
- tx_isolation=session_tx_isolation=default_tx_isolation;
+ session_tx_isolation= (enum_tx_isolation) variables.tx_isolation;
command=COM_CONNECT;
set_query_id=1;
- default_select_limit= HA_POS_ERROR;
- max_error_count=max_warning_count=MYSQL_DEFAULT_ERROR_COUNT;
- max_join_size= ((::max_join_size != ~ (ulong) 0L) ? ::max_join_size :
- HA_POS_ERROR);
db_access=NO_ACCESS;
/* Initialize sub structures */
@@ -199,6 +191,10 @@ THD::~THD()
{
THD_CHECK_SENTRY(this);
DBUG_ENTER("~THD()");
+ /* Ensure that no one is using THD */
+ pthread_mutex_lock(&LOCK_delete);
+ pthread_mutex_unlock(&LOCK_delete);
+
/* Close connection */
if (net.vio)
{
@@ -218,7 +214,6 @@ THD::~THD()
hash_free(&user_vars);
DBUG_PRINT("info", ("freeing host"));
-
if (host != localhost) // If not pointer to constant
safeFree(host);
if (user != delayed_user)
@@ -229,18 +224,19 @@ THD::~THD()
free_root(&con_root,MYF(0));
free_root(&transaction.mem_root,MYF(0));
mysys_var=0; // Safety (shouldn't be needed)
-#ifdef SIGNAL_WITH_VIO_CLOSE
- pthread_mutex_destroy(&active_vio_lock);
-#endif
+ pthread_mutex_destroy(&LOCK_delete);
#ifndef DBUG_OFF
dbug_sentry = THD_SENTRY_GONE;
#endif
DBUG_VOID_RETURN;
}
+
void THD::awake(bool prepare_to_die)
{
THD_CHECK_SENTRY(this);
+ safe_mutex_assert_owner(&LOCK_delete);
+
if (prepare_to_die)
killed = 1;
thr_alarm_kill(real_id);
@@ -248,26 +244,30 @@ void THD::awake(bool prepare_to_die)
close_active_vio();
#endif
if (mysys_var)
+ {
+ pthread_mutex_lock(&mysys_var->mutex);
+ if (!system_thread) // Don't abort locks
+ mysys_var->abort=1;
+ /*
+ This broadcast could be up in the air if the victim thread
+ exits the cond in the time between read and broadcast, but that is
+ ok since all we want to do is to make the victim thread get out
+ of waiting on current_cond.
+ */
+ if (mysys_var->current_cond)
{
- pthread_mutex_lock(&mysys_var->mutex);
- if (!system_thread) // Don't abort locks
- mysys_var->abort=1;
- // this broadcast could be up in the air if the victim thread
- // exits the cond in the time between read and broadcast, but that is
- // ok since all we want to do is to make the victim thread get out
- // of waiting on current_cond
- if (mysys_var->current_cond)
- {
- pthread_mutex_lock(mysys_var->current_mutex);
- pthread_cond_broadcast(mysys_var->current_cond);
- pthread_mutex_unlock(mysys_var->current_mutex);
- }
- pthread_mutex_unlock(&mysys_var->mutex);
+ pthread_mutex_lock(mysys_var->current_mutex);
+ pthread_cond_broadcast(mysys_var->current_cond);
+ pthread_mutex_unlock(mysys_var->current_mutex);
}
+ pthread_mutex_unlock(&mysys_var->mutex);
+ }
}
-// remember the location of thread info, the structure needed for
-// sql_alloc() and the structure for the net buffer
+/*
+ Remember the location of thread info, the structure needed for
+ sql_alloc() and the structure for the net buffer
+*/
bool THD::store_globals()
{
@@ -276,6 +276,7 @@ bool THD::store_globals()
my_pthread_setspecific_ptr(THR_NET, &net));
}
+
/* routings to adding tables to list of changed in transaction tables */
inline static void list_include(CHANGED_TABLE_LIST** prev,
@@ -290,17 +291,18 @@ inline static void list_include(CHANGED_TABLE_LIST** prev,
}
/* add table to list of changed in transaction tables */
+
void THD::add_changed_table(TABLE *table)
{
- DBUG_ENTER("THD::add_changed_table (table)");
+ DBUG_ENTER("THD::add_changed_table(table)");
- DBUG_ASSERT((options & (OPTION_NOT_AUTO_COMMIT | OPTION_BEGIN)) &&
- table->file->has_transactions());
+ DBUG_ASSERT((options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) &&
+ table->file->has_transactions());
CHANGED_TABLE_LIST** prev = &transaction.changed_tables;
CHANGED_TABLE_LIST* curr = transaction.changed_tables;
- for(; curr; prev = &(curr->next), curr = curr->next)
+ for (; curr; prev = &(curr->next), curr = curr->next)
{
int cmp = (long)curr->key_length - (long)table->key_length;
if (cmp < 0)
@@ -317,7 +319,8 @@ void THD::add_changed_table(TABLE *table)
{
list_include(prev, curr, changed_table_dup(table));
DBUG_PRINT("info",
- ("key_length %u %u", table->key_length, (*prev)->key_length));
+ ("key_length %u %u", table->key_length,
+ (*prev)->key_length));
DBUG_VOID_RETURN;
}
else if (cmp == 0)
@@ -328,10 +331,12 @@ void THD::add_changed_table(TABLE *table)
}
}
*prev = changed_table_dup(table);
- DBUG_PRINT("info", ("key_length %u %u", table->key_length, (*prev)->key_length));
+ DBUG_PRINT("info", ("key_length %u %u", table->key_length,
+ (*prev)->key_length));
DBUG_VOID_RETURN;
}
+
CHANGED_TABLE_LIST* THD::changed_table_dup(TABLE *table)
{
CHANGED_TABLE_LIST* new_table =
@@ -349,11 +354,7 @@ CHANGED_TABLE_LIST* THD::changed_table_dup(TABLE *table)
ALIGN_SIZE(sizeof(CHANGED_TABLE_LIST)));
new_table->next = 0;
new_table->key_length = table->key_length;
- uint32 db_len = ((new_table->table_name =
- ::strmake(new_table->key, table->table_cache_key,
- table->key_length) + 1) - new_table->key);
- ::memcpy(new_table->key + db_len, table->table_cache_key + db_len,
- table->key_length - db_len);
+ ::memcpy(new_table->key, table->table_cache_key, table->key_length);
return new_table;
}
@@ -614,7 +615,7 @@ bool select_export::send_data(List<Item> &items)
bfill(space,sizeof(space),' ');
}
uint length=item->max_length-used_length;
- for ( ; length > sizeof(space) ; length-=sizeof(space))
+ for (; length > sizeof(space) ; length-=sizeof(space))
{
if (my_b_write(&cache,(byte*) space,sizeof(space)))
goto err;
diff --git a/sql/sql_class.h b/sql/sql_class.h
index a6b7e45ab03..8b2e9400613 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -31,6 +31,8 @@ enum enum_enable_or_disable { LEAVE_AS_IS, ENABLE, DISABLE };
enum enum_ha_read_modes { RFIRST, RNEXT, RPREV, RLAST, RKEY };
enum enum_duplicates { DUP_ERROR, DUP_REPLACE, DUP_IGNORE };
enum enum_log_type { LOG_CLOSED, LOG_NORMAL, LOG_NEW, LOG_BIN };
+enum enum_delay_key_write { DELAY_KEY_WRITE_NONE, DELAY_KEY_WRITE_ON,
+ DELAY_KEY_WRITE_ALL };
// log info errors
#define LOG_INFO_EOF -1
@@ -47,7 +49,7 @@ struct st_relay_log_info;
typedef struct st_log_info
{
char log_file_name[FN_REFLEN];
- my_off_t index_file_offset;
+ my_off_t index_file_offset, index_file_start_offset;
my_off_t pos;
bool fatal; // if the purge happens to give us a negative offset
pthread_mutex_t lock;
@@ -60,63 +62,60 @@ class Log_event;
class MYSQL_LOG {
private:
pthread_mutex_t LOCK_log, LOCK_index;
+ pthread_cond_t update_cond;
+ ulonglong bytes_written;
time_t last_time,query_start;
IO_CACHE log_file;
- File index_file;
+ IO_CACHE index_file;
char *name;
- volatile enum_log_type log_type;
char time_buff[20],db[NAME_LEN+1];
char log_file_name[FN_REFLEN],index_file_name[FN_REFLEN];
+ // current file sequence number for load data infile binary logging
+ uint file_id;
+ uint open_count; // For replication
+ volatile enum_log_type log_type;
+ enum cache_type io_cache_type;
bool write_error,inited;
- uint file_id; // current file sequence number for load data infile
/*
- For binlog - if log name can never change
- we should not try to rotate it or write any rotation events
- the user should use FLUSH MASTER instead of FLUSH LOGS for
- purging
+ For binlog - if log name can never change we should not try to rotate it
+ or write any rotation events. The user should use FLUSH MASTER instead
+ of FLUSH LOGS for purging.
*/
bool no_rotate;
- enum cache_type io_cache_type;
bool need_start_event;
- pthread_cond_t update_cond;
bool no_auto_events; // for relay binlog
- ulonglong bytes_written;
friend class Log_event;
public:
MYSQL_LOG();
~MYSQL_LOG();
- pthread_mutex_t* get_log_lock() { return &LOCK_log; }
void reset_bytes_written()
- {
- bytes_written = 0;
- }
+ {
+ bytes_written = 0;
+ }
void harvest_bytes_written(ulonglong* counter)
- {
+ {
#ifndef DBUG_OFF
- char buf1[22],buf2[22];
+ char buf1[22],buf2[22];
#endif
- DBUG_ENTER("harvest_bytes_written");
- (*counter)+=bytes_written;
- DBUG_PRINT("info",("counter=%s,bytes_written=%s", llstr(*counter,buf1),
- llstr(bytes_written,buf2)));
- bytes_written=0;
- DBUG_VOID_RETURN;
- }
- IO_CACHE* get_log_file() { return &log_file; }
+ DBUG_ENTER("harvest_bytes_written");
+ (*counter)+=bytes_written;
+ DBUG_PRINT("info",("counter: %s bytes_written: %s", llstr(*counter,buf1),
+ llstr(bytes_written,buf2)));
+ bytes_written=0;
+ DBUG_VOID_RETURN;
+ }
void signal_update() { pthread_cond_broadcast(&update_cond);}
void wait_for_update(THD* thd);
void set_need_start_event() { need_start_event = 1; }
- void set_index_file_name(const char* index_file_name = 0);
void init(enum_log_type log_type_arg,
enum cache_type io_cache_type_arg = WRITE_CACHE,
bool no_auto_events_arg = 0);
- void open(const char *log_name,enum_log_type log_type,
- const char *new_name, enum cache_type io_cache_type_arg,
+ bool open(const char *log_name,enum_log_type log_type,
+ const char *new_name, const char *index_file_name_arg,
+ enum cache_type io_cache_type_arg,
bool no_auto_events_arg);
- void new_file(bool inside_mutex = 0);
- bool open_index(int options);
- void close_index();
+ void new_file(bool need_lock= 1);
bool write(THD *thd, enum enum_server_command command,
const char *format,...);
bool write(THD *thd, const char *query, uint query_length,
@@ -136,23 +135,27 @@ public:
bool is_active(const char* log_file_name);
int purge_logs(THD* thd, const char* to_log);
int purge_first_log(struct st_relay_log_info* rli);
- int reset_logs(THD* thd);
- void close(bool exiting = 0); // if we are exiting, we also want to close the
- // index file
+ bool reset_logs(THD* thd);
+ // if we are exiting, we also want to close the index file
+ void close(bool exiting = 0);
// iterating through the log index file
- int find_first_log(LOG_INFO* linfo, const char* log_name,
- bool need_mutex=1);
- int find_next_log(LOG_INFO* linfo, bool need_mutex=1);
+ int find_log_pos(LOG_INFO* linfo, const char* log_name,
+ bool need_mutex);
+ int find_next_log(LOG_INFO* linfo, bool need_mutex);
int get_current_log(LOG_INFO* linfo);
uint next_file_id();
inline bool is_open() { return log_type != LOG_CLOSED; }
- char* get_index_fname() { return index_file_name;}
- char* get_log_fname() { return log_file_name; }
- void lock_index() { pthread_mutex_lock(&LOCK_index);}
- void unlock_index() { pthread_mutex_unlock(&LOCK_index);}
- File get_index_file() { return index_file;}
+ inline char* get_index_fname() { return index_file_name;}
+ inline char* get_log_fname() { return log_file_name; }
+ inline pthread_mutex_t* get_log_lock() { return &LOCK_log; }
+ inline IO_CACHE* get_log_file() { return &log_file; }
+
+ inline void lock_index() { pthread_mutex_lock(&LOCK_index);}
+ inline void unlock_index() { pthread_mutex_unlock(&LOCK_index);}
+ inline IO_CACHE *get_index_file() { return &index_file;}
+ inline uint32 get_open_count() { return open_count; }
};
/* character conversion tables */
@@ -182,9 +185,9 @@ typedef struct st_copy_info {
ha_rows records;
ha_rows deleted;
ha_rows copied;
- ha_rows error;
+ ha_rows error_count;
enum enum_duplicates handle_duplicates;
- int escape_char, errorno;
+ int escape_char, last_errno;
} COPY_INFO;
@@ -321,28 +324,68 @@ class delayed_insert;
#define THD_CHECK_SENTRY(thd) DBUG_ASSERT(thd->dbug_sentry == THD_SENTRY_MAGIC)
+struct system_variables
+{
+ ulonglong myisam_max_extra_sort_file_size;
+ ulonglong myisam_max_sort_file_size;
+ ulong bulk_insert_buff_size;
+ ulong join_buff_size;
+ ulong long_query_time;
+ ulong max_allowed_packet;
+ ulong max_heap_table_size;
+ ulong max_sort_length;
+ ulong max_join_size;
+ ulong max_tmp_tables;
+ ulong max_error_count;
+ ulong max_warning_count;
+ ulong myisam_sort_buff_size;
+ ulong net_buffer_length;
+ ulong net_interactive_timeout;
+ ulong net_read_timeout;
+ ulong net_wait_timeout;
+ ulong net_write_timeout;
+ ulong net_retry_count;
+ ulong query_cache_type;
+ ulong read_buff_size;
+ ulong read_rnd_buff_size;
+ ulong select_limit;
+ ulong sortbuff_size;
+ ulong tmp_table_size;
+ ulong tx_isolation;
+ ulong table_type;
+
+ my_bool log_warnings;
+ my_bool low_priority_updates;
+
+ CONVERT *convert_set;
+};
+
+
/*
For each client connection we create a separate thread with THD serving as
- a thread/connection descriptor.
+ a thread/connection descriptor
*/
class THD :public ilink {
public:
NET net; // client connection descriptor
LEX lex; // parse tree descriptor
- MEM_ROOT mem_root; // 1 command-life memory
+ MEM_ROOT mem_root; // 1 command-life memory pool
MEM_ROOT con_root; // connection-life memory
- HASH user_vars; // hash for user variables
- String packet; // buffer used for network I/O
+ HASH user_vars; // hash for user variables
+ String packet; // dynamic buffer for network I/O
struct sockaddr_in remote; // client socket address
struct rand_struct rand; // used for authentication
-
+ struct system_variables variables; // Changeable local variables
+ pthread_mutex_t LOCK_delete; // Locked before thd is deleted
+
+ char *query; // Points to the current query,
/*
- Query points to the current query,
- thread_stack is a pointer to the stack frame of handle_one_connection(),
- which is called first in the thread for handling a client
+ A pointer to the stack frame of handle_one_connection(),
+ which is called first in the thread for handling a client
*/
- char *query,*thread_stack;
+ char *thread_stack;
+
/*
host - host of the client
user - user of the client, set to NULL until the user has been read from
@@ -353,35 +396,25 @@ public:
*/
char *host,*user,*priv_user,*db,*ip;
- /*
- Proc_info points to a string that will show in the Info column of
- SHOW PROCESSLIST output
- host_or_ip points to host if host is available, otherwise points to ip
- */
- const char *proc_info, *host_or_ip;
-
- /*
- client_capabilities has flags describing what the client can do
- sql_mode determines if certain non-standard SQL behaviour should be
- enabled
- max_packet_length - supposed to be maximum packet length the client
- can handle, but it currently appears to be assigned but never used
- except for one debugging statement
- */
- uint client_capabilities,sql_mode,max_packet_length;
+ /* Points to info-string that will show in SHOW PROCESSLIST */
+ const char *proc_info;
+ /* points to host if host is available, otherwise points to ip */
+ const char *host_or_ip;
+
+ uint client_capabilities; /* What the client supports */
+ /* Determines if which non-standard SQL behaviour should be enabled */
+ uint sql_mode;
+ uint max_client_packet_length;
+ ulong master_access; /* Global privileges from mysql.user */
+ ulong db_access; /* Privileges for current db */
- /*
- master_access - privillege descriptor mask for system threads
- db_access - privillege descriptor mask for regular threads
- */
- uint master_access,db_access;
/*
open_tables - list of regular tables in use by this thread
temporary_tables - list of temp tables in use by this thread
handler_tables - list of tables that were opened with HANDLER OPEN
and are still in use by this thread
- */
+ */
TABLE *open_tables,*temporary_tables, *handler_tables;
// TODO: document the variables below
MYSQL_LOCK *lock; /* Current locks */
@@ -392,7 +425,7 @@ public:
#endif
struct st_my_thread_var *mysys_var;
enum enum_server_command command;
- uint32 server_id;
+ uint32 server_id;
uint32 file_id; // for LOAD DATA INFILE
const char *where;
time_t start_time,time_after_lock,user_time;
@@ -419,30 +452,30 @@ public:
}
} transaction;
Item *free_list, *handler_items;
- CONVERT *convert_set;
Field *dupp_field;
#ifndef __WIN__
sigset_t signals,block_signals;
#endif
#ifdef SIGNAL_WITH_VIO_CLOSE
Vio* active_vio;
- pthread_mutex_t active_vio_lock;
#endif
ulonglong next_insert_id,last_insert_id,current_insert_id,
limit_found_rows;
- ha_rows default_select_limit,cuted_fields,
- max_join_size, sent_row_count, examined_row_count;
+ ha_rows select_limit, offset_limit, cuted_fields,
+ sent_row_count, examined_row_count;
table_map used_tables;
USER_CONN *user_connect;
- ulong query_id,version, inactive_timeout,options,thread_id,
- max_error_count, max_warning_count;
+ CHARSET_INFO *db_charset;
+ ulong query_id, version, options, thread_id, col_access;
+ ulong param_count,current_param_number;
long dbug_thread_id;
pthread_t real_id;
- uint current_tablenr,tmp_table,cond_count,col_access;
+ uint current_tablenr,tmp_table,cond_count;
uint server_status,open_options;
uint32 query_length;
uint32 db_length;
- enum_tx_isolation tx_isolation, session_tx_isolation;
+ /* variables.transaction_isolation is reset to this after each commit */
+ enum_tx_isolation session_tx_isolation;
char scramble[9];
uint8 query_cache_type; // type of query cache processing
bool slave_thread;
@@ -454,7 +487,6 @@ public:
bool safe_to_cache_query;
bool volatile killed;
bool prepare_command;
- ulong param_count,current_param_number;
Error<mysql_st_error> err_list;
Error<mysql_st_error> warn_list;
Item_param *current_param;
@@ -472,7 +504,12 @@ public:
ulong slave_proxy_id;
NET* slave_net; // network connection from slave -> m.
my_off_t log_pos;
- CHARSET_INFO *db_charset;
+ /* Used by the sys_var class to store temporary values */
+ union
+ {
+ my_bool my_bool_value;
+ long long_value;
+ } sys_var_tmp;
THD();
~THD();
@@ -481,25 +518,24 @@ public:
#ifdef SIGNAL_WITH_VIO_CLOSE
inline void set_active_vio(Vio* vio)
{
- pthread_mutex_lock(&active_vio_lock);
+ pthread_mutex_lock(&LOCK_delete);
active_vio = vio;
- pthread_mutex_unlock(&active_vio_lock);
+ pthread_mutex_unlock(&LOCK_delete);
}
inline void clear_active_vio()
{
- pthread_mutex_lock(&active_vio_lock);
+ pthread_mutex_lock(&LOCK_delete);
active_vio = 0;
- pthread_mutex_unlock(&active_vio_lock);
+ pthread_mutex_unlock(&LOCK_delete);
}
inline void close_active_vio()
{
- pthread_mutex_lock(&active_vio_lock);
- if(active_vio)
- {
- vio_close(active_vio);
- active_vio = 0;
- }
- pthread_mutex_unlock(&active_vio_lock);
+ safe_mutex_assert_owner(&LOCK_delete);
+ if (active_vio)
+ {
+ vio_close(active_vio);
+ active_vio = 0;
+ }
}
#endif
void awake(bool prepare_to_die);
diff --git a/sql/sql_db.cc b/sql/sql_db.cc
index 7e82e1433b9..dee26aae4be 100644
--- a/sql/sql_db.cc
+++ b/sql/sql_db.cc
@@ -255,7 +255,7 @@ int mysql_alter_db(THD *thd, char *db, HA_CREATE_INFO *create_info, bool silent)
mysql_update_log.write(thd,thd->query, thd->query_length);
if (mysql_bin_log.is_open())
{
- Query_log_event qinfo(thd, thd->query);
+ Query_log_event qinfo(thd, thd->query, thd->query_length);
mysql_bin_log.write(&qinfo);
}
}
@@ -327,7 +327,9 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
send_ok(&thd->net,0);
goto exit;
}
+ pthread_mutex_lock(&LOCK_open);
remove_db_from_cache(db);
+ pthread_mutex_unlock(&LOCK_open);
error = -1;
if ((deleted=mysql_rm_known_files(thd, dirp, db, path,0)) >= 0 && thd)
@@ -345,7 +347,7 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
mysql_update_log.write(thd, thd->query, thd->query_length);
if (mysql_bin_log.is_open())
{
- Query_log_event qinfo(thd, thd->query);
+ Query_log_event qinfo(thd, thd->query, thd->query_length);
mysql_bin_log.write(&qinfo);
}
if (thd->query == path)
@@ -450,7 +452,8 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db,
}
my_dirend(dirp);
- if (thd->killed || (tot_list && mysql_rm_table_part2(thd, tot_list, 1, 1)))
+ if (thd->killed ||
+ (tot_list && mysql_rm_table_part2_with_lock(thd, tot_list, 1, 1)))
DBUG_RETURN(-1);
/*
@@ -522,6 +525,8 @@ bool mysql_change_db(THD *thd,const char *name)
x_free(dbname);
DBUG_RETURN(1);
}
+ if (lower_case_table_names)
+ casedn_str(dbname);
DBUG_PRINT("info",("Use database: %s", dbname));
if (test_all_bits(thd->master_access,DB_ACLS))
db_access=DB_ACLS;
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index 3e9df1cfd29..fc98cfb90c5 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -78,7 +78,7 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order,
select=make_select(table,0,0,conds,&error);
if (error)
DBUG_RETURN(-1);
- if ((select && select->check_quick(test(thd->options & SQL_SAFE_UPDATES),
+ if ((select && select->check_quick(test(thd->options & OPTION_SAFE_UPDATES),
limit)) ||
!limit)
{
@@ -167,7 +167,8 @@ cleanup:
mysql_update_log.write(thd,thd->query, thd->query_length);
if (mysql_bin_log.is_open())
{
- Query_log_event qinfo(thd, thd->query, using_transactions);
+ Query_log_event qinfo(thd, thd->query, thd->query_length,
+ using_transactions);
if (mysql_bin_log.write(&qinfo) && using_transactions)
error=1;
}
@@ -198,10 +199,10 @@ cleanup:
/***************************************************************************
-** delete multiple tables from join
+ Delete multiple tables from join
***************************************************************************/
-#define MEM_STRIP_BUF_SIZE sortbuff_size
+#define MEM_STRIP_BUF_SIZE current_thd->variables.sortbuff_size
int refposcmp2(void* arg, const void *a,const void *b)
{
@@ -215,21 +216,8 @@ multi_delete::multi_delete(THD *thd_arg, TABLE_LIST *dt,
num_of_tables(num_of_tables_arg), error(0), lock_option(lock_option_arg),
do_delete(false)
{
- uint counter=0;
not_trans_safe=false;
tempfiles = (Unique **) sql_calloc(sizeof(Unique *) * (num_of_tables-1));
-
- /* Don't use key read with MULTI-TABLE-DELETE */
- dt->table->used_keys=0;
- for (dt=dt->next ; dt ; dt=dt->next,counter++)
- {
- TABLE *table=dt->table;
- table->used_keys=0;
- tempfiles[counter] = new Unique (refposcmp2,
- (void *) &table->file->ref_length,
- table->file->ref_length,
- MEM_STRIP_BUF_SIZE);
- }
}
@@ -261,6 +249,7 @@ multi_delete::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
void
multi_delete::initialize_tables(JOIN *join)
{
+ int counter=0;
TABLE_LIST *walk;
table_map tables_to_delete_from=0;
for (walk= delete_tables ; walk ; walk=walk->next)
@@ -274,14 +263,27 @@ multi_delete::initialize_tables(JOIN *join)
if (tab->table->map & tables_to_delete_from)
{
/* We are going to delete from this table */
- walk->table=tab->table;
+ TABLE *tbl=walk->table=tab->table;
+ /* Don't use KEYREAD optimization on this table */
+ tbl->no_keyread=1;
walk=walk->next;
- if (tab == join->join_tab)
- tab->table->no_keyread=1;
- if (!not_trans_safe && !tab->table->file->has_transactions())
+ if (!not_trans_safe && !tbl->file->has_transactions())
not_trans_safe=true;
}
}
+ walk= delete_tables;
+ walk->table->used_keys=0;
+ for (walk=walk->next ; walk ; walk=walk->next, counter++)
+ {
+ tables_to_delete_from|= walk->table->map;
+ TABLE *table=walk->table;
+ /* Don't use key read with MULTI-TABLE-DELETE */
+ table->used_keys=0;
+ tempfiles[counter] = new Unique (refposcmp2,
+ (void *) &table->file->ref_length,
+ table->file->ref_length,
+ MEM_STRIP_BUF_SIZE);
+ }
init_ftfuncs(thd,1);
}
@@ -358,7 +360,7 @@ void multi_delete::send_error(uint errcode,const char *err)
if (!deleted)
DBUG_VOID_RETURN;
- /* Somthing alredy deleted consequently we have to invalidate cache */
+ /* Something already deleted so we have to invalidate cache */
query_cache_invalidate3(thd, delete_tables, 1);
/* Below can happen when thread is killed early ... */
@@ -437,6 +439,8 @@ int multi_delete::do_deletes(bool from_send_error)
/*
+ Send ok to the client
+
return: 0 sucess
1 error
*/
@@ -467,7 +471,7 @@ bool multi_delete::send_eof()
mysql_update_log.write(thd,thd->query,thd->query_length);
if (mysql_bin_log.is_open())
{
- Query_log_event qinfo(thd, thd->query);
+ 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
@@ -485,7 +489,7 @@ bool multi_delete::send_eof()
/***************************************************************************
-* TRUNCATE TABLE
+ TRUNCATE TABLE
****************************************************************************/
/*
@@ -530,9 +534,8 @@ int mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok)
table_list->real_name, 1))))
(void) rm_temporary_table(table_type, path);
/*
- If we return here we will not have binloged the truncation and
- we will not send_ok() to the client. Yes, we do need better coverage
- testing, this bug has been here for a few months :-).
+ If we return here we will not have logged the truncation to the bin log
+ and we will not send_ok() to the client.
*/
goto end;
}
@@ -546,7 +549,8 @@ int mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok)
db_type table_type;
if ((table_type=get_table_type(path)) == DB_TYPE_UNKNOWN)
{
- my_error(ER_NO_SUCH_TABLE, MYF(0), table_list->real_name);
+ my_error(ER_NO_SUCH_TABLE, MYF(0), table_list->db,
+ table_list->real_name);
DBUG_RETURN(-1);
}
if (!ha_supports_generate(table_type))
@@ -573,14 +577,20 @@ end:
mysql_update_log.write(thd,thd->query,thd->query_length);
if (mysql_bin_log.is_open())
{
- Query_log_event qinfo(thd, thd->query);
+ Query_log_event qinfo(thd, thd->query, thd->query_length);
mysql_bin_log.write(&qinfo);
}
send_ok(&thd->net); // This should return record count
}
+ VOID(pthread_mutex_lock(&LOCK_open));
unlock_table_name(thd, table_list);
+ VOID(pthread_mutex_unlock(&LOCK_open));
}
else if (error)
+ {
+ VOID(pthread_mutex_lock(&LOCK_open));
unlock_table_name(thd, table_list);
+ VOID(pthread_mutex_unlock(&LOCK_open));
+ }
DBUG_RETURN(error ? -1 : 0);
}
diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc
index 3668a817165..7fa24faf6c4 100644
--- a/sql/sql_handler.cc
+++ b/sql/sql_handler.cc
@@ -17,9 +17,9 @@
/* HANDLER ... commands - direct access to ISAM */
-#include <assert.h>
#include "mysql_priv.h"
#include "sql_select.h"
+#include <assert.h>
/* TODO:
HANDLER blabla OPEN [ AS foobar ] [ (column-list) ]
@@ -117,6 +117,7 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
keyname,tables->name);
return -1;
}
+ table->file->index_init(keyno);
}
List<Item> list;
@@ -127,7 +128,7 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
insert_fields(thd,tables,tables->db,tables->name,&it);
- table->file->index_init(keyno);
+ table->file->init_table_handle_for_HANDLER(); // Only InnoDB requires it
select_limit+=offset_limit;
send_fields(thd,list,1);
@@ -212,7 +213,7 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
if (cond)
{
err=err;
- if(!cond->val_int())
+ if (!cond->val_int())
continue;
}
if (num_rows>=offset_limit)
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index c3aeca1fff8..b02fd99e358 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -60,7 +60,7 @@ check_insert_fields(THD *thd,TABLE *table,List<Item> &fields,
if (grant_option &&
check_grant_all_columns(thd,INSERT_ACL,table))
return -1;
- table->time_stamp=0; // This should be saved
+ table->time_stamp=0; // This is saved by caller
}
else
{ // Part field list
@@ -73,6 +73,7 @@ check_insert_fields(THD *thd,TABLE *table,List<Item> &fields,
}
TABLE_LIST table_list;
bzero((char*) &table_list,sizeof(table_list));
+ table_list.db= table->table_cache_key;
table_list.name=table->table_name;
table_list.table=table;
table_list.grant=table->grant;
@@ -102,7 +103,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
{
int error;
bool log_on= ((thd->options & OPTION_UPDATE_LOG) ||
- !(thd->master_access & PROCESS_ACL));
+ !(thd->master_access & SUPER_ACL));
bool using_transactions, bulk_insert=0;
uint value_count;
uint save_time_stamp;
@@ -177,7 +178,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
}
its.rewind ();
/*
- ** Fill in the given fields and dump it to the table file
+ Fill in the given fields and dump it to the table file
*/
info.records=info.deleted=info.copied=0;
@@ -197,11 +198,13 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
lock_type != TL_WRITE_DELAYED &&
!(specialflag & SPECIAL_SAFE_MODE))))
{
- table->file->extra(HA_EXTRA_WRITE_CACHE);
- table->file->extra(HA_EXTRA_BULK_INSERT_BEGIN);
+ 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);
}
- while ((values = its++))
+ while ((values= its++))
{
if (fields.elements || !value_count)
{
@@ -263,7 +266,9 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
end_delayed_insert(thd);
}
if (info.copied || info.deleted)
+ {
query_cache_invalidate3(thd, table_list, 1);
+ }
}
else
{
@@ -296,7 +301,8 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
mysql_update_log.write(thd, thd->query, thd->query_length);
if (mysql_bin_log.is_open())
{
- Query_log_event qinfo(thd, thd->query, using_transactions);
+ Query_log_event qinfo(thd, thd->query, thd->query_length,
+ using_transactions);
if (mysql_bin_log.write(&qinfo) && using_transactions)
error=1;
}
@@ -332,12 +338,14 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
{
char buff[160];
if (duplic == DUP_IGNORE)
- sprintf(buff,ER(ER_INSERT_INFO),info.records,info.records-info.copied,
+ sprintf(buff,ER(ER_INSERT_INFO),info.records,
+ (lock_type == TL_WRITE_DELAYED) ? 0 :
+ info.records-info.copied,
thd->cuted_fields);
else
sprintf(buff,ER(ER_INSERT_INFO),info.records,info.deleted,
thd->cuted_fields);
- ::send_ok(&thd->net,info.copied+info.deleted,0L,buff);
+ ::send_ok(&thd->net,info.copied+info.deleted,(ulonglong)id,buff);
}
DBUG_RETURN(0);
@@ -360,7 +368,7 @@ static int last_uniq_key(TABLE *table,uint keynr)
/*
-** Write a record to table with optional deleting of conflicting records
+ Write a record to table with optional deleting of conflicting records
*/
@@ -447,16 +455,16 @@ int write_record(TABLE *table,COPY_INFO *info)
err:
if (key)
my_afree(key);
- info->errorno= error;
+ info->last_errno= error;
table->file->print_error(error,MYF(0));
return 1;
}
/******************************************************************************
- Check that all fields with arn't null_fields are used
- if DONT_USE_DEFAULT_FIELDS isn't defined use default value for not
- set fields.
+ Check that all fields with arn't null_fields are used
+ If DONT_USE_DEFAULT_FIELDS isn't defined use default value for not set
+ fields.
******************************************************************************/
static int check_null_fields(THD *thd __attribute__((unused)),
@@ -479,10 +487,8 @@ static int check_null_fields(THD *thd __attribute__((unused)),
}
/*****************************************************************************
-** Handling of delayed inserts
-**
-** A thread is created for each table that one uses with the DELAYED
-** attribute.
+ Handling of delayed inserts
+ A thread is created for each table that one uses with the DELAYED attribute.
*****************************************************************************/
class delayed_row :public ilink {
@@ -556,8 +562,8 @@ public:
thd.user=thd.host=0;
thread_count--;
delayed_insert_threads--;
- VOID(pthread_cond_broadcast(&COND_thread_count)); /* Tell main we are ready */
VOID(pthread_mutex_unlock(&LOCK_thread_count));
+ VOID(pthread_cond_broadcast(&COND_thread_count)); /* Tell main we are ready */
}
/* The following is for checking when we can delete ourselves */
@@ -929,9 +935,7 @@ static pthread_handler_decl(handle_delayed_insert,arg)
#endif
DBUG_ENTER("handle_delayed_insert");
- if (init_thr_lock() ||
- my_pthread_setspecific_ptr(THR_THD, thd) ||
- my_pthread_setspecific_ptr(THR_NET, &thd->net))
+ if (init_thr_lock() || thd->store_globals())
{
thd->fatal_error=1;
strmov(thd->net.last_error,ER(thd->net.last_errno=ER_OUT_OF_RESOURCES));
@@ -1179,7 +1183,7 @@ bool delayed_insert::handle_inserts(void)
thd.net.last_errno = 0; // reset error for binlog
if (write_record(table,&info))
{
- info.error++; // Ignore errors
+ info.error_count++; // Ignore errors
thread_safe_increment(delayed_insert_errors,&LOCK_delayed_status);
row->log_query = 0;
}
@@ -1193,8 +1197,7 @@ bool delayed_insert::handle_inserts(void)
mysql_update_log.write(&thd,row->query, row->query_length);
if (using_bin_log)
{
- thd.query_length = row->query_length;
- Query_log_event qinfo(&thd, row->query);
+ Query_log_event qinfo(&thd, row->query, row->query_length);
mysql_bin_log.write(&qinfo);
}
}
@@ -1267,7 +1270,7 @@ bool delayed_insert::handle_inserts(void)
/***************************************************************************
-** store records in INSERT ... SELECT *
+ Store records in INSERT ... SELECT *
***************************************************************************/
int
@@ -1375,7 +1378,7 @@ bool select_insert::send_eof()
mysql_update_log.write(thd,thd->query,thd->query_length);
if (mysql_bin_log.is_open())
{
- Query_log_event qinfo(thd, thd->query,
+ Query_log_event qinfo(thd, thd->query, thd->query_length,
table->file->has_transactions());
mysql_bin_log.write(&qinfo);
}
@@ -1385,7 +1388,7 @@ bool select_insert::send_eof()
/***************************************************************************
-** CREATE TABLE (SELECT) ...
+ CREATE TABLE (SELECT) ...
***************************************************************************/
int
@@ -1453,6 +1456,11 @@ bool select_create::send_eof()
table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
VOID(pthread_mutex_lock(&LOCK_open));
mysql_unlock_tables(thd, lock);
+ /*
+ TODO:
+ Check if we can remove the following two rows.
+ We should be able to just keep the table in the table cache.
+ */
if (!table->tmp_table)
hash_delete(&open_cache,(byte*) table);
lock=0;
@@ -1484,7 +1492,7 @@ void select_create::abort()
/*****************************************************************************
-** Instansiate templates
+ Instansiate templates
*****************************************************************************/
#ifdef __GNUC__
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 9ae5cdeeb15..dc9019de2c8 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -147,10 +147,11 @@ LEX *lex_start(THD *thd, uchar *buf,uint length)
lex->select->in_sum_expr=0;
lex->select->expr_list.empty();
lex->select->ftfunc_list.empty();
- lex->convert_set=(lex->thd=thd)->convert_set;
+ lex->convert_set=(lex->thd=thd)->variables.convert_set;
lex->yacc_yyss=lex->yacc_yyvs=0;
lex->ignore_space=test(thd->sql_mode & MODE_IGNORE_SPACE);
lex->slave_thd_opt=0;
+ lex->sql_command=SQLCOM_END;
bzero(&lex->mi,sizeof(lex->mi));
return lex;
}
@@ -507,7 +508,7 @@ int yylex(void *arg)
length= (uint) (lex->ptr - lex->tok_start)-1;
if (lex->ignore_space)
{
- for ( ; state_map[c] == STATE_SKIP ; c= yyGet());
+ for (; state_map[c] == STATE_SKIP ; c= yyGet());
}
if (c == '.' && (state_map[yyPeek()] == STATE_IDENT ||
state_map[yyPeek()] == STATE_NUMBER_IDENT))
@@ -524,7 +525,7 @@ int yylex(void *arg)
}
yylval->lex_str=get_token(lex,length);
if (lex->convert_set)
- lex->convert_set->convert((char*) yylval->lex_str.str,lex->yytoklen);
+ lex->convert_set->convert((char*) yylval->lex_str.str,lex->yytoklen);
/*
Note: "SELECT _bla AS 'alias'"
@@ -866,14 +867,12 @@ int yylex(void *arg)
}
break;
case STATE_USER_END: // end '@' of user@hostname
- switch (state_map[yyPeek()])
- {
+ switch (state_map[yyPeek()]) {
case STATE_STRING:
case STATE_USER_VARIABLE_DELIMITER:
break;
case STATE_USER_END:
- lex->next_state=STATE_USER_END;
- yySkip();
+ lex->next_state=STATE_SYSTEM_VAR;
break;
default:
lex->next_state=STATE_HOSTNAME;
@@ -888,6 +887,33 @@ int yylex(void *arg)
c= yyGet()) ;
yylval->lex_str=get_token(lex,yyLength());
return(LEX_HOSTNAME);
+ case STATE_SYSTEM_VAR:
+ yylval->lex_str.str=(char*) lex->ptr;
+ yylval->lex_str.length=1;
+ lex->next_state=STATE_IDENT_OR_KEYWORD;
+ yySkip(); // Skip '@'
+ return((int) '@');
+ case STATE_IDENT_OR_KEYWORD:
+ /*
+ We come here when we have found two '@' in a row.
+ We should now be able to handle:
+ [(global | local | session) .]variable_name
+ */
+
+ while (state_map[c=yyGet()] == STATE_IDENT ||
+ state_map[c] == STATE_NUMBER_IDENT) ;
+ if (c == '.')
+ lex->next_state=STATE_IDENT_SEP;
+ length= (uint) (lex->ptr - lex->tok_start)-1;
+ if ((tokval= find_keyword(lex,length,0)))
+ {
+ yyUnget(); // Put back 'c'
+ return(tokval); // Was keyword
+ }
+ yylval->lex_str=get_token(lex,length);
+ if (lex->convert_set)
+ lex->convert_set->convert((char*) yylval->lex_str.str,lex->yytoklen);
+ return(IDENT);
}
}
}
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index af80b175cd3..6aef99886e9 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -22,8 +22,12 @@ class Table_ident;
class sql_exchange;
class LEX_COLUMN;
-// The following hack is needed because mysql_yacc.cc does not define
-// YYSTYPE before including this file
+/*
+ The following hack is needed because mysql_yacc.cc does not define
+ YYSTYPE before including this file
+*/
+
+#include "set_var.h"
#ifdef MYSQL_YACC
#define LEX_YYSTYPE void *
@@ -40,6 +44,7 @@ enum enum_sql_command {
SQLCOM_SHOW_DATABASES, SQLCOM_SHOW_TABLES, SQLCOM_SHOW_FIELDS,
SQLCOM_SHOW_KEYS, SQLCOM_SHOW_VARIABLES, SQLCOM_SHOW_LOGS, SQLCOM_SHOW_STATUS,
+ SQLCOM_SHOW_INNODB_STATUS,
SQLCOM_SHOW_PROCESSLIST, SQLCOM_SHOW_MASTER_STAT, SQLCOM_SHOW_SLAVE_STAT,
SQLCOM_SHOW_GRANTS, SQLCOM_SHOW_CREATE, SQLCOM_SHOW_CHARSETS,
SQLCOM_SHOW_CREATE_DB,
@@ -59,56 +64,47 @@ enum enum_sql_command {
SQLCOM_HA_OPEN, SQLCOM_HA_CLOSE, SQLCOM_HA_READ,
SQLCOM_SHOW_SLAVE_HOSTS, SQLCOM_DELETE_MULTI, SQLCOM_MULTI_UPDATE,
SQLCOM_SHOW_BINLOG_EVENTS, SQLCOM_SHOW_NEW_MASTER, SQLCOM_DO,
- SQLCOM_END, SQLCOM_SHOW_WARNS, SQLCOM_SHOW_WARNS_COUNT,
- SQLCOM_EMPTY_QUERY, SQLCOM_SHOW_ERRORS,
- SQLCOM_SHOW_ERRORS_COUNT, SQLCOM_SHOW_COLUMN_TYPES,
- SQLCOM_SHOW_TABLE_TYPES, SQLCOM_SHOW_PRIVILEGES
+ SQLCOM_SHOW_WARNS, SQLCOM_EMPTY_QUERY, SQLCOM_SHOW_ERRORS,
+ SQLCOM_SHOW_COLUMN_TYPES, SQLCOM_SHOW_TABLE_TYPES, SQLCOM_SHOW_PRIVILEGES,
+ SQLCOM_END
};
-enum lex_states { STATE_START, STATE_CHAR, STATE_IDENT,
- STATE_IDENT_SEP,
- STATE_IDENT_START,
- STATE_FOUND_IDENT,
- STATE_SIGNED_NUMBER,
- STATE_REAL,
- STATE_HEX_NUMBER,
- STATE_CMP_OP,
- STATE_LONG_CMP_OP,
- STATE_STRING,
- STATE_COMMENT,
- STATE_END,
- STATE_OPERATOR_OR_IDENT,
- STATE_NUMBER_IDENT,
- STATE_INT_OR_REAL,
- STATE_REAL_OR_POINT,
- STATE_BOOL,
- STATE_EOL,
- STATE_ESCAPE,
- STATE_LONG_COMMENT,
- STATE_END_LONG_COMMENT,
- STATE_COLON,
- STATE_SET_VAR,
- STATE_USER_END,
- STATE_HOSTNAME,
- STATE_SKIP,
- STATE_USER_VARIABLE_DELIMITER
+enum lex_states
+{
+ STATE_START, STATE_CHAR, STATE_IDENT, STATE_IDENT_SEP, STATE_IDENT_START,
+ STATE_FOUND_IDENT, STATE_SIGNED_NUMBER, STATE_REAL, STATE_HEX_NUMBER,
+ STATE_CMP_OP, STATE_LONG_CMP_OP, STATE_STRING, STATE_COMMENT, STATE_END,
+ STATE_OPERATOR_OR_IDENT, STATE_NUMBER_IDENT, STATE_INT_OR_REAL,
+ STATE_REAL_OR_POINT, STATE_BOOL, STATE_EOL, STATE_ESCAPE, STATE_LONG_COMMENT,
+ STATE_END_LONG_COMMENT, STATE_COLON, STATE_SET_VAR, STATE_USER_END,
+ STATE_HOSTNAME, STATE_SKIP, STATE_USER_VARIABLE_DELIMITER, STATE_SYSTEM_VAR,
+ STATE_IDENT_OR_KEYWORD
};
+
typedef List<Item> List_item;
typedef struct st_lex_master_info
{
- char* host, *user, *password,*log_file_name;
+ char *host, *user, *password, *log_file_name;
uint port, connect_retry;
ulonglong pos;
ulong server_id;
- char* relay_log_name;
+ char *relay_log_name;
ulong relay_log_pos;
} LEX_MASTER_INFO;
-enum sub_select_type {UNSPECIFIED_TYPE,UNION_TYPE, INTERSECT_TYPE,
- EXCEPT_TYPE, GLOBAL_OPTIONS_TYPE, DERIVED_TABLE_TYPE};
+enum sub_select_type
+{
+ UNSPECIFIED_TYPE,UNION_TYPE, INTERSECT_TYPE,
+ EXCEPT_TYPE, GLOBAL_OPTIONS_TYPE, DERIVED_TABLE_TYPE, OLAP_TYPE
+};
+
+enum olap_type
+{
+ UNSPECIFIED_OLAP_TYPE, CUBE_TYPE, ROLLUP_TYPE
+};
/*
The state of the lex parsing for selects
@@ -246,6 +242,7 @@ class st_select_lex: public st_select_lex_node {
public:
char *db, *db1, *table1, *db2, *table2; /* For outer join using .. */
Item *where, *having; /* WHERE & HAVING clauses */
+ enum olap_type olap;
List<List_item> expr_list;
List<List_item> when_list; /* WHEN clause */
SQL_LIST table_list, group_list; /* FROM & GROUP BY clauses */
@@ -255,11 +252,11 @@ public:
List<Item_func_match> ftfunc_list;
JOIN *join; /* after JOIN::prepare it is pointer to corresponding JOIN */
uint in_sum_expr;
- bool create_refs,
- braces, /* SELECT ... UNION (SELECT ... ) <- this braces */
- depended, /* depended from outer select subselect */
- /* TRUE when having fix field called in processing of this SELECT */
- having_fix_field;
+ bool create_refs;
+ bool braces; /* SELECT ... UNION (SELECT ... ) <- this braces */
+ bool depended; /* depended from outer select subselect */
+ /* TRUE when having fix field called in processing of this SELECT */
+ bool having_fix_field;
void init_query();
void init_select();
@@ -286,20 +283,11 @@ public:
};
typedef class st_select_lex SELECT_LEX;
-class Set_option :public Sql_alloc {
-public:
- const char *name;
- Item *item;
- uint name_length;
- bool type; /* 1 if global */
- Set_option(bool par_type, const char *par_name, uint length,
- Item *par_item)
- :name(par_name), item(par_item), name_length(length), type(par_type) {}
-};
/* The state of the lex parsing. This is saved in the THD struct */
-typedef struct st_lex {
+typedef struct st_lex
+{
uint yylineno,yytoklen; /* Simulate lex */
LEX_YYSTYPE yylval;
SELECT_LEX_UNIT unit; /* most upper unit */
@@ -320,19 +308,20 @@ typedef struct st_lex {
List<Alter_drop> drop_list;
List<Alter_column> alter_list;
List<String> interval_list;
- List<st_lex_user> users_list;
+ List<LEX_USER> users_list;
List<LEX_COLUMN> columns;
List<Key> key_list;
List<create_field> create_list;
List<Item> *insert_list,field_list,value_list;
List<List_item> many_values;
- List<Set_option> option_list;
+ List<set_var_base> var_list;
List<Item> param_list;
SQL_LIST proc_list, auxilliary_table_list;
TYPELIB *interval;
create_field *last_field;
Item *default_value, *comment;
CONVERT *convert_set;
+ CONVERT *thd_convert_set; // Set with SET CHAR SET
LEX_USER *grant_user;
gptr yacc_yyss,yacc_yyvs;
THD *thd;
@@ -350,10 +339,12 @@ typedef struct st_lex {
enum enum_ha_read_modes ha_read_mode;
enum ha_rkey_function ha_rkey_mode;
enum enum_enable_or_disable alter_keys_onoff;
+ enum enum_var_type option_type;
uint grant, grant_tot_col, which_columns, union_option;
uint fk_delete_opt, fk_update_opt, fk_match_option;
- bool drop_primary,drop_if_exists,local_file;
- bool in_comment,ignore_space,verbose,simple_alter, option_type, derived_tables;
+ bool drop_primary, drop_if_exists, local_file, olap;
+ bool in_comment, ignore_space, verbose, simple_alter;
+ bool derived_tables;
uint slave_thd_opt;
CHARSET_INFO *charset;
} LEX;
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index faeeaf2812e..ad25ef85e75 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -52,17 +52,21 @@ public:
char unescape(char chr);
int terminator(char *ptr,uint length);
bool find_start_of_fields();
- // we need to force cache close before destructor is invoked to log
- // the last read block
+ /*
+ We need to force cache close before destructor is invoked to log
+ the last read block
+ */
void end_io_cache()
{
::end_io_cache(&cache);
need_end_io_cache = 0;
}
- // either this method, or we need to make cache public
- // arg must be set from mysql_load() since constructor does not see
- // either the table or THD value
+ /*
+ Either this method, or we need to make cache public
+ Arg must be set from mysql_load() since constructor does not see
+ either the table or THD value
+ */
void set_io_cache_arg(void* arg) { cache.arg = arg; }
};
@@ -89,6 +93,10 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
bool using_transactions;
DBUG_ENTER("mysql_load");
+#ifdef EMBEDDED_LIBRARY
+ read_file_from_client = 0; //server is always in the same process
+#endif
+
if (escaped->length() > 1 || enclosed->length() > 1)
{
my_message(ER_WRONG_FIELD_TERMINATORS,ER(ER_WRONG_FIELD_TERMINATORS),
@@ -216,7 +224,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;
- read_info.set_io_cache_arg((void*)&lf_info);
+ read_info.set_io_cache_arg((void*) &lf_info);
}
restore_record(table,2);
@@ -238,8 +246,10 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
if (use_timestamp)
table->time_stamp=0;
table->next_number_field=table->found_next_number_field;
- VOID(table->file->extra(HA_EXTRA_WRITE_CACHE));
- VOID(table->file->extra(HA_EXTRA_BULK_INSERT_BEGIN));
+ VOID(table->file->extra_opt(HA_EXTRA_WRITE_CACHE,
+ thd->variables.read_buff_size));
+ VOID(table->file->extra_opt(HA_EXTRA_BULK_INSERT_BEGIN,
+ thd->variables.bulk_insert_buff_size));
if (handle_duplicates == DUP_IGNORE ||
handle_duplicates == DUP_REPLACE)
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
@@ -285,7 +295,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
info.records-info.copied,thd->cuted_fields);
send_ok(&thd->net,info.copied+info.deleted,0L,name);
// on the slave thd->query is never initialized
- if(!thd->slave_thread)
+ if (!thd->slave_thread)
mysql_update_log.write(thd,thd->query,thd->query_length);
if (!using_transactions)
@@ -420,7 +430,7 @@ read_sep_field(THD *thd,COPY_INFO &info,TABLE *table,
{
if (field->type() == FIELD_TYPE_TIMESTAMP)
((Field_timestamp*) field)->set_time();
- else
+ else if (field != table->next_number_field)
thd->cuted_fields++;
}
continue;
@@ -435,7 +445,7 @@ read_sep_field(THD *thd,COPY_INFO &info,TABLE *table,
{ // Last record
if (sql_field == (Item_field*) fields.head())
break;
- for ( ; sql_field ; sql_field=(Item_field*) it++)
+ for (; sql_field ; sql_field=(Item_field*) it++)
{
sql_field->field->set_null();
sql_field->field->reset();
@@ -475,8 +485,10 @@ READ_INFO::unescape(char chr)
}
- /* Read a line using buffering */
- /* If last line is empty (in line mode) then it isn't outputed */
+/*
+ Read a line using buffering
+ If last line is empty (in line mode) then it isn't outputed
+*/
READ_INFO::READ_INFO(File file_par, uint tot_length, String &field_term,
@@ -535,10 +547,11 @@ READ_INFO::READ_INFO(File file_par, uint tot_length, String &field_term,
}
else
{
- /* init_io_cache() will not initialize read_function member
- if the cache is READ_NET. The reason is explained in
- mysys/mf_iocache.c. So we work around the problem with a
- manual assignment
+ /*
+ init_io_cache() will not initialize read_function member
+ if the cache is READ_NET. The reason is explained in
+ mysys/mf_iocache.c. So we work around the problem with a
+ manual assignment
*/
if (get_it_from_net)
cache.read_function = _my_b_net_read;
diff --git a/sql/sql_olap.cc b/sql/sql_olap.cc
new file mode 100644
index 00000000000..930e052ab90
--- /dev/null
+++ b/sql/sql_olap.cc
@@ -0,0 +1,194 @@
+/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+
+/*
+ OLAP implementation by Sinisa Milivojevic <sinisa@mysql.com>
+ Inspired by code submitted by Srilakshmi <lakshmi@gdit.iiit.net>
+
+ The ROLLUP code in this file has to be complitely rewritten as it's
+ not good enough to satisfy the goals of MySQL.
+
+ In 4.1 we will replace this with a working, superior implementation
+ of ROLLUP.
+*/
+
+#ifdef DISABLED_UNTIL_REWRITTEN_IN_4_1
+
+#ifdef __GNUC__
+#pragma implementation // gcc: Class implementation
+#endif
+
+#include "mysql_priv.h"
+#include "sql_select.h"
+
+
+/****************************************************************************
+ Functions that recursively actually creates new SELECT's
+ Returns 0 if OK, 1 if error, -1 if error already printed to client
+****************************************************************************/
+
+
+static int make_new_olap_select(LEX *lex, SELECT_LEX *select_lex, List<Item> new_fields)
+{
+ THD *thd=current_thd;
+ Item *item, *new_item;
+ Item_null *constant= new Item_null("ALL");
+
+ SELECT_LEX *new_select = (SELECT_LEX *) thd->memdup((char*) select_lex, sizeof(*select_lex));
+ if (!new_select)
+ return 1;
+ lex->last_selects->next=new_select;
+ new_select->linkage=OLAP_TYPE;
+ new_select->olap=NON_EXISTING_ONE;
+ new_select->group_list.elements=0;
+ new_select->group_list.first=(byte *)0;
+ new_select->group_list.next=(byte **)&new_select->group_list.first;
+ List<Item> privlist;
+
+ List_iterator<Item> list_it(select_lex->item_list);
+ List_iterator<Item> new_it(new_fields);
+
+ while((item=list_it++))
+ {
+ bool not_found=true;
+ if (item->type()==Item::FIELD_ITEM)
+ {
+ Item_field *iif = (Item_field *)item;
+ new_it.rewind();
+ while ((new_item=new_it++))
+ {
+ if (new_item->type()==Item::FIELD_ITEM &&
+ !strcmp(((Item_field*)new_item)->table_name,iif->table_name) &&
+ !strcmp(((Item_field*)new_item)->field_name,iif->field_name))
+ {
+ not_found=false;
+ ((Item_field*)new_item)->db_name=iif->db_name;
+ Item_field *new_one=new Item_field(iif->db_name, iif->table_name, iif->field_name);
+ privlist.push_back(new_one);
+ if (add_to_list(new_select->group_list,new_one,1))
+ return 1;
+ break;
+ }
+ }
+ }
+ if (not_found)
+ {
+ if (item->type() == Item::FIELD_ITEM)
+ privlist.push_back(constant);
+ else
+ privlist.push_back((Item*)thd->memdup((char *)item,item->size_of()));
+ }
+ }
+ new_select->item_list=privlist;
+
+ lex->last_selects = new_select;
+ return 0;
+}
+
+/****************************************************************************
+ Functions that recursively creates combinations of queries for OLAP
+ Returns 0 if OK, 1 if error, -1 if error already printed to client
+****************************************************************************/
+
+static int olap_combos(List<Item> old_fields, List<Item> new_fields, Item *item, LEX *lex,
+ SELECT_LEX *select_lex, int position, int selection, int num_fields,
+ int num_new_fields)
+{
+ int sl_return = 0;
+ if(position == num_new_fields)
+ {
+ if(item)
+ new_fields.push_front(item);
+ sl_return = make_new_olap_select(lex, select_lex, new_fields);
+ }
+ else
+ {
+ if(item)
+ new_fields.push_front(item);
+ while ((num_fields - num_new_fields >= selection - position) && !sl_return)
+ {
+ item = old_fields.pop();
+ sl_return = olap_combos(old_fields, new_fields, item, lex, select_lex, position+1, ++selection, num_fields, num_new_fields);
+ }
+ }
+ return sl_return;
+}
+
+
+/****************************************************************************
+ Top level function for converting OLAP clauses to multiple selects
+ This is also a place where clauses treatment depends on OLAP type
+ Returns 0 if OK, 1 if error, -1 if error already printed to client
+****************************************************************************/
+
+int handle_olaps(LEX *lex, SELECT_LEX *select_lex)
+{
+ List<Item> item_list_copy, new_item_list;
+ item_list_copy.empty();
+ new_item_list.empty();
+ int count=select_lex->group_list.elements;
+ int sl_return=0;
+
+// a fix for UNION's
+ for (TABLE_LIST *cursor= (TABLE_LIST *)select_lex->table_list.first;
+ cursor;
+ cursor=cursor->next)
+ {
+ if (cursor->do_redirect)
+ {
+ cursor->table= ((TABLE_LIST*) cursor->table)->table;
+ cursor->do_redirect=false;
+ }
+ }
+
+ lex->last_selects=select_lex;
+
+ for (ORDER *order=(ORDER *)select_lex->group_list.first ; order ; order=order->next)
+ item_list_copy.push_back(*(order->item));
+
+ List<Item> all_fields(select_lex->item_list);
+
+
+ if (setup_tables((TABLE_LIST *)select_lex->table_list.first) ||
+ setup_fields(lex->thd,(TABLE_LIST *)select_lex->table_list.first,select_lex->item_list,1,&all_fields,1) ||
+ setup_fields(lex->thd,(TABLE_LIST *)select_lex->table_list.first,item_list_copy,1,&all_fields,1))
+ return -1;
+
+ if (select_lex->olap == CUBE_TYPE)
+ {
+ for( int i=count-1; i>=0 && !sl_return; i--)
+ sl_return=olap_combos(item_list_copy, new_item_list, (Item *)0, lex, select_lex, 0, 0, count, i);
+ }
+ else if (select_lex->olap == ROLLUP_TYPE)
+ {
+ for( int i=count-1; i>=0 && !sl_return; i--)
+ {
+ Item *item;
+ item_list_copy.pop();
+ List_iterator<Item> it(item_list_copy);
+ new_item_list.empty();
+ while ((item = it++))
+ new_item_list.push_front(item);
+ sl_return=make_new_olap_select(lex, select_lex, new_item_list);
+ }
+ }
+ else
+ sl_return=1; // impossible
+ return sl_return;
+}
+
+#endif /* DISABLED_UNTIL_REWRITTEN_IN_4_1 */
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index fef022ff513..b889b9ee29f 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -14,21 +14,19 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-#ifdef EMBEDDED_LIBRARY
-#define net_read_timeout net_read_timeout1
-#define net_write_timeout net_write_timeout1
-#endif
-
#include "mysql_priv.h"
#include "sql_acl.h"
#include "sql_repl.h"
#include "repl_failsafe.h"
#include <m_ctype.h>
-#include <thr_alarm.h>
#include <myisam.h>
#include <my_dir.h>
#include <assert.h>
+#ifdef HAVE_INNOBASE_DB
+#include "ha_innodb.h"
+#endif
+
#ifdef HAVE_OPENSSL
/*
Without SSL the handshake consists of one packet. This packet
@@ -40,11 +38,11 @@
Maybe it is better to accept flags other than CLIENT_SSL from the
second packet?
*/
-#define SSL_HANDSHAKE_SIZE 2
-#define NORMAL_HANDSHAKE_SIZE 6
-#define MIN_HANDSHAKE_SIZE 2
+#define SSL_HANDSHAKE_SIZE 2
+#define NORMAL_HANDSHAKE_SIZE 6
+#define MIN_HANDSHAKE_SIZE 2
#else
-#define MIN_HANDSHAKE_SIZE 6
+#define MIN_HANDSHAKE_SIZE 6
#endif /* HAVE_OPENSSL */
#define SCRAMBLE_LENGTH 8
@@ -60,7 +58,6 @@ extern "C" int gethostname(char *name, int namelen);
#endif
static int check_for_max_user_connections(USER_CONN *uc);
-static bool check_mqh(THD *thd);
static void decrease_user_connections(USER_CONN *uc);
static bool check_db_used(THD *thd,TABLE_LIST *tables);
static bool check_merge_table_access(THD *thd, char *db, TABLE_LIST *tables);
@@ -100,7 +97,7 @@ static void test_signal(int sig_ptr)
static void init_signals(void)
{
int signals[7] = {SIGINT,SIGILL,SIGFPE,SIGSEGV,SIGTERM,SIGBREAK,SIGABRT } ;
- for(int i=0 ; i < 7 ; i++)
+ for (int i=0 ; i < 7 ; i++)
signal( signals[i], test_signal) ;
}
#endif
@@ -108,7 +105,7 @@ static void init_signals(void)
inline bool end_active_trans(THD *thd)
{
int error=0;
- if (thd->options & (OPTION_NOT_AUTO_COMMIT | OPTION_BEGIN |
+ if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN |
OPTION_TABLE_LOCK))
{
thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE);
@@ -204,7 +201,7 @@ static bool check_user(THD *thd,enum_server_command command, const char *user,
CLIENT_LONG_PASSWORD),&ur);
DBUG_PRINT("info",
("Capabilities: %d packet_length: %d Host: '%s' User: '%s' Using password: %s Access: %u db: '%s'",
- thd->client_capabilities, thd->max_packet_length,
+ thd->client_capabilities, thd->max_client_packet_length,
thd->host_or_ip, thd->priv_user,
passwd[0] ? "yes": "no",
thd->master_access, thd->db ? thd->db : "*none*"));
@@ -224,7 +221,7 @@ static bool check_user(THD *thd,enum_server_command command, const char *user,
{
VOID(pthread_mutex_lock(&LOCK_thread_count));
bool tmp=(thread_count - delayed_insert_threads >= max_connections &&
- !(thd->master_access & PROCESS_ACL));
+ !(thd->master_access & SUPER_ACL));
VOID(pthread_mutex_unlock(&LOCK_thread_count));
if (tmp)
{ // Too many connections
@@ -291,16 +288,19 @@ static int check_for_max_user_connections(USER_CONN *uc)
int error=0;
DBUG_ENTER("check_for_max_user_connections");
- if (max_user_connections && ( max_user_connections <= (uint) uc->connections))
+ if (max_user_connections &&
+ (max_user_connections <= (uint) uc->connections))
{
net_printf(&(current_thd->net),ER_TOO_MANY_USER_CONNECTIONS, uc->user);
error=1;
goto end;
}
uc->connections++;
- if (uc->user_resources.connections && uc->conn_per_hour++ >= uc->user_resources.connections)
+ if (uc->user_resources.connections &&
+ uc->conn_per_hour++ >= uc->user_resources.connections)
{
- net_printf(&current_thd->net, ER_USER_LIMIT_REACHED, uc->user, "max_connections",
+ net_printf(&current_thd->net, ER_USER_LIMIT_REACHED, uc->user,
+ "max_connections",
(long) uc->user_resources.connections);
error=1;
goto end;
@@ -312,12 +312,8 @@ end:
static void decrease_user_connections(USER_CONN *uc)
{
-/* if (!max_user_connections)
- return;
-*/
-
DBUG_ENTER("decrease_user_connections");
- if (!mqh_used && uc->connections && !--uc->connections)
+ if ((uc->connections && !--uc->connections) && !mqh_used)
{
/* Last connection for user; Delete it */
(void) pthread_mutex_lock(&LOCK_user_conn);
@@ -338,26 +334,45 @@ void free_max_user_conn(void)
Check if maximum queries per hour limit has been reached
returns 0 if OK.
- In theory we would need a mutex in the USER_CONN structure for this to be 100 %
- safe, but as the worst scenario is that we would miss counting a couple of
- queries, this isn't critical.
+ In theory we would need a mutex in the USER_CONN structure for this to
+ be 100 % safe, but as the worst scenario is that we would miss counting
+ a couple of queries, this isn't critical.
*/
char uc_update_queries[SQLCOM_END];
-static bool check_mqh(THD *thd)
+static bool check_mqh(THD *thd, uint check_command)
{
bool error=0;
- DBUG_ENTER("check_mqh");
+ time_t check_time = thd->start_time ? thd->start_time : time(NULL);
USER_CONN *uc=thd->user_connect;
+ DBUG_ENTER("check_mqh");
DBUG_ASSERT(uc != 0);
- uint check_command = thd->lex.sql_command;
-
+ /* If more than a hour since last check, reset resource checking */
+ if (check_time - uc->intime >= 3600)
+ {
+ (void) pthread_mutex_lock(&LOCK_user_conn);
+ uc->questions=1;
+ uc->updates=0;
+ uc->conn_per_hour=0;
+ uc->intime=check_time;
+ (void) pthread_mutex_unlock(&LOCK_user_conn);
+ }
+ /* Check that we have not done too many questions / hour */
+ if (uc->user_resources.questions &&
+ uc->questions++ >= uc->user_resources.questions)
+ {
+ net_printf(&thd->net, ER_USER_LIMIT_REACHED, uc->user, "max_questions",
+ (long) uc->user_resources.questions);
+ error=1;
+ goto end;
+ }
if (check_command < (uint) SQLCOM_END)
{
- if (uc->user_resources.updates && uc_update_queries[check_command] &&
- ++(uc->updates) > uc->user_resources.updates)
+ /* Check that we have not done too many updates / hour */
+ if (uc->user_resources.updates && uc_update_queries[check_command] &&
+ uc->updates++ >= uc->user_resources.updates)
{
net_printf(&thd->net, ER_USER_LIMIT_REACHED, uc->user, "max_updates",
(long) uc->user_resources.updates);
@@ -365,34 +380,12 @@ static bool check_mqh(THD *thd)
goto end;
}
}
- else
- {
- bool my_start = thd->start_time != 0;
- time_t check_time = (my_start) ? thd->start_time : time(NULL);
-
- if (check_time - uc->intime >= 3600)
- {
- (void) pthread_mutex_lock(&LOCK_user_conn);
- uc->questions=1;
- uc->updates=0;
- uc->conn_per_hour=0;
- uc->intime=check_time;
- (void) pthread_mutex_unlock(&LOCK_user_conn);
- }
- else if (uc->user_resources.questions && ++(uc->questions) > uc->user_resources.questions)
- {
- net_printf(&thd->net, ER_USER_LIMIT_REACHED, uc->user, "max_questions",
- (long) uc->user_resources.questions);
- error=1;
- goto end;
- }
- }
end:
DBUG_RETURN(error);
}
-static void reset_mqh(THD *thd, LEX_USER *lu, USER_RESOURCES *mqh, bool get_them=false)
+static void reset_mqh(THD *thd, LEX_USER *lu, bool get_them=false)
{
(void) pthread_mutex_lock(&LOCK_user_conn);
@@ -406,10 +399,10 @@ static void reset_mqh(THD *thd, LEX_USER *lu, USER_RESOURCES *mqh, bool get_the
memcpy(temp_user+lu->user.length+1,lu->host.str,lu->host.length);
temp_user[lu->user.length]='\0'; temp_user[temp_len-1]=0;
if ((uc = (struct user_conn *) hash_search(&hash_user_connections,
- (byte*) temp_user, temp_len-1)))
+ (byte*) temp_user, temp_len)))
{
uc->questions=0;
- uc->user_resources=*mqh;
+ get_mqh(temp_user,&temp_user[lu->user.length+1],uc);
uc->updates=0;
uc->conn_per_hour=0;
}
@@ -522,7 +515,7 @@ check_connections(THD *thd)
#endif
if (connect_errors)
reset_host_errors(&thd->remote.sin_addr);
- if (thd->packet.alloc(net_buffer_length))
+ if (thd->packet.alloc(thd->variables.net_buffer_length))
return(ER_OUT_OF_RESOURCES);
thd->client_capabilities=uint2korr(net->read_pos);
@@ -534,7 +527,7 @@ check_connections(THD *thd)
{
/* Do the SSL layering. */
DBUG_PRINT("info", ("IO layer change in progress..."));
- sslaccept(ssl_acceptor_fd, net->vio, thd->inactive_timeout);
+ sslaccept(ssl_acceptor_fd, net->vio, thd->variables.net_wait_timeout);
DBUG_PRINT("info", ("Reading user information over SSL layer"));
if ((pkt_len=my_net_read(net)) == packet_error ||
pkt_len < NORMAL_HANDSHAKE_SIZE)
@@ -556,7 +549,7 @@ check_connections(THD *thd)
}
#endif
- thd->max_packet_length=uint3korr(net->read_pos+2);
+ thd->max_client_packet_length=uint3korr(net->read_pos+2);
char *user= (char*) net->read_pos+5;
char *passwd= strend(user)+1;
char *db=0;
@@ -565,11 +558,11 @@ check_connections(THD *thd)
if (thd->client_capabilities & CLIENT_CONNECT_WITH_DB)
db=strend(passwd)+1;
if (thd->client_capabilities & CLIENT_INTERACTIVE)
- thd->inactive_timeout=net_interactive_timeout;
+ thd->variables.net_wait_timeout= thd->variables.net_interactive_timeout;
if ((thd->client_capabilities & CLIENT_TRANSACTIONS) &&
opt_using_transactions)
thd->net.return_status= &thd->server_status;
- net->timeout=(uint) net_read_timeout;
+ net->read_timeout=(uint) thd->variables.net_read_timeout;
if (check_user(thd,COM_CONNECT, user, passwd, db, 1))
return (-1);
thd->password=test(passwd[0]);
@@ -592,7 +585,7 @@ pthread_handler_decl(handle_one_connection,arg)
if (!(test_flags & TEST_NO_THREADS) & my_thread_init())
{
close_connection(&thd->net,ER_OUT_OF_RESOURCES);
- statistic_increment(aborted_connects,&LOCK_thread_count);
+ statistic_increment(aborted_connects,&LOCK_status);
end_thread(thd,0);
return 0;
}
@@ -619,7 +612,7 @@ pthread_handler_decl(handle_one_connection,arg)
if (thd->store_globals())
{
close_connection(&thd->net,ER_OUT_OF_RESOURCES);
- statistic_increment(aborted_connects,&LOCK_thread_count);
+ statistic_increment(aborted_connects,&LOCK_status);
end_thread(thd,0);
return 0;
}
@@ -641,11 +634,11 @@ pthread_handler_decl(handle_one_connection,arg)
if (vio_type(net->vio) == VIO_TYPE_NAMEDPIPE)
sleep(1); /* must wait after eof() */
#endif
- statistic_increment(aborted_connects,&LOCK_thread_count);
+ statistic_increment(aborted_connects,&LOCK_status);
goto end_thread;
}
- if (thd->max_join_size == HA_POS_ERROR)
+ if ((ulong) thd->variables.max_join_size == (ulong) HA_POS_ERROR)
thd->options |= OPTION_BIG_SELECTS;
if (thd->client_capabilities & CLIENT_COMPRESS)
net->compress=1; // Use compression
@@ -667,7 +660,7 @@ pthread_handler_decl(handle_one_connection,arg)
free_root(&thd->mem_root,MYF(0));
if (net->error && net->vio != 0)
{
- if (!thd->killed && opt_warnings)
+ if (!thd->killed && thd->variables.log_warnings)
sql_print_error(ER(ER_NEW_ABORTING_CONNECTION),
thd->thread_id,(thd->db ? thd->db : "unconnected"),
thd->user ? thd->user : "unauthenticated",
@@ -675,7 +668,7 @@ pthread_handler_decl(handle_one_connection,arg)
(net->last_errno ? ER(net->last_errno) :
ER(ER_UNKNOWN_ERROR)));
send_error(net,net->last_errno,NullS);
- thread_safe_increment(aborted_threads,&LOCK_thread_count);
+ thread_safe_increment(aborted_threads,&LOCK_status);
}
end_thread:
@@ -719,14 +712,16 @@ pthread_handler_decl(handle_bootstrap,arg)
sigset_t set;
VOID(sigemptyset(&set)); // Get mask in use
VOID(pthread_sigmask(SIG_UNBLOCK,&set,&thd->block_signals));
+
+
#endif
- if (thd->max_join_size == (ulong) ~0L)
+ if ((ulong) thd->variables.max_join_size == (ulong) HA_POS_ERROR)
thd->options |= OPTION_BIG_SELECTS;
thd->proc_info=0;
thd->version=refresh_version;
- thd->priv_user=thd->user=(char*)"boot";
+ thd->priv_user=thd->user=(char*) my_strdup("boot", MYF(MY_WME));
buff= (char*) thd->net.buff;
init_sql_alloc(&thd->mem_root, MEM_ROOT_BLOCK_SIZE, MEM_ROOT_PREALLOC);
@@ -744,7 +739,7 @@ pthread_handler_decl(handle_bootstrap,arg)
thd->query= thd->memdup_w_gap(buff, length+1, thd->db_length+1);
thd->query[length] = '\0';
thd->query_id=query_id++;
- if (mqh_used && thd->user_connect && check_mqh(thd))
+ if (mqh_used && thd->user_connect && check_mqh(thd, SQLCOM_END))
{
thd->net.error = 0;
close_thread_tables(thd); // Free tables
@@ -758,14 +753,13 @@ pthread_handler_decl(handle_bootstrap,arg)
free_root(&thd->mem_root,MYF(MY_KEEP_PREALLOC));
free_root(&thd->transaction.mem_root,MYF(MY_KEEP_PREALLOC));
}
- thd->priv_user=thd->user=0;
/* thd->fatal_error should be set in case something went wrong */
end:
(void) pthread_mutex_lock(&LOCK_thread_count);
thread_count--;
- (void) pthread_cond_broadcast(&COND_thread_count);
(void) pthread_mutex_unlock(&LOCK_thread_count);
+ (void) pthread_cond_broadcast(&COND_thread_count);
my_thread_end();
pthread_exit(0);
DBUG_RETURN(0); // Never reached
@@ -840,8 +834,9 @@ bool do_command(THD *thd)
thd->current_tablenr=0;
packet=0;
- old_timeout=net->timeout;
- net->timeout=(uint) thd->inactive_timeout; // Wait max for 8 hours
+ old_timeout=net->read_timeout;
+ // Wait max for 8 hours
+ net->read_timeout=(uint) thd->variables.net_wait_timeout;
net->last_error[0]=0; // Clear error message
net->last_errno=0;
@@ -860,7 +855,7 @@ bool do_command(THD *thd)
vio_description(net->vio), command,
command_name[command]));
}
- net->timeout=old_timeout; // Timeout for writing
+ net->read_timeout=old_timeout; // restore it
DBUG_RETURN(dispatch_command(command,thd, packet+1, (uint) packet_length));
}
@@ -878,31 +873,30 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
DBUG_ENTER("dispatch_command");
thd->command=command;
+ thd->set_time();
VOID(pthread_mutex_lock(&LOCK_thread_count));
thd->query_id=query_id;
if (command != COM_STATISTICS && command != COM_PING)
query_id++;
thread_running++;
VOID(pthread_mutex_unlock(&LOCK_thread_count));
- thd->set_time();
+
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_thread_count);
+ thread_safe_increment(com_stat[SQLCOM_CHANGE_DB],&LOCK_status);
if (!mysql_change_db(thd,packet))
mysql_log.write(thd,command,"%s",thd->db);
break;
case COM_REGISTER_SLAVE:
{
- if (register_slave(thd, (uchar*)packet, packet_length))
- send_error(&thd->net);
- else
+ if (!register_slave(thd, (uchar*)packet, packet_length))
send_ok(&thd->net);
break;
}
case COM_TABLE_DUMP:
{
- thread_safe_increment(com_other,&LOCK_thread_count);
+ thread_safe_increment(com_other, &LOCK_status);
slow_command = TRUE;
uint db_len = *(uchar*)packet;
uint tbl_len = *(uchar*)(packet + db_len + 1);
@@ -919,7 +913,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
}
case COM_CHANGE_USER:
{
- thread_safe_increment(com_other,&LOCK_thread_count);
+ thread_safe_increment(com_other,&LOCK_status);
char *user= (char*) packet;
char *passwd= strend(user)+1;
char *db= strend(passwd)+1;
@@ -994,17 +988,11 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
thd->db_length+2)))
break;
thd->query[packet_length]=0;
- thd->packet.shrink(net_buffer_length); // Reclaim some memory
+ thd->packet.shrink(thd->variables.net_buffer_length);// Reclaim some memory
if (!(specialflag & SPECIAL_NO_PRIOR))
my_pthread_setprio(pthread_self(),QUERY_PRIOR);
mysql_log.write(thd,command,"%s",thd->query);
DBUG_PRINT("query",("%s",thd->query));
- if (mqh_used && thd->user_connect && check_mqh(thd))
- {
- error = TRUE; // Abort client
- net->error = 0; // Don't give abort message
- break;
- }
/* thd->query_length is set by mysql_parse() */
mysql_parse(thd,thd->query,packet_length);
if (!(specialflag & SPECIAL_NO_PRIOR))
@@ -1020,7 +1008,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_thread_count);
+ thread_safe_increment(com_stat[SQLCOM_SHOW_FIELDS],&LOCK_status);
bzero((char*) &table_list,sizeof(table_list));
if (!(table_list.db=thd->db))
{
@@ -1055,7 +1043,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_thread_count);
+ thread_safe_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))
@@ -1063,6 +1051,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
net_printf(&thd->net,ER_WRONG_DB_NAME, db ? db : "NULL");
break;
}
+ if (lower_case_table_names)
+ casedn_str(db);
if (check_access(thd,CREATE_ACL,db,0,1))
break;
mysql_log.write(thd,command,packet);
@@ -1071,7 +1061,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_thread_count);
+ thread_safe_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,6 +1069,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
net_printf(&thd->net,ER_WRONG_DB_NAME, db ? db : "NULL");
break;
}
+ if (lower_case_table_names)
+ casedn_str(db);
if (thd->locked_tables || thd->active_transaction())
{
send_error(&thd->net,ER_LOCK_OR_ACTIVE_TRANSACTION);
@@ -1090,23 +1082,22 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
}
case COM_BINLOG_DUMP:
{
- thread_safe_increment(com_other,&LOCK_thread_count);
+ thread_safe_increment(com_other,&LOCK_status);
slow_command = TRUE;
- if (check_access(thd, FILE_ACL, any_db))
+ if (check_global_access(thd, REPL_SLAVE_ACL))
break;
mysql_log.write(thd,command, 0);
ulong pos;
ushort flags;
uint32 slave_server_id;
+ /* TODO: The following has to be changed to an 8 byte integer */
pos = uint4korr(packet);
flags = uint2korr(packet + 4);
- pthread_mutex_lock(&LOCK_server_id);
thd->server_id=0; /* avoid suicide */
kill_zombie_dump_threads(slave_server_id = uint4korr(packet+6));
thd->server_id = slave_server_id;
- pthread_mutex_unlock(&LOCK_server_id);
- mysql_binlog_send(thd, thd->strdup(packet + 10), pos, flags);
+ mysql_binlog_send(thd, thd->strdup(packet + 10), (my_off_t) pos, flags);
unregister_slave(thd,1,1);
// fake COM_QUIT -- if we get here, the thread needs to terminate
error = TRUE;
@@ -1115,9 +1106,9 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
}
case COM_REFRESH:
{
- thread_safe_increment(com_stat[SQLCOM_FLUSH],&LOCK_thread_count);
+ thread_safe_increment(com_stat[SQLCOM_FLUSH],&LOCK_status);
ulong options= (ulong) (uchar) packet[0];
- if (check_access(thd,RELOAD_ACL,any_db))
+ if (check_global_access(thd,RELOAD_ACL))
break;
mysql_log.write(thd,command,NullS);
if (reload_acl_and_cache(thd, options, (TABLE_LIST*) 0))
@@ -1127,8 +1118,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
break;
}
case COM_SHUTDOWN:
- thread_safe_increment(com_other,&LOCK_thread_count);
- if (check_access(thd,SHUTDOWN_ACL,any_db))
+ thread_safe_increment(com_other,&LOCK_status);
+ if (check_global_access(thd,SHUTDOWN_ACL))
break; /* purecov: inspected */
DBUG_PRINT("quit",("Got shutdown command"));
mysql_log.write(thd,command,NullS);
@@ -1150,7 +1141,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_thread_count);
+ thread_safe_increment(com_stat[SQLCOM_SHOW_STATUS],&LOCK_status);
char buff[200];
ulong uptime = (ulong) (thd->start_time - start_time);
sprintf((char*) buff,
@@ -1169,12 +1160,12 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
break;
}
case COM_PING:
- thread_safe_increment(com_other,&LOCK_thread_count);
+ thread_safe_increment(com_other,&LOCK_status);
send_ok(net); // Tell client we are alive
break;
case COM_PROCESS_INFO:
- thread_safe_increment(com_stat[SQLCOM_SHOW_PROCESSLIST],&LOCK_thread_count);
- if (!thd->priv_user[0] && check_process_priv(thd))
+ thread_safe_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);
mysqld_list_processes(thd,thd->master_access & PROCESS_ACL ? NullS :
@@ -1182,14 +1173,14 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
break;
case COM_PROCESS_KILL:
{
- thread_safe_increment(com_stat[SQLCOM_KILL],&LOCK_thread_count);
+ thread_safe_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_thread_count);
- if (check_process_priv(thd))
+ thread_safe_increment(com_other,&LOCK_status);
+ if (check_global_access(thd, SUPER_ACL))
break; /* purecov: inspected */
mysql_print_status(thd);
mysql_log.write(thd,command,NullS);
@@ -1220,7 +1211,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
{
thd->proc_info="logging slow query";
- if ((ulong) (thd->start_time - thd->time_after_lock) > long_query_time ||
+ if ((ulong) (thd->start_time - thd->time_after_lock) >
+ thd->variables.long_query_time ||
((thd->lex.select_lex.options &
(QUERY_NO_INDEX_USED | QUERY_NO_GOOD_INDEX_USED)) &&
(specialflag & SPECIAL_LONG_LOG_FORMAT)))
@@ -1236,7 +1228,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
thd->query=0;
thread_running--;
VOID(pthread_mutex_unlock(&LOCK_thread_count));
- thd->packet.shrink(net_buffer_length); // Reclaim some memory
+ thd->packet.shrink(thd->variables.net_buffer_length); // Reclaim some memory
free_root(&thd->mem_root,MYF(MY_KEEP_PREALLOC));
DBUG_RETURN(error);
}
@@ -1299,7 +1291,7 @@ mysql_execute_command(void)
!tables_ok(thd,tables)))
DBUG_VOID_RETURN;
- thread_safe_increment(com_stat[lex->sql_command],&LOCK_thread_count);
+ thread_safe_increment(com_stat[lex->sql_command],&LOCK_status);
switch (lex->sql_command) {
case SQLCOM_SELECT:
{
@@ -1389,26 +1381,16 @@ mysql_execute_command(void)
case SQLCOM_PURGE:
{
- if (check_process_priv(thd))
+ if (check_global_access(thd, SUPER_ACL))
goto error;
res = purge_master_logs(thd, lex->to_log);
break;
}
- case SQLCOM_SHOW_WARNS_COUNT:
- {
- res = mysqld_show_warnings_count(thd);
- break;
- }
case SQLCOM_SHOW_WARNS:
{
res = mysqld_show_warnings(thd);
break;
}
- case SQLCOM_SHOW_ERRORS_COUNT:
- {
- res = mysqld_show_errors_count(thd);
- break;
- }
case SQLCOM_SHOW_ERRORS:
{
res = mysqld_show_errors(thd);
@@ -1416,21 +1398,21 @@ mysql_execute_command(void)
}
case SQLCOM_SHOW_NEW_MASTER:
{
- if (check_access(thd, FILE_ACL, any_db))
+ if (check_global_access(thd, REPL_SLAVE_ACL))
goto error;
res = show_new_master(thd);
break;
}
case SQLCOM_SHOW_SLAVE_HOSTS:
{
- if (check_access(thd, FILE_ACL, any_db))
+ if (check_global_access(thd, REPL_SLAVE_ACL))
goto error;
res = show_slave_hosts(thd);
break;
}
case SQLCOM_SHOW_BINLOG_EVENTS:
{
- if (check_access(thd, FILE_ACL, any_db))
+ if (check_global_access(thd, REPL_SLAVE_ACL))
goto error;
res = show_binlog_events(thd);
break;
@@ -1439,7 +1421,7 @@ mysql_execute_command(void)
{
if (check_db_used(thd,tables) ||
check_table_access(thd,SELECT_ACL, tables) ||
- check_access(thd, FILE_ACL, any_db))
+ check_global_access(thd, FILE_ACL))
goto error; /* purecov: inspected */
res = mysql_backup_table(thd, tables);
@@ -1448,15 +1430,15 @@ mysql_execute_command(void)
case SQLCOM_RESTORE_TABLE:
{
if (check_db_used(thd,tables) ||
- check_table_access(thd,INSERT_ACL, tables) ||
- check_access(thd, FILE_ACL, any_db))
+ check_table_access(thd, INSERT_ACL, tables) ||
+ check_global_access(thd, FILE_ACL))
goto error; /* purecov: inspected */
res = mysql_restore_table(thd, tables);
break;
}
case SQLCOM_CHANGE_MASTER:
{
- if (check_access(thd, PROCESS_ACL, any_db))
+ if (check_global_access(thd, SUPER_ACL))
goto error;
LOCK_ACTIVE_MI;
res = change_master(thd,active_mi);
@@ -1465,7 +1447,7 @@ mysql_execute_command(void)
}
case SQLCOM_SHOW_SLAVE_STAT:
{
- if (check_process_priv(thd))
+ if (check_global_access(thd, SUPER_ACL))
goto error;
LOCK_ACTIVE_MI;
res = show_master_info(thd,active_mi);
@@ -1474,18 +1456,31 @@ mysql_execute_command(void)
}
case SQLCOM_SHOW_MASTER_STAT:
{
- if (check_process_priv(thd))
+ if (check_global_access(thd, SUPER_ACL))
goto error;
res = show_binlog_info(thd);
break;
}
case SQLCOM_LOAD_MASTER_DATA: // sync with master
- if (check_process_priv(thd))
+ if (check_global_access(thd, SUPER_ACL))
goto error;
- res = load_master_data(thd);
+ if (end_active_trans(thd))
+ res= -1;
+ else
+ res = load_master_data(thd);
break;
+#ifdef HAVE_INNOBASE_DB
+ case SQLCOM_SHOW_INNODB_STATUS:
+ {
+ if (check_global_access(thd, SUPER_ACL))
+ goto error;
+ res = innodb_show_status(thd);
+ break;
+ }
+#endif
+
case SQLCOM_LOAD_MASTER_TABLE:
{
if (!tables->db)
@@ -1518,19 +1513,22 @@ mysql_execute_command(void)
break;
}
case SQLCOM_CREATE_TABLE:
+ {
+ ulong want_priv= ((lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) ?
+ CREATE_TMP_ACL : CREATE_ACL);
if (!tables->db)
tables->db=thd->db;
- if (check_access(thd,CREATE_ACL,tables->db,&tables->grant.privilege) ||
+ if (check_access(thd,want_priv,tables->db,&tables->grant.privilege) ||
check_merge_table_access(thd, tables->db,
(TABLE_LIST *)
lex->create_info.merge_list.first))
goto error; /* purecov: inspected */
- if (grant_option)
+ if (grant_option && want_priv != CREATE_TMP_ACL)
{
/* Check that the first table has CREATE privilege */
TABLE_LIST *tmp_table_list=tables->next;
tables->next=0;
- bool error=check_grant(thd,CREATE_ACL,tables);
+ bool error=check_grant(thd, want_priv, tables);
tables->next=tmp_table_list;
if (error)
goto error;
@@ -1603,6 +1601,7 @@ mysql_execute_command(void)
send_ok(&thd->net);
}
break;
+ }
case SQLCOM_CREATE_INDEX:
if (!tables->db)
tables->db=thd->db;
@@ -1636,7 +1635,7 @@ mysql_execute_command(void)
break;
#else
{
- uint priv=0;
+ ulong priv=0;
if (lex->name && strlen(lex->name) > NAME_LEN)
{
net_printf(&thd->net,ER_WRONG_TABLE_NAME,lex->name);
@@ -1726,7 +1725,7 @@ mysql_execute_command(void)
DBUG_VOID_RETURN;
#else
{
- if (check_process_priv(thd))
+ if (check_global_access(thd, SUPER_ACL))
goto error;
res = show_binlogs(thd);
break;
@@ -1829,25 +1828,37 @@ mysql_execute_command(void)
multi_update *result;
uint table_count;
TABLE_LIST *auxi;
+ const char *msg=0;
+
lex->sql_command=SQLCOM_MULTI_UPDATE;
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 || (select_lex->select_limit && select_lex->select_limit < INT_MAX))
+
+ if (select_lex->order_list.elements)
+ msg="ORDER BY";
+ else if (select_lex->select_limit && select_lex->select_limit !=
+ HA_POS_ERROR)
+ msg="LIMIT";
+ if (msg)
{
- send_error(&thd->net,ER_NOT_ALLOWED_COMMAND); /// will have to come up with something better eventually
- DBUG_VOID_RETURN;
+ net_printf(&thd->net, ER_WRONG_USAGE, "UPDATE", msg);
+ res= 1;
+ break;
}
+
tables->grant.want_privilege=(SELECT_ACL & ~tables->grant.privilege);
if ((res=open_and_lock_tables(thd,tables)))
break;
unit->select_limit_cnt= HA_POS_ERROR;
if (!setup_fields(thd,tables,select_lex->item_list,1,0,0) &&
- !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)))
+ !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)))
{
List <Item> total_list;
List_iterator <Item> field_list(select_lex->item_list);
@@ -1897,11 +1908,13 @@ mysql_execute_command(void)
case SQLCOM_INSERT_SELECT:
{
- // Check that we have modify privileges for the first table and
- // select privileges for the rest
+ /*
+ Check that we have modify privileges for the first table and
+ select privileges for the rest
+ */
{
- uint privilege= (lex->sql_command == SQLCOM_INSERT_SELECT ?
- INSERT_ACL : INSERT_ACL | UPDATE_ACL | DELETE_ACL);
+ ulong privilege= (lex->sql_command == SQLCOM_INSERT_SELECT ?
+ INSERT_ACL : INSERT_ACL | UPDATE_ACL | DELETE_ACL);
TABLE_LIST *save_next=tables->next;
tables->next=0;
if (check_access(thd, privilege,
@@ -2011,9 +2024,7 @@ mysql_execute_command(void)
}
auxi->lock_type=walk->lock_type=TL_WRITE;
auxi->table_list= walk; // Remember corresponding table
- (void)add_item_to_list(new Item_field(auxi->db,auxi->real_name,"*"));
}
- tables->grant.want_privilege=(SELECT_ACL & ~tables->grant.privilege);
if (add_item_to_list(new Item_null()))
{
res= -1;
@@ -2071,13 +2082,13 @@ mysql_execute_command(void)
DBUG_VOID_RETURN;
#else
if ((specialflag & SPECIAL_SKIP_SHOW_DB) &&
- check_process_priv(thd))
+ check_global_access(thd, SHOW_DB_ACL))
goto error;
res= mysqld_show_dbs(thd, (lex->wild ? lex->wild->ptr() : NullS));
break;
#endif
case SQLCOM_SHOW_PROCESSLIST:
- if (!thd->priv_user[0] && check_process_priv(thd))
+ if (!thd->priv_user[0] && check_global_access(thd,PROCESS_ACL))
break;
mysqld_list_processes(thd,thd->master_access & PROCESS_ACL ? NullS :
thd->priv_user,lex->verbose);
@@ -2092,11 +2103,12 @@ mysql_execute_command(void)
res= mysqld_show_column_types(thd);
break;
case SQLCOM_SHOW_STATUS:
- res= mysqld_show(thd,(lex->wild ? lex->wild->ptr() : NullS),status_vars);
+ res= mysqld_show(thd,(lex->wild ? lex->wild->ptr() : NullS),status_vars,
+ OPT_GLOBAL);
break;
case SQLCOM_SHOW_VARIABLES:
res= mysqld_show(thd, (lex->wild ? lex->wild->ptr() : NullS),
- init_vars);
+ init_vars, lex->option_type);
break;
case SQLCOM_SHOW_LOGS:
#ifdef DONT_ALLOW_SHOW_COMMANDS
@@ -2227,39 +2239,11 @@ mysql_execute_command(void)
break;
}
case SQLCOM_SET_OPTION:
- {
- ulong org_options=thd->options;
- thd->options=select_lex->options;
- thd->update_lock_default= ((thd->options & OPTION_LOW_PRIORITY_UPDATES) ?
- TL_WRITE_LOW_PRIORITY : TL_WRITE);
- thd->default_select_limit=select_lex->select_limit;
- thd->tx_isolation=lex->tx_isolation;
- DBUG_PRINT("info",("options: %ld limit: %ld",
- thd->options,(long) thd->default_select_limit));
-
- /* Check if auto_commit mode changed */
- if ((org_options ^ select_lex->options) & OPTION_NOT_AUTO_COMMIT)
- {
- if ((org_options & OPTION_NOT_AUTO_COMMIT))
- {
- /* We changed to auto_commit mode */
- thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE);
- thd->server_status|= SERVER_STATUS_AUTOCOMMIT;
- if (ha_commit(thd))
- {
- res= -1;
- break;
- }
- }
- else
- {
- thd->options&= ~(ulong) (OPTION_STATUS_NO_TRANS_UPDATE);
- thd->server_status&= ~SERVER_STATUS_AUTOCOMMIT;
- }
- }
- send_ok(&thd->net);
+ if (sql_set_variables(thd, &lex->var_list))
+ res= -1;
+ else
+ send_ok(&thd->net);
break;
- }
case SQLCOM_UNLOCK_TABLES:
if (thd->locked_tables)
{
@@ -2284,8 +2268,7 @@ mysql_execute_command(void)
}
if (check_db_used(thd,tables) || end_active_trans(thd))
goto error;
- if (check_table_access(thd, SELECT_ACL | INSERT_ACL | UPDATE_ACL | DELETE_ACL , tables)
- || (grant_option && check_grant(thd,SELECT_ACL | INSERT_ACL | UPDATE_ACL | DELETE_ACL,tables)))
+ if (check_table_access(thd, LOCK_TABLES_ACL | SELECT_ACL, tables))
goto error;
thd->in_lock_tables=1;
thd->options|= OPTION_TABLE_LOCK;
@@ -2306,6 +2289,8 @@ mysql_execute_command(void)
net_printf(&thd->net,ER_WRONG_DB_NAME, lex->name);
break;
}
+ if (lower_case_table_names)
+ casedn_str(lex->name);
if (check_access(thd,CREATE_ACL,lex->name,0,1))
break;
res=mysql_create_db(thd,lex->name,&lex->create_info,0);
@@ -2318,6 +2303,8 @@ mysql_execute_command(void)
net_printf(&thd->net,ER_WRONG_DB_NAME, lex->name);
break;
}
+ if (lower_case_table_names)
+ casedn_str(lex->name);
if (check_access(thd,DROP_ACL,lex->name,0,1))
break;
if (thd->locked_tables || thd->active_transaction())
@@ -2391,8 +2378,10 @@ mysql_execute_command(void)
tables ? 0 : 1))
goto error;
- /* Check that the user isn't trying to change a password for another
- user if he doesn't have UPDATE privilege to the MySQL database */
+ /*
+ Check that the user isn't trying to change a password for another
+ user if he doesn't have UPDATE privilege to the MySQL database
+ */
if (thd->user) // If not replication
{
@@ -2426,7 +2415,7 @@ mysql_execute_command(void)
mysql_update_log.write(thd, thd->query, thd->query_length);
if (mysql_bin_log.is_open())
{
- Query_log_event qinfo(thd, thd->query);
+ Query_log_event qinfo(thd, thd->query, thd->query_length);
mysql_bin_log.write(&qinfo);
}
}
@@ -2446,15 +2435,15 @@ mysql_execute_command(void)
mysql_update_log.write(thd, thd->query, thd->query_length);
if (mysql_bin_log.is_open())
{
- Query_log_event qinfo(thd, thd->query);
+ Query_log_event qinfo(thd, thd->query, thd->query_length);
mysql_bin_log.write(&qinfo);
}
- if (mqh_used && (lex->mqh.questions || lex->mqh.updates || lex->mqh.connections) && lex->sql_command == SQLCOM_GRANT)
+ if (mqh_used && lex->sql_command == SQLCOM_GRANT)
{
List_iterator <LEX_USER> str_list(lex->users_list);
LEX_USER *user;
while ((user=str_list++))
- reset_mqh(thd,user,&(lex->mqh));
+ reset_mqh(thd,user);
}
}
}
@@ -2462,7 +2451,7 @@ mysql_execute_command(void)
}
case SQLCOM_FLUSH:
case SQLCOM_RESET:
- if (check_access(thd,RELOAD_ACL,any_db) || check_db_used(thd, tables))
+ if (check_global_access(thd,RELOAD_ACL) || check_db_used(thd, tables))
goto error;
if (reload_acl_and_cache(thd, lex->type, tables))
send_error(&thd->net,0);
@@ -2535,7 +2524,6 @@ mysql_execute_command(void)
}
else
res= -1;
- thd->transaction.cleanup();
break;
}
case SQLCOM_ROLLBACK:
@@ -2550,7 +2538,6 @@ mysql_execute_command(void)
else
res= -1;
thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE);
- thd->transaction.cleanup();
break;
default: /* Impossible */
send_ok(&thd->net);
@@ -2566,20 +2553,23 @@ error:
/****************************************************************************
-** Get the user (global) and database privileges for all used tables
-** Returns true (error) if we can't get the privileges and we don't use
-** table/column grants.
-** The idea of EXTRA_ACL is that one will be granted access to the table if
-** one has the asked privilege on any column combination of the table; For
-** example to be able to check a table one needs to have SELECT privilege on
-** any column of the table.
+ Get the user (global) and database privileges for all used tables
+ Returns true (error) if we can't get the privileges and we don't use
+ table/column grants.
+ The idea of EXTRA_ACL is that one will be granted access to the table if
+ one has the asked privilege on any column combination of the table; For
+ example to be able to check a table one needs to have SELECT privilege on
+ any column of the table.
****************************************************************************/
bool
-check_access(THD *thd,uint want_access,const char *db, uint *save_priv,
+check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
bool dont_check_global_grants, bool no_errors)
{
- uint db_access,dummy;
+ DBUG_ENTER("check_access");
+ DBUG_PRINT("enter",("want_access: %lu master_access: %lu", want_access,
+ thd->master_access));
+ ulong db_access,dummy;
if (save_priv)
*save_priv=0;
else
@@ -2589,15 +2579,15 @@ check_access(THD *thd,uint want_access,const char *db, uint *save_priv,
{
if (!no_errors)
send_error(&thd->net,ER_NO_DB_ERROR); /* purecov: tested */
- return TRUE; /* purecov: tested */
+ DBUG_RETURN(TRUE); /* purecov: tested */
}
if ((thd->master_access & want_access) == want_access)
{
*save_priv=thd->master_access;
- return FALSE;
+ DBUG_RETURN(FALSE);
}
- if ((want_access & ~thd->master_access) & ~(DB_ACLS | EXTRA_ACL) ||
+ if (((want_access & ~thd->master_access) & ~(DB_ACLS | EXTRA_ACL)) ||
! db && dont_check_global_grants)
{ // We can never grant this
if (!no_errors)
@@ -2605,50 +2595,60 @@ check_access(THD *thd,uint want_access,const char *db, uint *save_priv,
thd->priv_user,
thd->host_or_ip,
thd->password ? ER(ER_YES) : ER(ER_NO));/* purecov: tested */
- return TRUE; /* purecov: tested */
+ DBUG_RETURN(TRUE); /* purecov: tested */
}
if (db == any_db)
- return FALSE; // Allow select on anything
+ DBUG_RETURN(FALSE); // Allow select on anything
if (db && (!thd->db || strcmp(db,thd->db)))
db_access=acl_get(thd->host, thd->ip, (char*) &thd->remote.sin_addr,
thd->priv_user, db); /* purecov: inspected */
else
db_access=thd->db_access;
- want_access &= ~EXTRA_ACL; // Remove SHOW attribute
+ // Remove SHOW attribute and access rights we already have
+ want_access &= ~(thd->master_access | EXTRA_ACL);
db_access= ((*save_priv=(db_access | thd->master_access)) & want_access);
/* grant_option is set if there exists a single table or column grant */
if (db_access == want_access ||
((grant_option && !dont_check_global_grants) &&
!(want_access & ~TABLE_ACLS)))
- return FALSE; /* Ok */
+ DBUG_RETURN(FALSE); /* Ok */
if (!no_errors)
net_printf(&thd->net,ER_DBACCESS_DENIED_ERROR,
thd->priv_user,
thd->host_or_ip,
db ? db : thd->db ? thd->db : "unknown"); /* purecov: tested */
- return TRUE; /* purecov: tested */
+ DBUG_RETURN(TRUE); /* purecov: tested */
}
-bool check_process_priv(THD *thd)
+/* check for global access and give descriptive error message if it fails */
+
+bool check_global_access(THD *thd, ulong want_access)
{
- return (check_access(thd ? thd : current_thd,PROCESS_ACL,any_db));
+ char command[128];
+ if ((thd->master_access & want_access) == want_access)
+ return 0;
+ get_privilege_desc(command, sizeof(command), want_access);
+ net_printf(&thd->net,ER_SPECIFIC_ACCESS_DENIED_ERROR,
+ command);
+ return 1;
}
/*
-** Check the privilege for all used tables. Table privileges are cached
-** in the table list for GRANT checking
+ Check the privilege for all used tables. Table privileges are cached
+ in the table list for GRANT checking
*/
bool
-check_table_access(THD *thd,uint want_access,TABLE_LIST *tables,
+check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables,
bool no_errors)
{
- uint found=0,found_access=0;
+ uint found=0;
+ ulong found_access=0;
TABLE_LIST *org_tables=tables;
for (; tables ; tables=tables->next)
{
@@ -2669,17 +2669,8 @@ check_table_access(THD *thd,uint want_access,TABLE_LIST *tables,
}
}
else if (check_access(thd,want_access,tables->db,&tables->grant.privilege,
- 0, no_errors | grant_option))
- {
- if (grant_option)
- {
- if ( check_access(thd,want_access & (uint) ~TABLE_ACLS,tables->db,&tables->grant.privilege,
0, no_errors))
- return TRUE;
- }
- else
- return TRUE;
- }
+ return TRUE;
}
if (grant_option)
return check_grant(thd,want_access & ~EXTRA_ACL,org_tables,
@@ -2805,6 +2796,8 @@ mysql_init_query(THD *thd)
thd->free_list= 0;
thd->lex.union_option= 0;
thd->lex.select= &thd->lex.select_lex;
+ thd->lex.olap=0;
+ thd->lex.select->olap= UNSPECIFIED_OLAP_TYPE;
thd->fatal_error= 0; // Safety
thd->last_insert_id_used= thd->query_start_used= thd->insert_id_used=0;
thd->sent_row_count= thd->examined_row_count= 0;
@@ -2821,11 +2814,13 @@ mysql_init_select(LEX *lex)
SELECT_LEX *select_lex= lex->select;
select_lex->init_select();
select_lex->master_unit()->select_limit= select_lex->select_limit=
- lex->thd->default_select_limit;
+ lex->thd->variables.select_limit;
+ select_lex->olap= UNSPECIFIED_OLAP_TYPE;
lex->exchange= 0;
lex->proc_list.first= 0;
}
+
bool
mysql_new_select(LEX *lex, bool move_down)
{
@@ -2855,6 +2850,7 @@ mysql_new_select(LEX *lex, bool move_down)
return 0;
}
+
void mysql_init_multi_delete(LEX *lex)
{
lex->sql_command= SQLCOM_DELETE_MULTI;
@@ -2865,6 +2861,7 @@ void mysql_init_multi_delete(LEX *lex)
lex->select->init_query();
}
+
void
mysql_parse(THD *thd, char *inBuf, uint length)
{
@@ -2877,7 +2874,8 @@ mysql_parse(THD *thd, char *inBuf, uint length)
LEX *lex=lex_start(thd, (uchar*) inBuf, length);
if (!yyparse() && ! thd->fatal_error)
{
- if (mqh_used && thd->user_connect && check_mqh(thd))
+ if (mqh_used && thd->user_connect &&
+ check_mqh(thd, thd->lex.sql_command))
{
thd->net.error = 0;
}
@@ -2888,7 +2886,11 @@ mysql_parse(THD *thd, char *inBuf, uint length)
}
}
else
+ {
+ DBUG_PRINT("info",("Command aborted. Fatal_error: %d",
+ thd->fatal_error));
query_cache_abort(&thd->net);
+ }
thd->proc_info="freeing items";
free_items(thd); /* Free strings used by items */
lex_end(lex);
@@ -3379,14 +3381,12 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables)
bool result=0;
select_errors=0; /* Write if more errors */
- // TODO: figure out what's up with the commented out line below
- // mysql_log.flush(); // Flush log
if (options & REFRESH_GRANT)
{
acl_reload();
grant_reload();
if (mqh_used)
- reset_mqh(thd,(LEX_USER *) NULL, 0, true);
+ reset_mqh(thd,(LEX_USER *) NULL,true);
}
if (options & REFRESH_LOG)
{
@@ -3436,38 +3436,56 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables)
if (options & REFRESH_SLAVE)
{
LOCK_ACTIVE_MI;
- if (reset_slave(active_mi))
+ if (reset_slave(thd, active_mi))
result=1;
UNLOCK_ACTIVE_MI;
}
if (options & REFRESH_USER_RESOURCES)
- reset_mqh(thd,(LEX_USER *) NULL, 0);
+ reset_mqh(thd,(LEX_USER *) NULL);
return result;
}
+/*
+ kill on thread
+
+ SYNOPSIS
+ kill_one_thread()
+ thd Thread class
+ id Thread id
+
+ NOTES
+ This is written such that we have a short lock on LOCK_thread_count
+*/
+
void kill_one_thread(THD *thd, ulong id)
{
- VOID(pthread_mutex_lock(&LOCK_thread_count)); // For unlink from list
- I_List_iterator<THD> it(threads);
THD *tmp;
uint error=ER_NO_SUCH_THREAD;
+ VOID(pthread_mutex_lock(&LOCK_thread_count)); // For unlink from list
+ I_List_iterator<THD> it(threads);
while ((tmp=it++))
{
if (tmp->thread_id == id)
{
- if ((thd->master_access & PROCESS_ACL) ||
- !strcmp(thd->user,tmp->user))
- {
- tmp->awake(1 /*prepare to die*/);
- error=0;
- }
- else
- error=ER_KILL_DENIED_ERROR;
- break; // Found thread
+ pthread_mutex_lock(&tmp->LOCK_delete); // Lock from delete
+ break;
}
}
VOID(pthread_mutex_unlock(&LOCK_thread_count));
+ if (tmp)
+ {
+ if ((thd->master_access & SUPER_ACL) ||
+ !strcmp(thd->user,tmp->user))
+ {
+ tmp->awake(1 /*prepare to die*/);
+ error=0;
+ }
+ else
+ error=ER_KILL_DENIED_ERROR;
+ pthread_mutex_unlock(&tmp->LOCK_delete);
+ }
+
if (!error)
send_ok(&thd->net);
else
@@ -3514,3 +3532,28 @@ static bool append_file_to_dir(THD *thd, char **filename_ptr, char *table_name)
strxmov(ptr,buff,table_name,NullS);
return 0;
}
+
+/*
+ Check if the select is a simple select (not an union)
+
+ SYNOPSIS
+ check_simple_select()
+
+ RETURN VALUES
+ 0 ok
+ 1 error ; In this case the error messege is sent to the client
+*/
+
+bool check_simple_select()
+{
+ THD *thd= current_thd;
+ if (thd->lex.select != &thd->lex.select_lex)
+ {
+ char command[80];
+ strmake(command, thd->lex.yylval->symbol.str,
+ min(thd->lex.yylval->symbol.length, sizeof(command)-1));
+ net_printf(&thd->net, ER_CANT_USE_OPTION_HERE, command);
+ return 1;
+ }
+ return 0;
+}
diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc
index 305491c7346..049690eb318 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);
+ Query_log_event qinfo(thd, thd->query, thd->query_length);
mysql_bin_log.write(&qinfo);
}
send_ok(&thd->net);
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index b6c7c98a4cf..628b1775778 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -21,14 +21,13 @@
#include "sql_acl.h"
#include "log_event.h"
#include "mini_client.h"
-#include <thr_alarm.h>
#include <my_dir.h>
#include <assert.h>
extern const char* any_db;
int max_binlog_dump_events = 0; // unlimited
-bool opt_sporadic_binlog_dump_fail = 0;
+my_bool opt_sporadic_binlog_dump_fail = 0;
static int binlog_dump_count = 0;
int check_binlog_magic(IO_CACHE* log, const char** errmsg)
@@ -93,13 +92,17 @@ static int send_file(THD *thd)
char buf[IO_SIZE]; // It's safe to alloc this
DBUG_ENTER("send_file");
- // the client might be slow loading the data, give him wait_timeout to do
- // the job
- old_timeout = thd->net.timeout;
- thd->net.timeout = thd->inactive_timeout;
+ /*
+ The client might be slow loading the data, give him wait_timeout to do
+ the job
+ */
+ old_timeout = thd->net.read_timeout;
+ thd->net.read_timeout = thd->variables.net_wait_timeout;
- // we need net_flush here because the client will not know it needs to send
- // us the file name until it has processed the load event entry
+ /*
+ We need net_flush here because the client will not know it needs to send
+ us the file name until it has processed the load event entry
+ */
if (net_flush(net) || (packet_len = my_net_read(net)) == packet_error)
{
errmsg = "while reading file name";
@@ -138,7 +141,7 @@ static int send_file(THD *thd)
error = 0;
err:
- thd->net.timeout = old_timeout;
+ thd->net.read_timeout = old_timeout;
if (fd >= 0)
(void) my_close(fd, MYF(0));
if (errmsg)
@@ -154,6 +157,7 @@ File open_binlog(IO_CACHE *log, const char *log_file_name,
const char **errmsg)
{
File file;
+ DBUG_ENTER("open_binlog");
if ((file = my_open(log_file_name, O_RDONLY | O_BINARY, MYF(MY_WME))) < 0 ||
init_io_cache(log, file, IO_SIZE*2, READ_CACHE, 0, 0,
@@ -164,7 +168,7 @@ File open_binlog(IO_CACHE *log, const char *log_file_name,
}
if (check_binlog_magic(log,errmsg))
goto err;
- return file;
+ DBUG_RETURN(file);
err:
if (file >= 0)
@@ -172,10 +176,31 @@ err:
my_close(file,MYF(0));
end_io_cache(log);
}
- return -1;
+ DBUG_RETURN(-1);
}
+/*
+ Adjust the position pointer in the binary log file for all running slaves
+
+ SYNOPSIS
+ adjust_linfo_offsets()
+ purge_offset Number of bytes removed from start of log index file
+
+ NOTES
+ - This is called when doing a PURGE when we delete lines from the
+ index log file
+
+ REQUIREMENTS
+ - Before calling this function, we have to ensure that no threads are
+ using any binary log file before purge_offset.a
+
+ TODO
+ - Inform the slave threads that they should sync the position
+ in the binary log file with flush_relay_log_info.
+ Now they sync is done for next read.
+*/
+
void adjust_linfo_offsets(my_off_t purge_offset)
{
THD *tmp;
@@ -189,9 +214,10 @@ void adjust_linfo_offsets(my_off_t purge_offset)
if ((linfo = tmp->current_linfo))
{
pthread_mutex_lock(&linfo->lock);
- /* index file offset can be less that purge offset
- only if we just started reading the index file. In that case
- we have nothing to adjust
+ /*
+ Index file offset can be less that purge offset only if
+ we just started reading the index file. In that case
+ we have nothing to adjust
*/
if (linfo->index_file_offset < purge_offset)
linfo->fatal = (linfo->index_file_offset != 0);
@@ -221,7 +247,8 @@ bool log_in_use(const char* log_name)
pthread_mutex_lock(&linfo->lock);
result = !memcmp(log_name, linfo->log_file_name, log_name_len);
pthread_mutex_unlock(&linfo->lock);
- if (result) break;
+ if (result)
+ break;
}
}
@@ -265,12 +292,16 @@ binlog purge"; break;
return 0;
}
+/*
+ TODO: Clean up loop to only have one call to send_file()
+*/
-void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags)
+void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos,
+ ushort flags)
{
LOG_INFO linfo;
char *log_file_name = linfo.log_file_name;
- char search_file_name[FN_REFLEN];
+ char search_file_name[FN_REFLEN], *name;
IO_CACHE log;
File file = -1;
String* packet = &thd->packet;
@@ -281,66 +312,78 @@ void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags)
int left_events = max_binlog_dump_events;
#endif
DBUG_ENTER("mysql_binlog_send");
+ DBUG_PRINT("enter",("log_ident: '%s' pos: %ld", log_ident, (long) pos));
+
bzero((char*) &log,sizeof(log));
#ifndef DBUG_OFF
if (opt_sporadic_binlog_dump_fail && (binlog_dump_count++ % 2))
{
errmsg = "Master failed COM_BINLOG_DUMP to test if slave can recover";
+ my_errno= ER_UNKNOWN_ERROR;
goto err;
}
#endif
-
if (!mysql_bin_log.is_open())
{
errmsg = "Binary log is not open";
+ my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG;
goto err;
}
if (!server_id_supplied)
{
errmsg = "Misconfigured master - server id was not set";
+ my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG;
goto err;
}
+ name=search_file_name;
if (log_ident[0])
mysql_bin_log.make_log_name(search_file_name, log_ident);
else
- search_file_name[0] = 0;
+ name=0; // Find first log
linfo.index_file_offset = 0;
thd->current_linfo = &linfo;
- if (mysql_bin_log.find_first_log(&linfo, search_file_name))
+ if (mysql_bin_log.find_log_pos(&linfo, name, 1))
{
- errmsg = "Could not find first log";
+ errmsg = "Could not find first log file name in binary log index file";
+ my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG;
goto err;
}
if ((file=open_binlog(&log, log_file_name, &errmsg)) < 0)
+ {
+ my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG;
goto err;
-
- if (pos < 4)
+ }
+ if (pos < BIN_LOG_HEADER_SIZE || pos > my_b_filelength(&log))
{
- errmsg = "Client requested master to start repliction from \
+ errmsg= "Client requested master to start replication from \
impossible position";
+ my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG;
goto err;
}
my_b_seek(&log, pos); // Seek will done on next read
- packet->length(0);
- // we need to start a packet with something other than 255
- // to distiquish it from error
- packet->append("\0", 1);
+ /*
+ We need to start a packet with something other than 255
+ to distiquish it from error
+ */
+ packet->set("\0", 1);
// if we are at the start of the log
- if (pos == 4)
+ if (pos == BIN_LOG_HEADER_SIZE)
{
// tell the client log name with a fake rotate_event
if (fake_rotate_event(net, packet, log_file_name, &errmsg))
+ {
+ my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG;
goto err;
- packet->length(0);
- packet->append("\0", 1);
+ }
+ packet->set("\0", 1);
}
while (!net->error && net->vio != 0 && !thd->killed)
@@ -354,12 +397,14 @@ impossible position";
{
net_flush(net);
errmsg = "Debugging binlog dump abort";
+ my_errno= ER_UNKNOWN_ERROR;
goto err;
}
#endif
if (my_net_write(net, (char*)packet->ptr(), packet->length()) )
{
errmsg = "Failed on my_net_write()";
+ my_errno= ER_UNKNOWN_ERROR;
goto err;
}
DBUG_PRINT("info", ("log event code %d",
@@ -369,23 +414,26 @@ impossible position";
if (send_file(thd))
{
errmsg = "failed in send_file()";
+ my_errno= ER_UNKNOWN_ERROR;
goto err;
}
}
- packet->length(0);
- packet->append("\0",1);
+ packet->set("\0", 1);
}
- // TODO: now that we are logging the offset, check to make sure
- // the recorded offset and the actual match
+ /*
+ TODO: now that we are logging the offset, check to make sure
+ the recorded offset and the actual match
+ */
if (error != LOG_READ_EOF)
{
- switch(error) {
+ my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG;
+ switch (error) {
case LOG_READ_BOGUS:
errmsg = "bogus data in log event";
break;
case LOG_READ_TOO_LARGE:
- errmsg = "log event entry exceeded max_allowed_packet -\
- increase max_allowed_packet on master";
+ errmsg = "log event entry exceeded max_allowed_packet; \
+Increase max_allowed_packet on master";
break;
case LOG_READ_IO:
errmsg = "I/O error reading log event";
@@ -406,18 +454,22 @@ impossible position";
if (!(flags & BINLOG_DUMP_NON_BLOCK) &&
mysql_bin_log.is_active(log_file_name))
{
- // block until there is more data in the log
- // unless non-blocking mode requested
+ /*
+ Block until there is more data in the log
+ */
if (net_flush(net))
{
errmsg = "failed on net_flush()";
+ my_errno= ER_UNKNOWN_ERROR;
goto err;
}
- // we may have missed the update broadcast from the log
- // that has just happened, let's try to catch it if it did
- // if we did not miss anything, we just wait for other threads
- // to signal us
+ /*
+ We may have missed the update broadcast from the log
+ that has just happened, let's try to catch it if it did.
+ If we did not miss anything, we just wait for other threads
+ to signal us.
+ */
{
log.error=0;
bool read_packet = 0, fatal_error = 0;
@@ -425,45 +477,55 @@ impossible position";
#ifndef DBUG_OFF
if (max_binlog_dump_events && !left_events--)
{
- net_flush(net);
errmsg = "Debugging binlog dump abort";
+ my_errno= ER_UNKNOWN_ERROR;
goto err;
}
#endif
- // no one will update the log while we are reading
- // now, but we'll be quick and just read one record
+ /*
+ No one will update the log while we are reading
+ now, but we'll be quick and just read one record
+
+ TODO:
+ Add an counter that is incremented for each time we update
+ the binary log. We can avoid the following read if the counter
+ has not been updated since last read.
+ */
+
pthread_mutex_lock(log_lock);
- switch (Log_event::read_log_event(&log, packet, (pthread_mutex_t*)0))
- {
+ switch (Log_event::read_log_event(&log, packet, (pthread_mutex_t*)0)) {
case 0:
- pthread_mutex_unlock(log_lock);
+ /* we read successfully, so we'll need to send it to the slave */
+ pthread_mutex_unlock(log_lock);
read_packet = 1;
- // we read successfully, so we'll need to send it to the
- // slave
break;
+
case LOG_READ_EOF:
DBUG_PRINT("wait",("waiting for data in binary log"));
- // wait_for_update unlocks the log lock - needed to avoid race
if (!thd->killed)
+ {
+ /* Note that the following call unlocks lock_log */
mysql_bin_log.wait_for_update(thd);
+ }
else
pthread_mutex_unlock(log_lock);
DBUG_PRINT("wait",("binary log received update"));
break;
default:
- pthread_mutex_unlock(log_lock);
+ pthread_mutex_unlock(log_lock);
fatal_error = 1;
break;
}
-
+
if (read_packet)
{
thd->proc_info = "sending update to slave";
if (my_net_write(net, (char*)packet->ptr(), packet->length()) )
{
errmsg = "Failed on my_net_write()";
+ my_errno= ER_UNKNOWN_ERROR;
goto err;
}
@@ -472,18 +534,21 @@ impossible position";
if (send_file(thd))
{
errmsg = "failed in send_file()";
+ my_errno= ER_UNKNOWN_ERROR;
goto err;
}
}
- packet->length(0);
- packet->append("\0",1);
- // no need to net_flush because we will get to flush later when
- // we hit EOF pretty quick
+ packet->set("\0", 1);
+ /*
+ No need to net_flush because we will get to flush later when
+ we hit EOF pretty quick
+ */
}
if (fatal_error)
{
errmsg = "error reading log entry";
+ my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG;
goto err;
}
log.error=0;
@@ -494,7 +559,7 @@ impossible position";
bool loop_breaker = 0;
// need this to break out of the for loop from switch
thd->proc_info = "switching to next log";
- switch (mysql_bin_log.find_next_log(&linfo)) {
+ switch (mysql_bin_log.find_next_log(&linfo, 1)) {
case LOG_INFO_EOF:
loop_breaker = (flags & BINLOG_DUMP_NON_BLOCK);
break;
@@ -502,6 +567,7 @@ impossible position";
break;
default:
errmsg = "could not find next log";
+ my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG;
goto err;
}
@@ -515,8 +581,10 @@ impossible position";
// otherwise the slave make get confused about the offset
if ((file=open_binlog(&log, log_file_name, &errmsg)) < 0 ||
fake_rotate_event(net, packet, log_file_name, &errmsg))
+ {
+ my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG;
goto err;
-
+ }
packet->length(0);
packet->append("\0",1);
}
@@ -535,12 +603,14 @@ impossible position";
err:
thd->proc_info = "waiting to finalize termination";
end_io_cache(&log);
+ /*
+ Exclude iteration through thread list
+ this is needed for purge_logs() - it will iterate through
+ thread list and update thd->current_linfo->index_file_offset
+ this mutex will make sure that it never tried to update our linfo
+ after we return from this stack frame
+ */
pthread_mutex_lock(&LOCK_thread_count);
- // exclude iteration through thread list
- // this is needed for purge_logs() - it will iterate through
- // thread list and update thd->current_linfo->index_file_offset
- // this mutex will make sure that it never tried to update our linfo
- // after we return from this stack frame
thd->current_linfo = 0;
pthread_mutex_unlock(&LOCK_thread_count);
if (file >= 0)
@@ -555,16 +625,19 @@ int start_slave(THD* thd , MASTER_INFO* mi, bool net_report)
if (!thd) thd = current_thd;
NET* net = &thd->net;
int thread_mask;
+ DBUG_ENTER("start_slave");
- if (check_access(thd, PROCESS_ACL, any_db))
- return 1;
+ if (check_access(thd, SUPER_ACL, any_db))
+ DBUG_RETURN(1);
lock_slave_threads(mi); // this allows us to cleanly read slave_running
init_thread_mask(&thread_mask,mi,1 /* inverse */);
if (thd->lex.slave_thd_opt)
thread_mask &= thd->lex.slave_thd_opt;
if (thread_mask)
{
- if (server_id_supplied && (!mi->inited || (mi->inited && *mi->host)))
+ if (init_master_info(mi,master_info_file,relay_log_info_file, 0))
+ slave_errno=ER_MASTER_INFO;
+ else if (server_id_supplied && *mi->host)
slave_errno = start_slave_threads(0 /*no mutex */,
1 /* wait for start */,
mi,
@@ -582,12 +655,12 @@ int start_slave(THD* thd , MASTER_INFO* mi, bool net_report)
{
if (net_report)
send_error(net, slave_errno);
- return 1;
+ DBUG_RETURN(1);
}
else if (net_report)
send_ok(net);
- return 0;
+ DBUG_RETURN(0);
}
int stop_slave(THD* thd, MASTER_INFO* mi, bool net_report )
@@ -596,7 +669,7 @@ int stop_slave(THD* thd, MASTER_INFO* mi, bool net_report )
if (!thd) thd = current_thd;
NET* net = &thd->net;
- if (check_access(thd, PROCESS_ACL, any_db))
+ if (check_access(thd, SUPER_ACL, any_db))
return 1;
thd->proc_info = "Killing slave";
int thread_mask;
@@ -622,17 +695,20 @@ int stop_slave(THD* thd, MASTER_INFO* mi, bool net_report )
return 0;
}
-int reset_slave(MASTER_INFO* mi)
+int reset_slave(THD *thd, MASTER_INFO* mi)
{
MY_STAT stat_area;
char fname[FN_REFLEN];
int restart_thread_mask = 0,error=0;
const char* errmsg=0;
-
+ DBUG_ENTER("reset_slave");
+
lock_slave_threads(mi);
init_thread_mask(&restart_thread_mask,mi,0 /* not inverse */);
if ((error=terminate_slave_threads(mi,restart_thread_mask,1 /*skip lock*/))
- || (error=purge_relay_logs(&mi->rli,1 /*just reset*/,&errmsg)))
+ || (error=purge_relay_logs(&mi->rli, thd,
+ 1 /* just reset */,
+ &errmsg)))
goto err;
end_master_info(mi);
@@ -649,14 +725,14 @@ int reset_slave(MASTER_INFO* mi)
goto err;
}
if (restart_thread_mask)
- error=start_slave_threads(0 /* mutex not needed*/,
- 1 /* wait for start*/,
- mi,master_info_file,relay_log_info_file,
- restart_thread_mask);
+ error=start_slave_threads(0 /* mutex not needed */,
+ 1 /* wait for start*/,
+ mi,master_info_file,relay_log_info_file,
+ restart_thread_mask);
// TODO: fix error messages so they get to the client
err:
unlock_slave_threads(mi);
- return error;
+ DBUG_RETURN(error);
}
void kill_zombie_dump_threads(uint32 slave_server_id)
@@ -670,17 +746,21 @@ void kill_zombie_dump_threads(uint32 slave_server_id)
if (tmp->command == COM_BINLOG_DUMP &&
tmp->server_id == slave_server_id)
{
- /*
- Here we do not call kill_one_thread() as
- it will be slow because it will iterate through the list
- again. Plus it double-locks LOCK_tread_count, which
- make safe_mutex complain and abort.
- We just to do kill the thread ourselves.
- */
- tmp->awake(1/*prepare to die*/);
+ pthread_mutex_lock(&tmp->LOCK_delete); // Lock from delete
+ break;
}
}
pthread_mutex_unlock(&LOCK_thread_count);
+ if (tmp)
+ {
+ /*
+ Here we do not call kill_one_thread() as
+ it will be slow because it will iterate through the list
+ again. We just to do kill the thread ourselves.
+ */
+ tmp->awake(1/*prepare to die*/);
+ pthread_mutex_unlock(&tmp->LOCK_delete);
+ }
}
@@ -689,7 +769,8 @@ int change_master(THD* thd, MASTER_INFO* mi)
int error=0,restart_thread_mask;
const char* errmsg=0;
bool need_relay_log_purge=1;
-
+ DBUG_ENTER("change_master");
+
// kill slave thread
lock_slave_threads(mi);
init_thread_mask(&restart_thread_mask,mi,0 /*not inverse*/);
@@ -700,27 +781,28 @@ int change_master(THD* thd, MASTER_INFO* mi)
{
send_error(&thd->net,error);
unlock_slave_threads(mi);
- return 1;
+ DBUG_RETURN(1);
}
thd->proc_info = "changing master";
LEX_MASTER_INFO* lex_mi = &thd->lex.mi;
// TODO: see if needs re-write
- if (init_master_info(mi,master_info_file,relay_log_info_file))
+ if (init_master_info(mi, master_info_file, relay_log_info_file, 0))
{
send_error(&thd->net, 0, "Could not initialize master info");
unlock_slave_threads(mi);
- return 1;
+ DBUG_RETURN(1);
}
- /* data lock not needed since we have already stopped the running threads,
- and we have the hold on the run locks which will keep all threads that
- could possibly modify the data structures from running
+ /*
+ Data lock not needed since we have already stopped the running threads,
+ and we have the hold on the run locks which will keep all threads that
+ could possibly modify the data structures from running
*/
if ((lex_mi->host || lex_mi->port) && !lex_mi->log_file_name && !lex_mi->pos)
{
// if we change host or port, we must reset the postion
mi->master_log_name[0] = 0;
- mi->master_log_pos = 4; // skip magic number
+ mi->master_log_pos= BIN_LOG_HEADER_SIZE;
mi->rli.pending = 0;
}
@@ -729,9 +811,10 @@ int change_master(THD* thd, MASTER_INFO* mi)
sizeof(mi->master_log_name));
if (lex_mi->pos)
{
- mi->master_log_pos = lex_mi->pos;
+ mi->master_log_pos= lex_mi->pos;
mi->rli.pending = 0;
}
+ DBUG_PRINT("info", ("master_log_pos: %d", (ulong) mi->master_log_pos));
if (lex_mi->host)
strmake(mi->host, lex_mi->host, sizeof(mi->host));
@@ -748,7 +831,7 @@ int change_master(THD* thd, MASTER_INFO* mi)
{
need_relay_log_purge = 0;
mi->rli.skip_log_purge=1;
- strnmov(mi->rli.relay_log_name,lex_mi->relay_log_name,
+ strmake(mi->rli.relay_log_name,lex_mi->relay_log_name,
sizeof(mi->rli.relay_log_name)-1);
}
@@ -763,36 +846,38 @@ int change_master(THD* thd, MASTER_INFO* mi)
{
mi->rli.skip_log_purge=0;
thd->proc_info="purging old relay logs";
- if (purge_relay_logs(&mi->rli,0 /* not only reset, but also reinit*/,
+ if (purge_relay_logs(&mi->rli, thd,
+ 0 /* not only reset, but also reinit */,
&errmsg))
{
net_printf(&thd->net, 0, "Failed purging old relay logs: %s",errmsg);
- return 1;
+ DBUG_RETURN(1);
}
}
else
{
const char* msg;
- if (init_relay_log_pos(&mi->rli,0/*log already inited*/,
- 0 /*pos already inited*/,
+ /* Relay log is already initialized */
+ if (init_relay_log_pos(&mi->rli,
+ mi->rli.relay_log_name,
+ mi->rli.relay_log_pos,
0 /*no data lock*/,
&msg))
{
- //Sasha: note that I had to change net_printf() to make this work
net_printf(&thd->net,0,"Failed initializing relay log position: %s",msg);
unlock_slave_threads(mi);
- return 1;
+ DBUG_RETURN(1);
}
-
}
mi->rli.master_log_pos = mi->master_log_pos;
- strnmov(mi->rli.master_log_name,mi->master_log_name,
- sizeof(mi->rli.master_log_name));
+ DBUG_PRINT("info", ("master_log_pos: %d", (ulong) mi->master_log_pos));
+ strmake(mi->rli.master_log_name,mi->master_log_name,
+ sizeof(mi->rli.master_log_name)-1);
if (!mi->rli.master_log_name[0]) // uninitialized case
mi->rli.master_log_pos=0;
pthread_mutex_lock(&mi->rli.data_lock);
- mi->rli.abort_pos_wait = 1;
+ mi->rli.abort_pos_wait++;
pthread_cond_broadcast(&mi->data_cond);
pthread_mutex_unlock(&mi->rli.data_lock);
@@ -808,7 +893,7 @@ int change_master(THD* thd, MASTER_INFO* mi)
send_error(&thd->net,error);
else
send_ok(&thd->net);
- return 0;
+ DBUG_RETURN(0);
}
int reset_master(THD* thd)
@@ -848,26 +933,28 @@ int show_binlog_events(THD* thd)
if (mysql_bin_log.is_open())
{
- LOG_INFO linfo;
- char search_file_name[FN_REFLEN];
- LEX_MASTER_INFO* lex_mi = &thd->lex.mi;
+ LEX_MASTER_INFO *lex_mi = &thd->lex.mi;
uint event_count, limit_start, limit_end;
- const char* log_file_name = lex_mi->log_file_name;
- Log_event* ev;
my_off_t pos = lex_mi->pos;
-
+ char search_file_name[FN_REFLEN], *name;
+ const char *log_file_name = lex_mi->log_file_name;
+ pthread_mutex_t *log_lock = mysql_bin_log.get_log_lock();
+ LOG_INFO linfo;
+ Log_event* ev;
+
limit_start = thd->lex.select->offset_limit;
limit_end = thd->lex.select->select_limit + limit_start;
+ name= search_file_name;
if (log_file_name)
mysql_bin_log.make_log_name(search_file_name, log_file_name);
else
- search_file_name[0] = 0;
+ name=0; // Find first log
linfo.index_file_offset = 0;
thd->current_linfo = &linfo;
- if (mysql_bin_log.find_first_log(&linfo, search_file_name))
+ if (mysql_bin_log.find_log_pos(&linfo, name, 1))
{
errmsg = "Could not find target log";
goto err;
@@ -882,7 +969,7 @@ int show_binlog_events(THD* thd)
goto err;
}
- pthread_mutex_lock(mysql_bin_log.get_log_lock());
+ pthread_mutex_lock(log_lock);
my_b_seek(&log, pos);
for (event_count = 0;
@@ -893,7 +980,7 @@ int show_binlog_events(THD* thd)
{
errmsg = "Net error";
delete ev;
- pthread_mutex_unlock(mysql_bin_log.get_log_lock());
+ pthread_mutex_unlock(log_lock);
goto err;
}
@@ -907,11 +994,11 @@ int show_binlog_events(THD* thd)
if (event_count < limit_end && log.error)
{
errmsg = "Wrong offset or I/O error";
- pthread_mutex_unlock(mysql_bin_log.get_log_lock());
+ pthread_mutex_unlock(log_lock);
goto err;
}
- pthread_mutex_unlock(mysql_bin_log.get_log_lock());
+ pthread_mutex_unlock(log_lock);
}
err:
@@ -955,88 +1042,73 @@ int show_binlog_info(THD* thd)
net_store_data(packet, (longlong)li.pos);
net_store_data(packet, &binlog_do_db);
net_store_data(packet, &binlog_ignore_db);
+ if (my_net_write(&thd->net, (char*)thd->packet.ptr(), packet->length()))
+ DBUG_RETURN(-1);
}
- else
- {
- net_store_null(packet);
- net_store_null(packet);
- net_store_null(packet);
- net_store_null(packet);
- }
-
- if (my_net_write(&thd->net, (char*)thd->packet.ptr(), packet->length()))
- DBUG_RETURN(-1);
-
send_eof(&thd->net);
DBUG_RETURN(0);
}
+/*
+ Send a lost of all binary logs to client
+
+ SYNOPSIS
+ show_binlogs()
+ thd Thread specific variable
+
+ RETURN VALUES
+ 0 ok
+ 1 error (Error message sent to client)
+*/
+
int show_binlogs(THD* thd)
{
- const char* errmsg = 0;
- File index_file;
+ const char *errmsg;
+ IO_CACHE *index_file;
char fname[FN_REFLEN];
NET* net = &thd->net;
List<Item> field_list;
- String* packet = &thd->packet;
- IO_CACHE io_cache;
+ String *packet = &thd->packet;
uint length;
if (!mysql_bin_log.is_open())
{
- errmsg = "binlog is not open";
- goto err;
+ //TODO: Replace with ER() error message
+ errmsg= "You are not using binary logging";
+ goto err_with_msg;
}
- field_list.push_back(new Item_empty_string("Log_name", 128));
+ field_list.push_back(new Item_empty_string("Log_name", 255));
if (send_fields(thd, field_list, 1))
- {
- sql_print_error("Failed in send_fields");
return 1;
- }
-
mysql_bin_log.lock_index();
- index_file = mysql_bin_log.get_index_file();
- if (index_file < 0)
- {
- errmsg = "Uninitialized index file pointer";
- goto err2;
- }
- if (init_io_cache(&io_cache, index_file, IO_SIZE, READ_CACHE, 0, 0,
- MYF(MY_WME)))
- {
- errmsg = "Failed on init_io_cache()";
- goto err2;
- }
- while ((length=my_b_gets(&io_cache, fname, sizeof(fname))))
+ index_file=mysql_bin_log.get_index_file();
+
+ reinit_io_cache(index_file, READ_CACHE, (my_off_t) 0, 0, 0);
+
+ /* The file ends with EOF or empty line */
+ while ((length=my_b_gets(index_file, fname, sizeof(fname))) > 1)
{
- fname[--length]=0;
int dir_len = dirname_length(fname);
packet->length(0);
- net_store_data(packet, fname + dir_len, length-dir_len);
+ /* The -1 is for removing newline from fname */
+ net_store_data(packet, fname + dir_len, length-1-dir_len);
if (my_net_write(net, (char*) packet->ptr(), packet->length()))
- {
- sql_print_error("Failed in my_net_write");
- end_io_cache(&io_cache);
- mysql_bin_log.unlock_index();
- return 1;
- }
+ goto err;
}
-
mysql_bin_log.unlock_index();
- end_io_cache(&io_cache);
send_eof(net);
return 0;
-err2:
- mysql_bin_log.unlock_index();
- end_io_cache(&io_cache);
-err:
+err_with_msg:
send_error(net, 0, errmsg);
+err:
+ mysql_bin_log.unlock_index();
return 1;
}
+
int log_loaded_block(IO_CACHE* file)
{
LOAD_FILE_INFO* lf_info;
diff --git a/sql/sql_repl.h b/sql/sql_repl.h
index b15c72a0bde..1d919df7309 100644
--- a/sql/sql_repl.h
+++ b/sql/sql_repl.h
@@ -1,6 +1,3 @@
-#ifndef SQL_REPL_H
-#define SQL_REPL_H
-
#include "slave.h"
typedef struct st_slave_info
@@ -14,20 +11,19 @@ typedef struct st_slave_info
THD* thd;
} SLAVE_INFO;
-extern bool opt_show_slave_auth_info, opt_old_rpl_compat;
+extern my_bool opt_show_slave_auth_info, opt_old_rpl_compat;
extern char* master_host;
extern my_string opt_bin_logname, master_info_file;
-extern uint32 server_id;
extern bool server_id_supplied;
extern I_List<i_string> binlog_do_db, binlog_ignore_db;
extern int max_binlog_dump_events;
-extern bool opt_sporadic_binlog_dump_fail;
+extern my_bool opt_sporadic_binlog_dump_fail;
-#define KICK_SLAVE(thd) thd->awake(0 /* do not prepare to die*/);
+#define KICK_SLAVE(thd) { pthread_mutex_lock(&(thd)->LOCK_delete); (thd)->awake(0 /* do not prepare to die*/); pthread_mutex_unlock(&(thd)->LOCK_delete); }
File open_binlog(IO_CACHE *log, const char *log_file_name,
- const char **errmsg);
+ const char **errmsg);
int start_slave(THD* thd, MASTER_INFO* mi, bool net_report);
int stop_slave(THD* thd, MASTER_INFO* mi, bool net_report);
@@ -35,7 +31,7 @@ int change_master(THD* thd, MASTER_INFO* mi);
int show_binlog_events(THD* thd);
int cmp_master_pos(const char* log_file_name1, ulonglong log_pos1,
const char* log_file_name2, ulonglong log_pos2);
-int reset_slave(MASTER_INFO* mi);
+int reset_slave(THD *thd, MASTER_INFO* mi);
int reset_master(THD* thd);
int purge_master_logs(THD* thd, const char* to_log);
bool log_in_use(const char* log_name);
@@ -58,6 +54,3 @@ typedef struct st_load_file_info
} LOAD_FILE_INFO;
int log_loaded_block(IO_CACHE* file);
-
-#endif
-
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 4e7dbd96127..8a64fbf968c 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -62,7 +62,7 @@ static void update_depend_map(JOIN *join);
static void update_depend_map(JOIN *join, ORDER *order);
static ORDER *remove_const(JOIN *join,ORDER *first_order,COND *cond,
bool *simple_order);
-static int return_zero_rows(select_result *res,TABLE_LIST *tables,
+static int return_zero_rows(JOIN *join, select_result *res,TABLE_LIST *tables,
List<Item> &fields, bool send_row,
uint select_options, const char *info,
Item *having, Procedure *proc,
@@ -144,7 +144,7 @@ static void init_sum_functions(Item_sum **func);
static bool update_sum_func(Item_sum **func);
static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
bool distinct, const char *message=NullS);
-static void describe_info(THD *thd, const char *info);
+static void describe_info(JOIN *join, const char *info);
/*
This handles SELECT with and without UNION
@@ -164,9 +164,35 @@ int handle_select(THD *thd, LEX *lex, select_result *result)
for (TABLE_LIST *cursor= (TABLE_LIST *)sl->table_list.first;
cursor;
cursor=cursor->next)
- cursor->table= cursor->table_list->table;
+ {
+ if (cursor->do_redirect) // False if CUBE/ROLLUP
+ {
+ cursor->do_redirect=false;
+ cursor->table= ((TABLE_LIST*) cursor->table)->table;
+ }
+ }
}
}
+
+#ifdef DISABLED_UNTIL_REWRITTEN_IN_4_1
+ if (lex->olap)
+ {
+ SELECT_LEX *sl, *sl_next;
+ int error;
+ for (sl= &select_lex; sl; sl=sl_next)
+ {
+ sl_next=sl->next; // Save if sl->next changes
+ if (sl->olap != UNSPECIFIED_OLAP_TYPE)
+ {
+ if ((error=handle_olaps(lex,sl)))
+ return error;
+ lex->last_selects->next=sl_next;
+ }
+ }
+ lex->select = select_lex;
+ }
+#endif /* DISABLED_UNTIL_REWRITTEN_IN_4_1 */
+
if (select_lex->next_select())
res=mysql_union(thd,lex,result);
else
@@ -187,8 +213,8 @@ int handle_select(THD *thd, LEX *lex, select_result *result)
/*****************************************************************************
-** check fields, find best join, do the select and output fields.
-** mysql_select assumes that all tables are already opened
+ Check fields, find best join, do the select and output fields.
+ mysql_select assumes that all tables are already opened
*****************************************************************************/
/*
@@ -198,9 +224,10 @@ int handle_select(THD *thd, LEX *lex, select_result *result)
*/
int
JOIN::prepare(TABLE_LIST *tables_init,
- COND *conds_init, ORDER *order_init, ORDER *group_init,
- Item *having_init,
- ORDER *proc_param_init, SELECT_LEX *select, SELECT_LEX_UNIT *unit)
+ COND *conds_init, ORDER *order_init, ORDER *group_init,
+ Item *having_init,
+ ORDER *proc_param_init, SELECT_LEX *select_lex,
+ SELECT_LEX_UNIT *unit)
{
DBUG_ENTER("JOIN::prepare");
@@ -210,7 +237,6 @@ JOIN::prepare(TABLE_LIST *tables_init,
having= having_init;
proc_param= proc_param_init;
tables_list= tables_init;
- select_lex= select;
select->join= this;
union_part= (unit->first_select()->next_select() != 0);
@@ -243,7 +269,7 @@ JOIN::prepare(TABLE_LIST *tables_init,
and no GROUP BY.
TODO: Add check of calculation of GROUP functions and fields:
SELECT COUNT(*)+table.col1 from table1;
- */
+ */
{
if (!group_list)
{
@@ -382,11 +408,7 @@ JOIN::optimize()
}
if (select_options & SELECT_DESCRIBE)
{
- if (union_part)
- select_describe(this, false, false, false,
- "Select tables optimized away");
- else
- describe_info(thd, "Select tables optimized away");
+ describe_info(this, "Select tables optimized away");
delete procedure;
DBUG_RETURN(1);
}
@@ -429,7 +451,7 @@ JOIN::optimize()
DBUG_RETURN(0);
}
if (!(thd->options & OPTION_BIG_SELECTS) &&
- best_read > (double) thd->max_join_size &&
+ best_read > (double) thd->variables.max_join_size &&
!(select_options & SELECT_DESCRIBE))
{ /* purecov: inspected */
result->send_error(ER_TOO_BIG_SELECT,ER(ER_TOO_BIG_SELECT)); /* purecov: inspected */
@@ -530,9 +552,19 @@ JOIN::optimize()
simple_order=0;
}
+ /*
+ Check if we need to create a temporary table.
+ This has to be done if all tables are not already read (const tables)
+ and one of the following conditions holds:
+ - We are using DISTINCT (simple distinct's are already optimized away)
+ - We are using an ORDER BY or GROUP BY on fields not in the first table
+ - We are using different ORDER BY and GROUP BY orders
+ - The user wants us to buffer the result.
+ */
need_tmp= (const_tables != tables &&
((select_distinct || !simple_order || !simple_group) ||
- (group_list && order) || buffer_result));
+ (group_list && order) ||
+ test(select_options & OPTION_BUFFER_RESULT)));
// No cache for MATCH
make_join_readinfo(this,
@@ -541,11 +573,13 @@ JOIN::optimize()
(thd->lex.select->ftfunc_list.elements ?
SELECT_NO_JOIN_CACHE : 0));
- /* Need to tell Innobase that to play it safe, it should fetch all
- columns of the tables: this is because MySQL
- may build row pointers for the rows, and for all columns of the primary
- key the field->query_id has not necessarily been set to thd->query_id
- by MySQL. */
+ /*
+ Need to tell Innobase that to play it safe, it should fetch all
+ columns of the tables: this is because MySQL may build row
+ pointers for the rows, and for all columns of the primary key the
+ field->query_id has not necessarily been set to thd->query_id by
+ MySQL.
+ */
#ifdef HAVE_INNOBASE_DB
if (need_tmp || select_distinct || group_list || order)
@@ -639,12 +673,7 @@ JOIN::exec()
{ // Only test of functions
error=0;
if (select_options & SELECT_DESCRIBE)
- {
- if (union_part)
- select_describe(this, false, false, false, "No tables used");
- else
- describe_info(thd, "No tables used");
- }
+ describe_info(this, "No tables used");
else
{
result->send_fields(fields_list,1);
@@ -667,16 +696,13 @@ JOIN::exec()
if (zero_result_cause)
{
- if (select_options & SELECT_DESCRIBE && union_part)
- select_describe(this, false, false, false, zero_result_cause);
- else
- error=return_zero_rows(result, tables_list, fields_list,
- tmp_table_param.sum_func_count != 0 &&
- !group_list,
- select_options,
- zero_result_cause,
- having,procedure,
- unit);
+ (void) return_zero_rows(this, result, tables_list, fields_list,
+ tmp_table_param.sum_func_count != 0 &&
+ !group_list,
+ select_options,
+ zero_result_cause,
+ having,procedure,
+ unit);
DBUG_VOID_RETURN;
}
@@ -712,6 +738,8 @@ JOIN::exec()
DBUG_PRINT("info",("Creating tmp table"));
thd->proc_info="Creating tmp table";
+ tmp_table_param.hidden_field_count= (all_fields.elements-
+ fields.elements);
if (!(exec_tmp_table =
create_tmp_table(thd, &tmp_table_param, all_fields,
((!simple_group && !procedure &&
@@ -816,11 +844,11 @@ JOIN::exec()
}
/*
- ** If we have different sort & group then we must sort the data by group
- ** and copy it to another tmp table
- ** This code is also used if we are using distinct something
- ** we haven't been able to store in the temporary table yet
- ** like SEC_TO_TIME(SUM(...)).
+ If we have different sort & group then we must sort the data by group
+ and copy it to another tmp table
+ This code is also used if we are using distinct something
+ we haven't been able to store in the temporary table yet
+ like SEC_TO_TIME(SUM(...)).
*/
if (group_list && (!test_if_subpart(group_list,order) ||
@@ -1009,8 +1037,7 @@ mysql_select(THD *thd, TABLE_LIST *tables, List<Item> &fields, COND *conds,
{
DBUG_RETURN(-1);
}
- switch(join->optimize())
- {
+ switch (join->optimize()) {
case 1:
DBUG_RETURN(join->error);
case -1:
@@ -1032,8 +1059,8 @@ err:
}
/*****************************************************************************
-** Create JOIN_TABS, make a guess about the table types,
-** Approximate how many records will be used in each table
+ Create JOIN_TABS, make a guess about the table types,
+ Approximate how many records will be used in each table
*****************************************************************************/
static ha_rows get_quick_record_count(SQL_SELECT *select,TABLE *table,
@@ -1353,11 +1380,11 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
/*****************************************************************************
-** check with keys are used and with tables references with tables
-** updates in stat:
-** keys Bitmap of all used keys
-** const_keys Bitmap of all keys with may be used with quick_select
-** keyuse Pointer to possible keys
+ Check with keys are used and with tables references with tables
+ Updates in stat:
+ keys Bitmap of all used keys
+ const_keys Bitmap of all keys with may be used with quick_select
+ keyuse Pointer to possible keys
*****************************************************************************/
typedef struct key_field_t { // Used when finding key fields
@@ -1589,8 +1616,8 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level,
}
/*
-** Add all keys with uses 'field' for some keypart
-** If field->and_level != and_level then only mark key_part as const_part
+ Add all keys with uses 'field' for some keypart
+ If field->and_level != and_level then only mark key_part as const_part
*/
static uint
@@ -1725,9 +1752,9 @@ sort_keyuse(KEYUSE *a,KEYUSE *b)
/*
-** Update keyuse array with all possible keys we can use to fetch rows
-** join_tab is a array in tablenr_order
-** stat is a reference array in 'prefered' order.
+ Update keyuse array with all possible keys we can use to fetch rows
+ join_tab is a array in tablenr_order
+ stat is a reference array in 'prefered' order.
*/
static bool
@@ -1766,9 +1793,9 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
}
/*
- ** remove ref if there is a keypart which is a ref and a const.
- ** remove keyparts without previous keyparts.
- ** Special treatment for ft-keys.
+ Remove ref if there is a keypart which is a ref and a const.
+ Remove keyparts without previous keyparts.
+ Special treatment for ft-keys.
*/
if (keyuse->elements)
{
@@ -1818,8 +1845,8 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
/*****************************************************************************
-** Go through all combinations of not marked tables and find the one
-** which uses least records
+ Go through all combinations of not marked tables and find the one
+ which uses least records
*****************************************************************************/
/* Save const tables first as used tables */
@@ -1834,7 +1861,7 @@ set_position(JOIN *join,uint idx,JOIN_TAB *table,KEYUSE *key)
/* Move the const table as down as possible in best_ref */
JOIN_TAB **pos=join->best_ref+idx+1;
JOIN_TAB *next=join->best_ref[idx];
- for ( ;next != table ; pos++)
+ for (;next != table ; pos++)
{
JOIN_TAB *tmp=pos[0];
pos[0]=next;
@@ -1860,6 +1887,7 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
{
ulong rec;
double tmp;
+ THD *thd= join->thd;
if (!rest_tables)
{
@@ -1925,12 +1953,12 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
found_ref|= keyuse->used_tables;
}
/*
- ** If we find a ref, assume this table matches a proportional
- ** part of this table.
- ** For example 100 records matching a table with 5000 records
- ** gives 5000/100 = 50 records per key
- ** Constant tables are ignored and to avoid bad matches,
- ** we don't make rec less than 100.
+ If we find a ref, assume this table matches a proportional
+ part of this table.
+ For example 100 records matching a table with 5000 records
+ gives 5000/100 = 50 records per key
+ Constant tables are ignored and to avoid bad matches,
+ we don't make rec less than 100.
*/
if (keyuse->used_tables &
(map=(keyuse->used_tables & ~join->const_table_map)))
@@ -1951,7 +1979,7 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
} while (keyuse->table == table && keyuse->key == key);
/*
- ** Assume that that each key matches a proportional part of table.
+ Assume that that each key matches a proportional part of table.
*/
if (!found_part && !ft_key)
continue; // Nothing usable found
@@ -1959,13 +1987,13 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
rec=1L; // Fix for small tables
/*
- ** ft-keys require special treatment
+ ft-keys require special treatment
*/
if (ft_key)
{
/*
- ** Really, there should be records=0.0 (yes!)
- ** but 1.0 would be probably safer
+ Really, there should be records=0.0 (yes!)
+ but 1.0 would be probably safer
*/
tmp=prev_record_reads(join,found_ref);
records=1.0;
@@ -1973,7 +2001,7 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
else
{
/*
- ** Check if we found full key
+ Check if we found full key
*/
if (found_part == PREV_BITS(uint,keyinfo->key_parts))
{ /* use eq key */
@@ -2020,17 +2048,18 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
else
{
/*
- ** Use as much key-parts as possible and a uniq key is better
- ** than a not unique key
- ** Set tmp to (previous record count) * (records / combination)
+ Use as much key-parts as possible and a uniq key is better
+ than a not unique key
+ Set tmp to (previous record count) * (records / combination)
*/
if ((found_part & 1) &&
!(table->file->index_flags(key) & HA_ONLY_WHOLE_INDEX))
{
max_key_part=max_part_bit(found_part);
- /* Check if quick_range could determinate how many rows we
- will match */
-
+ /*
+ Check if quick_range could determinate how many rows we
+ will match
+ */
if (table->quick_keys & ((key_map) 1 << key) &&
table->quick_key_parts[key] <= max_key_part)
tmp=records= (double) table->quick_rows[key];
@@ -2042,18 +2071,18 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
else
{
/*
- ** Assume that the first key part matches 1% of the file
- ** and that the hole key matches 10 (dupplicates) or 1
- ** (unique) records.
- ** Assume also that more key matches proportionally more
- ** 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
- ** x = used key parts (1 <= x <= c)
+ Assume that the first key part matches 1% of the file
+ and that the hole key matches 10 (dupplicates) or 1
+ (unique) records.
+ Assume also that more key matches proportionally more
+ 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
+ x = used key parts (1 <= x <= c)
*/
double rec_per_key;
if (!(rec_per_key=(double)
@@ -2125,7 +2154,8 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
tmp=(double) s->read_time;
/* Calculate time to read through cache */
tmp*=(1.0+floor((double) cache_record_length(join,idx)*
- record_count/(double) join_buff_size));
+ record_count /
+ (double) thd->variables.join_buff_size));
}
if (best == DBL_MAX ||
(tmp + record_count/(double) TIME_FOR_COMPARE*s->found_records <
@@ -2177,7 +2207,7 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
/*
-** Find how much space the prevous read not const tables takes in cache
+ Find how much space the prevous read not const tables takes in cache
*/
static void calc_used_field_length(THD *thd, JOIN_TAB *join_tab)
@@ -2253,7 +2283,7 @@ prev_record_reads(JOIN *join,table_map found_ref)
/*****************************************************************************
-** Set up join struct according to best position.
+ Set up join struct according to best position.
*****************************************************************************/
static bool
@@ -2319,7 +2349,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse,
KEY *keyinfo;
/*
- ** Use best key from find_best
+ Use best key from find_best
*/
table=j->table;
key=keyuse->key;
@@ -2468,8 +2498,8 @@ get_store_key(THD *thd, KEYUSE *keyuse, table_map used_tables,
}
/*
-** This function is only called for const items on fields which are keys
-** returns 1 if there was some conversion made when the field was stored.
+ This function is only called for const items on fields which are keys
+ returns 1 if there was some conversion made when the field was stored.
*/
bool
@@ -2747,7 +2777,7 @@ make_join_readinfo(JOIN *join, uint options)
break;
case JT_ALL:
/*
- ** if previous table use cache
+ If previous table use cache
*/
table->status=STATUS_NO_RECORD;
if (i != join->const_tables && !(options & SELECT_NO_JOIN_CACHE) &&
@@ -2861,8 +2891,10 @@ join_free(JOIN *join)
if (!join->select_lex->depended)
join->table=0;
}
- // We are not using tables anymore
- // Unlock all tables. We may be in an INSERT .... SELECT statement.
+ /*
+ We are not using tables anymore
+ Unlock all tables. We may be in an INSERT .... SELECT statement.
+ */
if (join->lock && join->thd->lock &&
!(join->select_options & SELECT_NO_UNLOCK))
{
@@ -2879,19 +2911,19 @@ join_free(JOIN *join)
/*****************************************************************************
-** Remove the following expressions from ORDER BY and GROUP BY:
-** Constant expressions
-** Expression that only uses tables that are of type EQ_REF and the reference
-** is in the ORDER list or if all refereed tables are of the above type.
-**
-** In the following, the X field can be removed:
-** SELECT * FROM t1,t2 WHERE t1.a=t2.a ORDER BY t1.a,t2.X
-** SELECT * FROM t1,t2,t3 WHERE t1.a=t2.a AND t2.b=t3.b ORDER BY t1.a,t3.X
-**
-** These can't be optimized:
-** SELECT * FROM t1,t2 WHERE t1.a=t2.a ORDER BY t2.X,t1.a
-** SELECT * FROM t1,t2 WHERE t1.a=t2.a AND t1.b=t2.b ORDER BY t1.a,t2.c
-** SELECT * FROM t1,t2 WHERE t1.a=t2.a ORDER BY t2.b,t1.a
+ Remove the following expressions from ORDER BY and GROUP BY:
+ Constant expressions
+ Expression that only uses tables that are of type EQ_REF and the reference
+ is in the ORDER list or if all refereed tables are of the above type.
+
+ In the following, the X field can be removed:
+ SELECT * FROM t1,t2 WHERE t1.a=t2.a ORDER BY t1.a,t2.X
+ SELECT * FROM t1,t2,t3 WHERE t1.a=t2.a AND t2.b=t3.b ORDER BY t1.a,t3.X
+
+ These can't be optimized:
+ SELECT * FROM t1,t2 WHERE t1.a=t2.a ORDER BY t2.X,t1.a
+ SELECT * FROM t1,t2 WHERE t1.a=t2.a AND t1.b=t2.b ORDER BY t1.a,t2.c
+ SELECT * FROM t1,t2 WHERE t1.a=t2.a ORDER BY t2.b,t1.a
*****************************************************************************/
static bool
@@ -2931,7 +2963,7 @@ eq_ref_table(JOIN *join, ORDER *start_order, JOIN_TAB *tab)
}
}
/* Check that there was no reference to table before sort order */
- for ( ; found && start_order ; start_order=start_order->next)
+ for (; found && start_order ; start_order=start_order->next)
{
if (start_order->used & map)
{
@@ -2949,7 +2981,7 @@ static bool
only_eq_ref_tables(JOIN *join,ORDER *order,table_map tables)
{
if (specialflag & SPECIAL_SAFE_MODE)
- return 0; // skip this optimize /* purecov: inspected */
+ return 0; // skip this optimize /* purecov: inspected */
for (JOIN_TAB **tab=join->map2table ; tables ; tab++, tables>>=1)
{
if (tables & 1 && !eq_ref_table(join, order, *tab))
@@ -2965,7 +2997,7 @@ static void update_depend_map(JOIN *join)
{
JOIN_TAB *join_tab=join->join_tab, *end=join_tab+join->tables;
- for ( ; join_tab != end ; join_tab++)
+ for (; join_tab != end ; join_tab++)
{
TABLE_REF *ref= &join_tab->ref;
table_map depend_map=0;
@@ -2989,7 +3021,7 @@ static void update_depend_map(JOIN *join)
static void update_depend_map(JOIN *join, ORDER *order)
{
- for ( ; order ; order=order->next)
+ for (; order ; order=order->next)
{
table_map depend_map;
order->item[0]->update_used_tables();
@@ -3072,16 +3104,18 @@ remove_const(JOIN *join,ORDER *first_order, COND *cond, bool *simple_order)
DBUG_RETURN(first_order);
}
+
static int
-return_zero_rows(select_result *result,TABLE_LIST *tables,List<Item> &fields,
- bool send_row, uint select_options,const char *info,
- Item *having, Procedure *procedure, SELECT_LEX_UNIT *unit)
+return_zero_rows(JOIN *join, select_result *result,TABLE_LIST *tables,
+ List<Item> &fields, bool send_row, uint select_options,
+ const char *info, Item *having, Procedure *procedure,
+ SELECT_LEX_UNIT *unit)
{
DBUG_ENTER("return_zero_rows");
if (select_options & SELECT_DESCRIBE)
{
- describe_info(current_thd, info);
+ describe_info(join, info);
DBUG_RETURN(0);
}
if (procedure)
@@ -3119,12 +3153,12 @@ static void clear_tables(JOIN *join)
}
/*****************************************************************************
-** Make som simple condition optimization:
-** If there is a test 'field = const' change all refs to 'field' to 'const'
-** Remove all dummy tests 'item = item', 'const op const'.
-** Remove all 'item is NULL', when item can never be null!
-** item->marker should be 0 for all items on entry
-** Return in cond_value FALSE if condition is impossible (1 = 2)
+ Make som simple condition optimization:
+ If there is a test 'field = const' change all refs to 'field' to 'const'
+ Remove all dummy tests 'item = item', 'const op const'.
+ Remove all 'item is NULL', when item can never be null!
+ item->marker should be 0 for all items on entry
+ Return in cond_value FALSE if condition is impossible (1 = 2)
*****************************************************************************/
class COND_CMP :public ilink {
@@ -3146,8 +3180,8 @@ template class List_iterator<Item_func_match>;
#endif
/*
-** change field = field to field = const for each found field = const in the
-** and_level
+ change field = field to field = const for each found field = const in the
+ and_level
*/
static void
@@ -3292,8 +3326,8 @@ optimize_cond(COND *conds,Item::cond_result *cond_value)
DBUG_EXECUTE("where",print_where(conds,"original"););
propagate_cond_constants((I_List<COND_CMP> *) 0,conds,conds);
/*
- ** Remove all instances of item == item
- ** Remove all and-levels where CONST item != CONST item
+ Remove all instances of item == item
+ Remove all and-levels where CONST item != CONST item
*/
DBUG_EXECUTE("where",print_where(conds,"after const change"););
conds=remove_eq_conds(conds,cond_value) ;
@@ -3303,11 +3337,11 @@ optimize_cond(COND *conds,Item::cond_result *cond_value)
/*
-** remove const and eq items. Return new item, or NULL if no condition
-** cond_value is set to according:
-** COND_OK query is possible (field = constant)
-** COND_TRUE always true ( 1 = 1 )
-** COND_FALSE always false ( 1 = 2 )
+ Remove const and eq items. Return new item, or NULL if no condition
+ cond_value is set to according:
+ COND_OK query is possible (field = constant)
+ COND_TRUE always true ( 1 = 1 )
+ COND_FALSE always false ( 1 = 2 )
*/
static COND *
@@ -3445,7 +3479,7 @@ remove_eq_conds(COND *cond,Item::cond_result *cond_value)
}
/*
-** Return 1 if the item is a const value in all the WHERE clause
+ Return 1 if the item is a const value in all the WHERE clause
*/
static bool
@@ -3504,10 +3538,10 @@ const_expression_in_where(COND *cond, Item *comp_item, Item **const_item)
/****************************************************************************
-** Create a temp table according to a field list.
-** Set distinct if duplicates could be removed
-** Given fields field pointers are changed to point at tmp_table
-** for send_fields
+ Create a temp table according to a field list.
+ Set distinct if duplicates could be removed
+ Given fields field pointers are changed to point at tmp_table
+ for send_fields
****************************************************************************/
Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
@@ -3803,7 +3837,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
field_count= (uint) (reg_field - table->field);
/* If result table is small; use a heap */
- if (blob_count || using_unique_constraint ||
+ if (blob_count || using_unique_constraint || group_null_items ||
(select_options & (OPTION_BIG_TABLES | SELECT_SMALL_RESULT)) ==
OPTION_BIG_TABLES)
{
@@ -3825,7 +3859,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
if (blob_count == 0)
{
/* We need to ensure that first byte is not 0 for the delete link */
- if (hidden_null_count)
+ if (param->hidden_field_count)
hidden_null_count++;
else
null_count++;
@@ -3920,12 +3954,13 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
param->recinfo=recinfo;
store_record(table,2); // Make empty default record
- if (tmp_table_size == ~(ulong) 0) // No limit
+ if (thd->variables.tmp_table_size == ~(ulong) 0) // No limit
table->max_rows= ~(ha_rows) 0;
else
table->max_rows=(((table->db_type == DB_TYPE_HEAP) ?
- min(tmp_table_size, max_heap_table_size) :
- tmp_table_size)/ table->reclength);
+ min(thd->variables.tmp_table_size,
+ thd->variables.max_heap_table_size) :
+ thd->variables.tmp_table_size)/ table->reclength);
set_if_bigger(table->max_rows,1); // For dummy start options
keyinfo=param->keyinfo;
@@ -3973,7 +4008,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
key_part_info->null_offset= (uint) (field->null_ptr -
(uchar*) table->record[0]);
group->field->move_field((char*) ++group->buff);
- ++group_buff;
+ group_buff++;
}
else
group->field->move_field((char*) group_buff);
@@ -3991,6 +4026,8 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
'param->hidden_field_count' extra columns, whose null bits are stored
in the first 'hidden_null_pack_length' bytes of the row.
*/
+ DBUG_PRINT("info",("hidden_field_count: %d", param->hidden_field_count));
+
null_pack_length-=hidden_null_pack_length;
keyinfo->key_parts= ((field_count-param->hidden_field_count)+
test(null_pack_length));
@@ -4013,7 +4050,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
goto err;
table->key_info=keyinfo;
keyinfo->key_part=key_part_info;
- keyinfo->flags=HA_NOSAME;
+ keyinfo->flags=HA_NOSAME | HA_NULL_ARE_EQUAL;
keyinfo->key_length=(uint16) reclength;
keyinfo->name=(char*) "tmp";
if (null_pack_length)
@@ -4320,7 +4357,7 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
join->procedure=procedure;
/*
- ** Tell the client how many fields there are in a row
+ Tell the client how many fields there are in a row
*/
if (!table)
join->result->send_fields(*fields,1);
@@ -4405,7 +4442,7 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
}
if (table)
{
- int old_error=error,tmp;
+ int tmp;
if ((tmp=table->file->extra(HA_EXTRA_NO_CACHE)))
{
my_errno=tmp;
@@ -4582,10 +4619,9 @@ flush_cached_records(JOIN *join,JOIN_TAB *join_tab,bool skipp_last)
/*****************************************************************************
-** The different ways to read a record
-** Returns -1 if row was not found, 0 if row was found and 1 on errors
+ The different ways to read a record
+ Returns -1 if row was not found, 0 if row was found and 1 on errors
*****************************************************************************/
-
static int
join_read_const_table(JOIN_TAB *tab, POSITION *pos)
{
@@ -4929,7 +4965,8 @@ join_read_last(JOIN_TAB *tab)
{
TABLE *table=tab->table;
int error;
- if (!table->key_read && (table->used_keys & ((key_map) 1 << tab->index)))
+ if (!table->key_read && (table->used_keys & ((key_map) 1 << tab->index)) &&
+ !table->no_keyread)
{
table->key_read=1;
table->file->extra(HA_EXTRA_KEYREAD);
@@ -5022,12 +5059,12 @@ join_ft_read_next(READ_RECORD *info)
/*****************************************************************************
-** The different end of select functions
-** These functions returns < 0 when end is reached, 0 on ok and > 0 if a
-** fatal error (like table corruption) was detected
+ The different end of select functions
+ These functions returns < 0 when end is reached, 0 on ok and > 0 if a
+ fatal error (like table corruption) was detected
*****************************************************************************/
- /* ARGSUSED */
+/* ARGSUSED */
static int
end_send(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
bool end_of_records)
@@ -5053,12 +5090,24 @@ end_send(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
JOIN_TAB *jt=join->join_tab;
if ((join->tables == 1) && !join->tmp_table && !join->sort_and_group
&& !join->send_group_parts && !join->having && !jt->select_cond &&
+ !(jt->select && jt->select->quick) &&
!(jt->table->file->table_flags() & HA_NOT_EXACT_COUNT))
{
/* Join over all rows in table; Return number of found rows */
+ TABLE *table=jt->table;
+
join->select_options ^= OPTION_FOUND_ROWS;
- jt->table->file->info(HA_STATUS_VARIABLE);
- join->send_records = jt->table->file->records;
+ if (table->record_pointers ||
+ (table->io_cache && my_b_inited(table->io_cache)))
+ {
+ /* Using filesort */
+ join->send_records= table->found_records;
+ }
+ else
+ {
+ table->file->info(HA_STATUS_VARIABLE);
+ join->send_records = table->file->records;
+ }
}
else
{
@@ -5204,7 +5253,7 @@ end_write(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
error == HA_ERR_FOUND_DUPP_UNIQUE)
goto end;
if (create_myisam_from_heap(table, &join->tmp_table_param, error,1))
- DBUG_RETURN(1); // Not a table_is_full error
+ DBUG_RETURN(-1); // Not a table_is_full error
table->uniques=0; // To ensure rows are the same
}
if (++join->send_records >= join->tmp_table_param.end_write_records &&
@@ -5376,7 +5425,7 @@ end_write_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
{
if (create_myisam_from_heap(table, &join->tmp_table_param,
error, 0))
- DBUG_RETURN(1); // Not a table_is_full error
+ DBUG_RETURN(-1); // Not a table_is_full error
}
else
join->send_records++;
@@ -5409,11 +5458,11 @@ end_write_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
/*****************************************************************************
-** Remove calculation with tables that aren't yet read. Remove also tests
-** against fields that are read through key where the table is not a
-** outer join table.
-** We can't remove tests that are made against columns which are stored
-** in sorted order.
+ Remove calculation with tables that aren't yet read. Remove also tests
+ against fields that are read through key where the table is not a
+ outer join table.
+ We can't remove tests that are made against columns which are stored
+ in sorted order.
*****************************************************************************/
/* Return 1 if right_item is used removable reference key on left_item */
@@ -5431,8 +5480,10 @@ static bool test_if_ref(Item_field *left_item,Item *right_item)
return (field->eq_def(((Item_field *) right_item)->field));
if (right_item->const_item() && !(right_item->is_null()))
{
- // We can remove binary fields and numerical fields except float,
- // as float comparison isn't 100 % secure
+ /*
+ We can remove binary fields and numerical fields except float,
+ as float comparison isn't 100 % secure
+ */
if (field->binary() &&
(field->type() != FIELD_TYPE_FLOAT || field->decimals() == 0))
{
@@ -5496,9 +5547,9 @@ make_cond_for_table(COND *cond,table_map tables,table_map used_table)
}
/*
- ** Because the following test takes a while and it can be done
- ** table_count times, we mark each item that we have examined with the result
- ** of the test
+ Because the following test takes a while and it can be done
+ table_count times, we mark each item that we have examined with the result
+ of the test
*/
if (cond->marker == 3 || (cond->used_tables() & ~tables))
@@ -5546,11 +5597,11 @@ part_of_refkey(TABLE *table,Field *field)
/*****************************************************************************
-** Test if one can use the key to resolve ORDER BY
-** Returns: 1 if key is ok.
-** 0 if key can't be used
-** -1 if reverse key can be used
-** used_key_parts is set to key parts used if length != 0
+ Test if one can use the key to resolve ORDER BY
+ Returns: 1 if key is ok.
+ 0 if key can't be used
+ -1 if reverse key can be used
+ used_key_parts is set to key parts used if length != 0
*****************************************************************************/
static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx,
@@ -5817,7 +5868,7 @@ err:
}
/*
-** Add the HAVING criteria to table->select
+ Add the HAVING criteria to table->select
*/
#ifdef NOT_YET
@@ -5852,11 +5903,11 @@ static bool fix_having(JOIN *join, Item **having)
/*****************************************************************************
-** Remove duplicates from tmp table
-** This should be recoded to add a uniuqe index to the table and remove
-** dupplicates
-** Table is a locked single thread table
-** fields is the number of fields to check (from the end)
+ Remove duplicates from tmp table
+ This should be recoded to add a unique index to the table and remove
+ duplicates
+ Table is a locked single thread table
+ fields is the number of fields to check (from the end)
*****************************************************************************/
static bool compare_record(TABLE *table, Field **ptr)
@@ -5896,6 +5947,7 @@ remove_duplicates(JOIN *join, TABLE *entry,List<Item> &fields, Item *having)
int error;
ulong reclength,offset;
uint field_count;
+ THD *thd= current_thd;
DBUG_ENTER("remove_duplicates");
entry->reginfo.lock_type=TL_WRITE;
@@ -5924,7 +5976,7 @@ remove_duplicates(JOIN *join, TABLE *entry,List<Item> &fields, Item *having)
if (entry->db_type == DB_TYPE_HEAP ||
(!entry->blob_fields &&
((ALIGN_SIZE(reclength) +sizeof(HASH_LINK)) * entry->file->records <
- sortbuff_size)))
+ thd->variables.sortbuff_size)))
error=remove_dup_with_hash_index(join->thd, entry,
field_count, first_field,
reclength, having);
@@ -6247,7 +6299,7 @@ join_init_cache(THD *thd,JOIN_TAB *tables,uint table_count)
cache->length=length+blobs*sizeof(char*);
cache->blobs=blobs;
*blob_ptr=0; /* End sequentel */
- size=max(join_buff_size,cache->length);
+ size=max(thd->variables.join_buff_size, cache->length);
if (!(cache->buff=(uchar*) my_malloc(size,MYF(0))))
DBUG_RETURN(1); /* Don't use cache */ /* purecov: inspected */
cache->end=cache->buff+size;
@@ -6288,7 +6340,7 @@ store_record_in_cache(JOIN_CACHE *cache)
cache->ptr_record=cache->records;
/*
- ** There is room in cache. Put record there
+ There is room in cache. Put record there
*/
cache->records++;
for (copy=cache->field ; copy < end_field; copy++)
@@ -6414,13 +6466,13 @@ cp_buffer_from_ref(TABLE_REF *ref)
/*****************************************************************************
-** Group and order functions
+ Group and order functions
*****************************************************************************/
/*
-** Find order/group item in requested columns and change the item to point at
-** it. If item doesn't exists, add it first in the field list
-** Return 0 if ok.
+ Find order/group item in requested columns and change the item to point at
+ it. If item doesn't exists, add it first in the field list
+ Return 0 if ok.
*/
static int
@@ -6465,8 +6517,8 @@ find_order_in_list(THD *thd,TABLE_LIST *tables,ORDER *order,List<Item> &fields,
/*
-** Change order to point at item in select list. If item isn't a number
-** and doesn't exits in the select list, add it the the field list.
+ Change order to point at item in select list. If item isn't a number
+ and doesn't exits in the select list, add it the the field list.
*/
int setup_order(THD *thd,TABLE_LIST *tables,List<Item> &fields,
@@ -6500,7 +6552,7 @@ setup_group(THD *thd,TABLE_LIST *tables,List<Item> &fields,
uint org_fields=all_fields.elements;
thd->where="group statement";
- for ( ; order; order=order->next)
+ for (; order; order=order->next)
{
if (find_order_in_list(thd,tables,order,fields,all_fields))
return 1;
@@ -6535,7 +6587,7 @@ setup_group(THD *thd,TABLE_LIST *tables,List<Item> &fields,
}
/*
-** Add fields with aren't used at start of field list. Return FALSE if ok
+ Add fields with aren't used at start of field list. Return FALSE if ok
*/
static bool
@@ -6547,7 +6599,7 @@ setup_new_fields(THD *thd,TABLE_LIST *tables,List<Item> &fields,
thd->set_query_id=1; // Not really needed, but...
thd->where=0; // Don't give error
- for ( ; new_field ; new_field=new_field->next)
+ for (; new_field ; new_field=new_field->next)
{
if ((item=find_item_in_list(*new_field->item,fields)))
new_field->item=item; /* Change to shared Item */
@@ -6565,9 +6617,9 @@ setup_new_fields(THD *thd,TABLE_LIST *tables,List<Item> &fields,
}
/*
-** Create a group by that consist of all non const fields. Try to use
-** the fields in the order given by 'order' to allow one to optimize
-** away 'order by'.
+ Create a group by that consist of all non const fields. Try to use
+ the fields in the order given by 'order' to allow one to optimize
+ away 'order by'.
*/
static ORDER *
@@ -6616,7 +6668,7 @@ create_distinct_group(ORDER *order_list,List<Item> &fields)
/*****************************************************************************
-** Update join with count of the different type of fields
+ Update join with count of the different type of fields
*****************************************************************************/
void
@@ -6707,7 +6759,7 @@ get_sort_by_table(ORDER *a,ORDER *b,TABLE_LIST *tables)
if (!map || (map & RAND_TABLE_BIT))
DBUG_RETURN(0);
- for ( ; !(map & tables->table->map) ; tables=tables->next) ;
+ for (; !(map & tables->table->map) ; tables=tables->next) ;
if (map != tables->table->map)
DBUG_RETURN(0); // More than one table
DBUG_PRINT("exit",("sort by table: %d",tables->table->tablenr));
@@ -6751,8 +6803,8 @@ calc_group_buffer(JOIN *join,ORDER *group)
/*
-** Get a list of buffers for saveing last group
-** Groups are saved in reverse order for easyer check loop
+ Get a list of buffers for saveing last group
+ Groups are saved in reverse order for easyer check loop
*/
static bool
@@ -6790,10 +6842,10 @@ test_if_group_changed(List<Item_buff> &list)
/*
-** Setup copy_fields to save fields at start of new group
-** Only FIELD_ITEM:s and FUNC_ITEM:s needs to be saved between groups.
-** Change old item_field to use a new field with points at saved fieldvalue
-** This function is only called before use of send_fields
+ Setup copy_fields to save fields at start of new group
+ Only FIELD_ITEM:s and FUNC_ITEM:s needs to be saved between groups.
+ Change old item_field to use a new field with points at saved fieldvalue
+ This function is only called before use of send_fields
*/
bool
@@ -6862,7 +6914,7 @@ err2:
/*
-** Copy fields and null values between two tables
+ Copy fields and null values between two tables
*/
void
@@ -6871,7 +6923,7 @@ copy_fields(TMP_TABLE_PARAM *param)
Copy_field *ptr=param->copy_field;
Copy_field *end=param->copy_field_end;
- for ( ; ptr != end; ptr++)
+ for (; ptr != end; ptr++)
(*ptr->do_copy)(ptr);
List_iterator_fast<Item> &it=param->copy_funcs_it;
@@ -6883,7 +6935,7 @@ copy_fields(TMP_TABLE_PARAM *param)
/*****************************************************************************
-** Make an array of pointer to sum_functions to speed up sum_func calculation
+ Make an array of pointer to sum_functions to speed up sum_func calculation
*****************************************************************************/
static bool
@@ -6915,7 +6967,7 @@ make_sum_func_list(JOIN *join,List<Item> &fields)
/*
-** Change all funcs and sum_funcs to fields in tmp table
+ Change all funcs and sum_funcs to fields in tmp table
*/
static bool
@@ -6965,8 +7017,8 @@ change_to_use_tmp_fields(List<Item> &items)
/*
-** Change all sum_func refs to fields to point at fields in tmp table
-** Change all funcs to be fields in tmp table
+ Change all sum_func refs to fields to point at fields in tmp table
+ Change all funcs to be fields in tmp table
*/
static bool
@@ -7022,7 +7074,7 @@ change_refs_to_tmp_fields(THD *thd,List<Item> &items)
/******************************************************************************
-** code for calculating functions
+ Code for calculating functions
******************************************************************************/
static void
@@ -7090,8 +7142,8 @@ copy_funcs(Item_result_field **func_ptr)
/*****************************************************************************
-** Create a condition for a const reference and add this to the
-** currenct select for the table
+ Create a condition for a const reference and add this to the
+ currenct select for the table
*****************************************************************************/
static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab)
@@ -7132,7 +7184,7 @@ static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab)
}
/****************************************************************************
-** Send a description about what how the select will be done to stdout
+ Send a description about what how the select will be done to stdout
****************************************************************************/
static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
@@ -7145,6 +7197,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
MYSQL_LOCK *save_lock;
SELECT_LEX *select_lex = &(join->thd->lex.select_lex);
select_result *result=join->result;
+ Item *item_null= new Item_null();
DBUG_ENTER("select_describe");
/* Don't log this into the slow query log */
@@ -7172,14 +7225,11 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
if (message)
{
- item_list.push_back(new Item_empty_string("",0));
- item_list.push_back(new Item_empty_string("",0));
- item_list.push_back(new Item_empty_string("",0));
- item_list.push_back(new Item_empty_string("",0));
- item_list.push_back(new Item_empty_string("",0));
- item_list.push_back(new Item_empty_string("",0));
- item_list.push_back(new Item_empty_string("",0));
- item_list.push_back(new Item_string(message,strlen(message),default_charset_info));
+ Item *empty= new Item_empty_string("",0);
+ for (uint i=0 ; i < 7; i++)
+ item_list.push_back(empty);
+ item_list.push_back(new Item_string(message,strlen(message),
+ default_charset_info));
if (result->send_data(item_list))
result->send_error(0,NullS);
}
@@ -7191,15 +7241,21 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
JOIN_TAB *tab=join->join_tab+i;
TABLE *table=tab->table;
char buff[512],*buff_ptr=buff;
- char buff1[512], buff2[512], bufff[512];
+ char buff1[512], buff2[512], buff3[512];
String tmp1(buff1,sizeof(buff1),default_charset_info);
String tmp2(buff2,sizeof(buff2),default_charset_info);
+ tmp1.length(0);
+ tmp2.length(0);
item_list.empty();
+
if (tab->type == JT_ALL && tab->select && tab->select->quick)
tab->type= JT_RANGE;
- item_list.push_back(new Item_string(table->table_name,strlen(table->table_name),default_charset_info));
- item_list.push_back(new Item_string(join_type_str[tab->type],strlen(join_type_str[tab->type]),default_charset_info));
- tmp1.length(0); tmp2.length(0);
+ item_list.push_back(new Item_string(table->table_name,
+ strlen(table->table_name),
+ default_charset_info));
+ item_list.push_back(new Item_string(join_type_str[tab->type],
+ strlen(join_type_str[tab->type]),
+ default_charset_info));
key_map bits;
uint j;
for (j=0,bits=tab->keys ; bits ; j++,bits>>=1)
@@ -7212,48 +7268,61 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
}
}
if (tmp1.length())
- item_list.push_back(new Item_string(tmp1.ptr(),tmp1.length(),default_charset_info));
+ item_list.push_back(new Item_string(tmp1.ptr(),tmp1.length(),
+ default_charset_info));
else
- item_list.push_back(new Item_null());
+ item_list.push_back(item_null);
if (tab->ref.key_parts)
{
- item_list.push_back(new Item_string(table->key_info[tab->ref.key].name,strlen(table->key_info[tab->ref.key].name),default_charset_info));
- item_list.push_back(new Item_int((int) tab->ref.key_length));
+ KEY *key_info=table->key_info+ tab->ref.key;
+ item_list.push_back(new Item_string(key_info->name,
+ strlen(key_info->name)));
+ item_list.push_back(new Item_int((int32) tab->ref.key_length));
for (store_key **ref=tab->ref.key_copy ; *ref ; ref++)
{
if (tmp2.length())
tmp2.append(',');
tmp2.append((*ref)->name());
}
- item_list.push_back(new Item_string(tmp2.ptr(),tmp2.length(),default_charset_info));
+ item_list.push_back(new Item_string(tmp2.ptr(),tmp2.length(),
+ default_charset_info));
}
else if (tab->type == JT_NEXT)
{
- item_list.push_back(new Item_string(table->key_info[tab->index].name,strlen(table->key_info[tab->index].name),default_charset_info));
- item_list.push_back(new Item_int((int) table->key_info[tab->index].key_length));
- item_list.push_back(new Item_null());
+ KEY *key_info=table->key_info+ tab->index;
+ item_list.push_back(new Item_string(key_info->name,
+ strlen(key_info->name),
+ default_charset_info));
+ item_list.push_back(new Item_int((int32) key_info->key_length));
+ item_list.push_back(item_null);
}
else if (tab->select && tab->select->quick)
{
- item_list.push_back(new Item_string(table->key_info[tab->select->quick->index].name,strlen(table->key_info[tab->select->quick->index].name),default_charset_info));
- item_list.push_back(new Item_int((int) tab->select->quick->max_used_key_length));
- item_list.push_back(new Item_null());
+ KEY *key_info=table->key_info+ tab->select->quick->index;
+ item_list.push_back(new Item_string(key_info->name,
+ strlen(key_info->name),
+ default_charset_info));
+ item_list.push_back(new Item_int((int32) tab->select->quick->
+ max_used_key_length));
+ item_list.push_back(item_null);
}
else
{
- item_list.push_back(new Item_null());
- item_list.push_back(new Item_null());
- item_list.push_back(new Item_null());
+ item_list.push_back(item_null);
+ item_list.push_back(item_null);
+ item_list.push_back(item_null);
}
- sprintf(bufff,"%.0f",join->best_positions[i].records_read);
- item_list.push_back(new Item_string(bufff,strlen(bufff),default_charset_info));
+ sprintf(buff3,"%.0f",join->best_positions[i].records_read);
+ item_list.push_back(new Item_string(buff3,strlen(buff3),
+ default_charset_info));
my_bool key_read=table->key_read;
if (tab->type == JT_NEXT &&
((table->used_keys & ((key_map) 1 << tab->index))))
key_read=1;
if (tab->info)
- item_list.push_back(new Item_string(tab->info,strlen(tab->info),default_charset_info));
+ item_list.push_back(new Item_string(tab->info,strlen(tab->info),
+ default_charset_info));
else if (tab->select)
{
if (tab->use_quick == 2)
@@ -7307,14 +7376,15 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
}
buff_ptr=strmov(buff_ptr,"Distinct");
}
- item_list.push_back(new Item_string(buff,(uint) (buff_ptr - buff),default_charset_info));
+ item_list.push_back(new Item_string(buff,(uint) (buff_ptr - buff),
+ default_charset_info));
// For next iteration
used_tables|=table->map;
if (result->send_data(item_list))
result->send_error(0,NullS);
}
}
- if (!join->thd->lex.select->next_select())
+ if (!thd->lex.select->next_select())
{
save_lock=thd->lock;
thd->lock=(MYSQL_LOCK *)0;
@@ -7325,13 +7395,21 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
}
-static void describe_info(THD *thd, const char *info)
+static void describe_info(JOIN *join, const char *info)
{
+ THD *thd= join->thd;
+
+ if (thd->lex.select->next_select()) /* If in UNION */
+ {
+ select_describe(join,FALSE,FALSE,FALSE,info);
+ return;
+ }
List<Item> field_list;
String *packet= &thd->packet;
/* Don't log this into the slow query log */
- thd->lex.select_lex.options&= ~(QUERY_NO_INDEX_USED | QUERY_NO_GOOD_INDEX_USED);
+ thd->lex.select_lex.options&= ~(QUERY_NO_INDEX_USED |
+ QUERY_NO_GOOD_INDEX_USED);
field_list.push_back(new Item_empty_string("Comment",80));
if (send_fields(thd,field_list,1))
return; /* purecov: inspected */
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index e227a5bf5ca..5899fe86024 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -78,13 +78,13 @@ mysqld_show_dbs(THD *thd,const char *wild)
List_iterator_fast<char> it(files);
while ((file_name=it++))
{
- if (!opt_safe_show_db || thd->master_access ||
+ if (thd->master_access & (DB_ACLS | SHOW_DB_ACL) ||
acl_get(thd->host, thd->ip, (char*) &thd->remote.sin_addr,
thd->priv_user, file_name) ||
(grant_option && !check_grant_db(thd, file_name)))
- {
+ {
thd->packet.length(0);
- net_store_data(&thd->packet, thd->convert_set, file_name);
+ net_store_data(&thd->packet, thd->variables.convert_set, file_name);
if (my_net_write(&thd->net, (char*) thd->packet.ptr(),
thd->packet.length()))
DBUG_RETURN(-1);
@@ -102,7 +102,7 @@ int mysqld_show_open_tables(THD *thd,const char *wild)
{
List<Item> field_list;
OPEN_TABLE_LIST *open_list;
- CONVERT *convert=thd->convert_set;
+ CONVERT *convert=thd->variables.convert_set;
DBUG_ENTER("mysqld_show_open_tables");
field_list.push_back(new Item_empty_string("Database",NAME_LEN));
@@ -116,7 +116,7 @@ int mysqld_show_open_tables(THD *thd,const char *wild)
if (!(open_list=list_open_tables(thd,wild)) && thd->fatal_error)
DBUG_RETURN(-1);
- for ( ; open_list ; open_list=open_list->next)
+ for (; open_list ; open_list=open_list->next)
{
thd->packet.length(0);
net_store_data(&thd->packet,convert, open_list->db);
@@ -124,13 +124,15 @@ int mysqld_show_open_tables(THD *thd,const char *wild)
net_store_data(&thd->packet,open_list->in_use);
net_store_data(&thd->packet,open_list->locked);
if (my_net_write(&thd->net,(char*) thd->packet.ptr(),thd->packet.length()))
+ {
DBUG_RETURN(-1);
+ }
}
-
send_eof(&thd->net);
DBUG_RETURN(0);
}
+
/***************************************************************************
** List all tables in a database (fast version)
** A table is a .frm file in the current databasedir
@@ -161,7 +163,7 @@ int mysqld_show_tables(THD *thd,const char *db,const char *wild)
while ((file_name=it++))
{
thd->packet.length(0);
- net_store_data(&thd->packet, thd->convert_set, file_name);
+ net_store_data(&thd->packet, thd->variables.convert_set, file_name);
if (my_net_write(&thd->net,(char*) thd->packet.ptr(),thd->packet.length()))
DBUG_RETURN(-1);
}
@@ -452,7 +454,7 @@ int mysqld_extend_show_tables(THD *thd,const char *db,const char *wild)
char *file_name;
TABLE *table;
String *packet= &thd->packet;
- CONVERT *convert=thd->convert_set;
+ CONVERT *convert=thd->variables.convert_set;
DBUG_ENTER("mysqld_extend_show_tables");
(void) sprintf(path,"%s/%s",mysql_data_home,db);
@@ -628,7 +630,7 @@ mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild,
handler *file;
char tmp[MAX_FIELD_WIDTH];
Item *item;
- CONVERT *convert=thd->convert_set;
+ CONVERT *convert=thd->variables.convert_set;
DBUG_ENTER("mysqld_show_fields");
DBUG_PRINT("enter",("db: %s table: %s",table_list->db,
table_list->real_name));
@@ -748,7 +750,7 @@ int
mysqld_show_create(THD *thd, TABLE_LIST *table_list)
{
TABLE *table;
- CONVERT *convert=thd->convert_set;
+ CONVERT *convert=thd->variables.convert_set;
DBUG_ENTER("mysqld_show_create");
DBUG_PRINT("enter",("db: %s table: %s",table_list->db,
table_list->real_name));
@@ -840,7 +842,7 @@ mysqld_show_keys(THD *thd, TABLE_LIST *table_list)
{
TABLE *table;
char buff[256];
- CONVERT *convert=thd->convert_set;
+ CONVERT *convert=thd->variables.convert_set;
DBUG_ENTER("mysqld_show_keys");
DBUG_PRINT("enter",("db: %s table: %s",table_list->db,
table_list->real_name));
@@ -972,7 +974,7 @@ mysqld_list_fields(THD *thd, TABLE_LIST *table_list, const char *wild)
int
mysqld_dump_create_info(THD *thd, TABLE *table, int fd)
{
- CONVERT *convert=thd->convert_set;
+ CONVERT *convert=thd->variables.convert_set;
DBUG_ENTER("mysqld_dump_create_info");
DBUG_PRINT("enter",("table: %s",table->real_name));
@@ -1240,8 +1242,9 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose)
Item *field;
List<Item> field_list;
I_List<thread_info> thread_infos;
- ulong max_query_length= verbose ? max_allowed_packet : PROCESS_LIST_WIDTH;
- CONVERT *convert=thd->convert_set;
+ ulong max_query_length= (verbose ? thd->variables.max_allowed_packet :
+ PROCESS_LIST_WIDTH);
+ CONVERT *convert=thd->variables.convert_set;
DBUG_ENTER("mysqld_list_processes");
field_list.push_back(new Item_int("Id",0,7));
@@ -1360,7 +1363,7 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose)
/*****************************************************************************
-** Status functions
+ Status functions
*****************************************************************************/
int mysqld_show_charsets(THD *thd, const char *wild)
@@ -1385,7 +1388,8 @@ int mysqld_show_charsets(THD *thd, const char *wild)
{
if (!cs->name)
continue;
- if (!(wild && wild[0] && wild_case_compare(system_charset_info,cs->name,wild)))
+ if (!(wild && wild[0] &&
+ wild_case_compare(system_charset_info,cs->name,wild)))
{
packet2.length(0);
net_store_data(&packet2,convert,cs->name);
@@ -1403,15 +1407,17 @@ err:
DBUG_RETURN(1);
}
+
-int mysqld_show(THD *thd, const char *wild, show_var_st *variables)
+int mysqld_show(THD *thd, const char *wild, show_var_st *variables,
+ enum enum_var_type value_type)
{
- uint i;
char buff[8192];
- String packet2(buff,sizeof(buff),default_charset_info);
+ String packet2(buff,sizeof(buff), system_charset_info);
List<Item> field_list;
- CONVERT *convert=thd->convert_set;
+ CONVERT *convert=thd->variables.convert_set;
DBUG_ENTER("mysqld_show");
+
field_list.push_back(new Item_empty_string("Variable_name",30));
field_list.push_back(new Item_empty_string("Value",256));
if (send_fields(thd,field_list,1))
@@ -1419,40 +1425,49 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables)
/* pthread_mutex_lock(&THR_LOCK_keycache); */
pthread_mutex_lock(&LOCK_status);
- for (i=0; variables[i].name; i++)
+ for (; variables->name; variables++)
{
if (!(wild && wild[0] && wild_case_compare(system_charset_info,
variables[i].name,wild)))
{
packet2.length(0);
- net_store_data(&packet2,convert,variables[i].name);
- switch (variables[i].type){
+ net_store_data(&packet2,convert,variables->name);
+ SHOW_TYPE show_type=variables->type;
+ char *value=variables->value;
+ if (show_type == SHOW_SYS)
+ {
+ show_type= ((sys_var*) value)->type();
+ value= (char*) ((sys_var*) value)->value_ptr(thd, value_type);
+ }
+
+ switch (show_type) {
case SHOW_LONG:
case SHOW_LONG_CONST:
- net_store_data(&packet2,(uint32) *(ulong*) variables[i].value);
+ net_store_data(&packet2,(uint32) *(ulong*) value);
+ break;
+ case SHOW_LONGLONG:
+ net_store_data(&packet2,(longlong) *(longlong*) value);
break;
case SHOW_BOOL:
- net_store_data(&packet2,(ulong) *(bool*) variables[i].value ?
- "ON" : "OFF");
+ net_store_data(&packet2,(ulong) *(bool*) value ? "ON" : "OFF");
break;
case SHOW_MY_BOOL:
- net_store_data(&packet2,(ulong) *(my_bool*) variables[i].value ?
- "ON" : "OFF");
+ net_store_data(&packet2,(ulong) *(my_bool*) value ? "ON" : "OFF");
break;
case SHOW_INT_CONST:
case SHOW_INT:
- net_store_data(&packet2,(uint32) *(int*) variables[i].value);
+ net_store_data(&packet2,(uint32) *(int*) value);
break;
case SHOW_HAVE:
{
- SHOW_COMP_OPTION tmp= *(SHOW_COMP_OPTION*) variables[i].value;
+ SHOW_COMP_OPTION tmp= *(SHOW_COMP_OPTION*) value;
net_store_data(&packet2, (tmp == SHOW_OPTION_NO ? "NO" :
tmp == SHOW_OPTION_YES ? "YES" :
"DISABLED"));
break;
}
case SHOW_CHAR:
- net_store_data(&packet2,convert, variables[i].value);
+ net_store_data(&packet2,convert, value);
break;
case SHOW_STARTTIME:
net_store_data(&packet2,(uint32) (thd->query_start() - start_time));
@@ -1476,11 +1491,11 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables)
net_store_data(&packet2,(uint32) cached_tables());
break;
case SHOW_CHAR_PTR:
- {
- char *value= *(char**) variables[i].value;
- net_store_data(&packet2,convert, value ? value : "");
- break;
- }
+ {
+ value= *(char**) value;
+ net_store_data(&packet2,convert, value ? value : "");
+ break;
+ }
#ifdef HAVE_OPENSSL
/* First group - functions relying on CTX */
case SHOW_SSL_CTX_SESS_ACCEPT:
@@ -1564,7 +1579,7 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables)
net_store_data(&packet2,"NONE" );
break;
}
- switch(SSL_CTX_get_session_cache_mode(ssl_acceptor_fd->ssl_context_))
+ switch (SSL_CTX_get_session_cache_mode(ssl_acceptor_fd->ssl_context_))
{
case SSL_SESS_CACHE_OFF:
net_store_data(&packet2,"OFF" );
@@ -1637,6 +1652,10 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables)
break;
#endif /* HAVE_OPENSSL */
+ case SHOW_UNDEF: // Show never happen
+ case SHOW_SYS:
+ net_store_data(&packet2, ""); // Safety
+ break;
}
if (my_net_write(&thd->net, (char*) packet2.ptr(),packet2.length()))
goto err; /* purecov: inspected */
diff --git a/sql/sql_string.cc b/sql/sql_string.cc
index 9014ca430d9..6a42078cbcd 100644
--- a/sql/sql_string.cc
+++ b/sql/sql_string.cc
@@ -657,7 +657,7 @@ int wild_case_compare(CHARSET_INFO *cs, const char *str,const char *str_end,
{ // Found wild_many
wildstr++;
/* Remove any '%' and '_' from the wild search string */
- for ( ; wildstr != wildend ; wildstr++)
+ for (; wildstr != wildend ; wildstr++)
{
if (*wildstr == wild_many)
continue;
@@ -786,7 +786,7 @@ int wild_compare(const char *str,const char *str_end,
{ // Found wild_many
wildstr++;
/* Remove any '%' and '_' from the wild search string */
- for ( ; wildstr != wildend ; wildstr++)
+ for (; wildstr != wildend ; wildstr++)
{
if (*wildstr == wild_many)
continue;
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 3652b2512f4..6b24999763b 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -20,6 +20,7 @@
#include "mysql_priv.h"
#include <hash.h>
#include <myisam.h>
+#include <assert.h>
#ifdef __WIN__
#include <io.h>
@@ -71,8 +72,8 @@ int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists)
error=mysql_rm_table_part2(thd,tables,if_exists,0);
err:
- VOID(pthread_cond_broadcast(&COND_refresh)); // Signal to refresh
pthread_mutex_unlock(&LOCK_open);
+ VOID(pthread_cond_broadcast(&COND_refresh)); // Signal to refresh
pthread_mutex_lock(&thd->mysys_var->mutex);
thd->mysys_var->current_mutex= 0;
@@ -85,6 +86,27 @@ int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists)
DBUG_RETURN(0);
}
+int mysql_rm_table_part2_with_lock(THD *thd,
+ TABLE_LIST *tables, bool if_exists,
+ bool dont_log_query)
+{
+ int error;
+ thd->mysys_var->current_mutex= &LOCK_open;
+ thd->mysys_var->current_cond= &COND_refresh;
+ VOID(pthread_mutex_lock(&LOCK_open));
+
+ error=mysql_rm_table_part2(thd,tables, if_exists, dont_log_query);
+
+ pthread_mutex_unlock(&LOCK_open);
+ VOID(pthread_cond_broadcast(&COND_refresh)); // Signal to refresh
+
+ pthread_mutex_lock(&thd->mysys_var->mutex);
+ thd->mysys_var->current_mutex= 0;
+ thd->mysys_var->current_cond= 0;
+ pthread_mutex_unlock(&thd->mysys_var->mutex);
+ return error;
+}
+
int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
bool dont_log_query)
@@ -115,15 +137,8 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
}
drop_locked_tables(thd,db,table->real_name);
if (thd->killed)
- {
- VOID(pthread_cond_broadcast(&COND_refresh)); // Signal to refresh
- VOID(pthread_mutex_unlock(&LOCK_open));
- pthread_mutex_lock(&thd->mysys_var->mutex);
- thd->mysys_var->current_mutex= 0;
- thd->mysys_var->current_cond= 0;
- pthread_mutex_unlock(&thd->mysys_var->mutex);
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);
@@ -167,7 +182,7 @@ 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);
+ Query_log_event qinfo(thd, thd->query, thd->query_length);
mysql_bin_log.write(&qinfo);
}
}
@@ -746,7 +761,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
mysql_update_log.write(thd,thd->query, thd->query_length);
if (mysql_bin_log.is_open())
{
- Query_log_event qinfo(thd, thd->query);
+ Query_log_event qinfo(thd, thd->query, thd->query_length);
mysql_bin_log.write(&qinfo);
}
}
@@ -859,7 +874,9 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
table->reginfo.lock_type=TL_WRITE;
if (!((*lock)=mysql_lock_tables(thd,&table,1)))
{
+ VOID(pthread_mutex_lock(&LOCK_open));
hash_delete(&open_cache,(byte*) table);
+ VOID(pthread_mutex_unlock(&LOCK_open));
quick_rm_table(create_info->db_type,db,name);
DBUG_RETURN(0);
}
@@ -912,6 +929,8 @@ bool close_cached_table(THD *thd,TABLE *table)
{
bool result=0;
DBUG_ENTER("close_cached_table");
+ safe_mutex_assert_owner(&LOCK_open);
+
if (table)
{
DBUG_PRINT("enter",("table: %s", table->table_name));
@@ -964,8 +983,9 @@ static int send_check_errmsg(THD* thd, TABLE_LIST* table,
return 1;
}
+
static int prepare_for_restore(THD* thd, TABLE_LIST* table,
- HA_CHECK_OPT *check_opt)
+ HA_CHECK_OPT *check_opt)
{
DBUG_ENTER("prepare_for_restore");
@@ -995,27 +1015,38 @@ static int prepare_for_restore(THD* thd, TABLE_LIST* table,
fn_format(dst_path, dst_path,"", reg_ext, 4),
MYF(MY_WME)))
{
+ pthread_mutex_lock(&LOCK_open);
unlock_table_name(thd, table);
+ pthread_mutex_unlock(&LOCK_open);
DBUG_RETURN(send_check_errmsg(thd, table, "restore",
"Failed copying .frm file"));
}
if (mysql_truncate(thd, table, 1))
{
+ pthread_mutex_lock(&LOCK_open);
unlock_table_name(thd, table);
+ pthread_mutex_unlock(&LOCK_open);
DBUG_RETURN(send_check_errmsg(thd, table, "restore",
"Failed generating table from .frm file"));
}
}
- // now we should be able to open the partially restored table
- // to finish the restore in the handler later on
+ /*
+ Now we should be able to open the partially restored table
+ to finish the restore in the handler later on
+ */
if (!(table->table = reopen_name_locked_table(thd, table)))
- unlock_table_name(thd, table);
+ {
+ pthread_mutex_lock(&LOCK_open);
+ unlock_table_name(thd, table);
+ pthread_mutex_unlock(&LOCK_open);
+ }
DBUG_RETURN(0);
}
+
static int prepare_for_repair(THD* thd, TABLE_LIST* table,
- HA_CHECK_OPT *check_opt)
+ HA_CHECK_OPT *check_opt)
{
DBUG_ENTER("prepare_for_repair");
@@ -1040,38 +1071,52 @@ static int prepare_for_repair(THD* thd, TABLE_LIST* table,
if (my_rename(from, tmp, MYF(MY_WME)))
{
+ pthread_mutex_lock(&LOCK_open);
unlock_table_name(thd, table);
+ pthread_mutex_unlock(&LOCK_open);
DBUG_RETURN(send_check_errmsg(thd, table, "repair",
"Failed renaming .MYD file"));
}
if (mysql_truncate(thd, table, 1))
{
+ pthread_mutex_lock(&LOCK_open);
unlock_table_name(thd, table);
+ pthread_mutex_unlock(&LOCK_open);
DBUG_RETURN(send_check_errmsg(thd, table, "repair",
"Failed generating table from .frm file"));
}
if (my_rename(tmp, from, MYF(MY_WME)))
{
+ pthread_mutex_lock(&LOCK_open);
unlock_table_name(thd, table);
+ pthread_mutex_unlock(&LOCK_open);
DBUG_RETURN(send_check_errmsg(thd, table, "repair",
"Failed restoring .MYD file"));
}
}
- // now we should be able to open the partially repaired table
- // to finish the repair in the handler later on
+ /*
+ Now we should be able to open the partially repaired table
+ to finish the repair in the handler later on.
+ */
if (!(table->table = reopen_name_locked_table(thd, table)))
- unlock_table_name(thd, table);
+ {
+ pthread_mutex_lock(&LOCK_open);
+ unlock_table_name(thd, table);
+ pthread_mutex_unlock(&LOCK_open);
+ }
DBUG_RETURN(0);
}
+
static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
HA_CHECK_OPT* check_opt,
const char *operator_name,
thr_lock_type lock_type,
bool open_for_modify,
uint extra_open_options,
- int (*prepare_func)(THD *, TABLE_LIST *, HA_CHECK_OPT *),
+ int (*prepare_func)(THD *, TABLE_LIST *,
+ HA_CHECK_OPT *),
int (handler::*operator_func)
(THD *, HA_CHECK_OPT *))
{
@@ -1212,8 +1257,10 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
table->table->version=0; // Force close of table
else if (open_for_modify)
{
+ pthread_mutex_lock(&LOCK_open);
remove_table_from_cache(thd, table->table->table_cache_key,
table->table->real_name);
+ pthread_mutex_unlock(&LOCK_open);
/* May be something modified consequently we have to invalidate cache */
query_cache_invalidate3(thd, table->table, 0);
}
@@ -1242,6 +1289,7 @@ int mysql_backup_table(THD* thd, TABLE_LIST* table_list)
&handler::backup));
}
+
int mysql_restore_table(THD* thd, TABLE_LIST* table_list)
{
DBUG_ENTER("mysql_restore_table");
@@ -1251,6 +1299,7 @@ int mysql_restore_table(THD* thd, TABLE_LIST* table_list)
&handler::restore));
}
+
int mysql_repair_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
{
DBUG_ENTER("mysql_repair_table");
@@ -1260,6 +1309,7 @@ int mysql_repair_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
&handler::repair));
}
+
int mysql_optimize_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
{
DBUG_ENTER("mysql_optimize_table");
@@ -1423,7 +1473,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);
+ Query_log_event qinfo(thd, thd->query, thd->query_length);
mysql_bin_log.write(&qinfo);
}
send_ok(&thd->net);
@@ -1799,7 +1849,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);
+ Query_log_event qinfo(thd, thd->query, thd->query_length);
mysql_bin_log.write(&qinfo);
}
goto end_temporary;
@@ -1920,16 +1970,20 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
error=1;
if (error)
{
- VOID(pthread_cond_broadcast(&COND_refresh));
VOID(pthread_mutex_unlock(&LOCK_open));
+ VOID(pthread_cond_broadcast(&COND_refresh));
goto err;
}
-
+#ifdef HAVE_BERKELEY_DB
+ extern bool berkeley_flush_logs(void);
+ if (old_db_type == DB_TYPE_BERKELEY_DB && berkeley_flush_logs())
+ goto err;
+#endif
thd->proc_info="end";
mysql_update_log.write(thd, thd->query,thd->query_length);
if (mysql_bin_log.is_open())
{
- Query_log_event qinfo(thd, thd->query);
+ Query_log_event qinfo(thd, thd->query, thd->query_length);
mysql_bin_log.write(&qinfo);
}
VOID(pthread_cond_broadcast(&COND_refresh));
diff --git a/sql/sql_test.cc b/sql/sql_test.cc
index 0bc1feed839..ef26a1f45fe 100644
--- a/sql/sql_test.cc
+++ b/sql/sql_test.cc
@@ -21,6 +21,7 @@
#include "mysql_priv.h"
#include "sql_select.h"
#include <hash.h>
+#include <thr_alarm.h>
/* Intern key cache variables */
extern "C" pthread_mutex_t THR_LOCK_keycache;
@@ -240,6 +241,18 @@ Open streams: %10lu\n",
(ulong) cached_tables(),
(ulong) my_file_opened,
(ulong) my_stream_opened);
+
+ ALARM_INFO alarm_info;
+#ifndef DONT_USE_THR_ALARM
+ thr_alarm_info(&alarm_info);
+ printf("\nAlarm status:\n\
+Active alarms: %u\n\
+Max used alarms: %u\n\
+Next alarm time: %lu\n",
+ alarm_info.active_alarms,
+ alarm_info.max_used_alarms,
+ alarm_info.next_alarm_time);
+#endif
fflush(stdout);
if (thd)
thd->proc_info="malloc";
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index 0eea10e068a..51f278536de 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -43,8 +43,8 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
/* Global option */
if (((void*)(global= unit->global_parameters)) == ((void*)unit))
{
- found_rows_for_union = lex->select_lex.options & OPTION_FOUND_ROWS &&
- !describe && global->select_limit;
+ found_rows_for_union= (lex->select_lex.options & OPTION_FOUND_ROWS &&
+ !describe && global->select_limit);
if (found_rows_for_union)
lex->select_lex.options ^= OPTION_FOUND_ROWS;
}
@@ -221,10 +221,11 @@ bool select_union::send_data(List<Item> &values)
unit->offset_limit_cnt--;
return 0;
}
+
fill_record(table->field,values);
if ((write_record(table,&info)))
{
- if (create_myisam_from_heap(table, tmp_table_param, info.errorno, 0))
+ if (create_myisam_from_heap(table, tmp_table_param, info.last_errno, 0))
return 1;
}
return 0;
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 51453f955e8..f0ca5ad6c7b 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -16,9 +16,7 @@
/* Update of records
-
Multi-table updates were introduced by Monty and Sinisa <sinisa@mysql.com>
-
*/
#include "mysql_priv.h"
@@ -119,7 +117,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 & SQL_SAFE_UPDATES),
+ (select && select->check_quick(test(thd->options & OPTION_SAFE_UPDATES),
limit)) ||
!limit)
{
@@ -309,7 +307,8 @@ int mysql_update(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, using_transactions);
+ Query_log_event qinfo(thd, thd->query, thd->query_length,
+ using_transactions);
if (mysql_bin_log.write(&qinfo) && using_transactions)
error=1;
}
@@ -347,7 +346,7 @@ int mysql_update(THD *thd,
}
/***************************************************************************
-** update multiple tables from join
+ Update multiple tables from join
***************************************************************************/
multi_update::multi_update(THD *thd_arg, TABLE_LIST *ut, List<Item> &fs,
@@ -363,7 +362,7 @@ multi_update::multi_update(THD *thd_arg, TABLE_LIST *ut, List<Item> &fs,
for (TABLE_LIST *dt=ut ; dt ; dt=dt->next,counter++)
{
TABLE *table=ut->table;
-// (void) ut->table->file->extra(HA_EXTRA_NO_KEYREAD);
+ // (void) ut->table->file->extra(HA_EXTRA_NO_KEYREAD);
dt->table->used_keys=0;
if (table->timestamp_field)
{
@@ -403,10 +402,14 @@ multi_update::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
}
}
}
-// Here I have to connect fields with tables and only update tables that need to be updated ...
+ /*
+ Here I have to connect fields with tables and only update tables that
+ need to be updated.
+ I calculate num_updated and fill-up table_sequence
+ Set table_list->shared to true or false, depending on whether table is
+ to be updated or not
+ */
-// I calculate num_updated and fill-up table_sequence
-// Set table_list->shared to true or false, depending on whether table is to be updated or not
Item_field *item;
List_iterator<Item> it(fields);
num_fields=fields.elements;
@@ -415,21 +418,28 @@ multi_update::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
while ((item= (Item_field *)it++))
{
unsigned int counter=0;
- for (table_ref=update_tables; table_ref; table_ref=table_ref->next, counter++)
+ for (table_ref=update_tables; table_ref;
+ table_ref=table_ref->next, counter++)
{
- if (table_ref->table == item->field->table && !table_ref->shared)
+ if (table_ref->table == item->field->table)
{
- num_updated++;
- table_ref->shared=1;
- if (!not_trans_safe && !table_ref->table->file->has_transactions())
- not_trans_safe=true;
- table_ref->table->no_keyread=1; // to be moved if initialize_tables has to be used
+ if (!table_ref->shared)
+ {
+ TABLE *tbl=table_ref->table;
+ num_updated++;
+ table_ref->shared=1;
+ if (!not_trans_safe && !table_ref->table->file->has_transactions())
+ not_trans_safe=true;
+ // to be moved if initialize_tables has to be used
+ tbl->no_keyread=1;
+ tbl->used_keys=0;
+ }
break;
}
}
if (!table_ref)
{
- error = 1; // A proper error message is due here
+ net_printf(&thd->net, ER_NOT_SUPPORTED_YET, "JOIN SYNTAX WITH MULTI-TABLE UPDATES");
DBUG_RETURN(1);
}
else
@@ -437,12 +447,14 @@ multi_update::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
}
if (!num_updated)
{
- error = 1; // A proper error message is due here
+ net_printf(&thd->net, ER_NOT_SUPPORTED_YET, "SET CLAUSE MUST CONTAIN TABLE.FIELD REFERENCE");
DBUG_RETURN(1);
}
-// Here, I have to allocate the array of temporary tables
-// I have to treat a case of num_updated=1 differently in send_data() method.
+ /*
+ Here, I have to allocate the array of temporary tables
+ I have to treat a case of num_updated=1 differently in send_data() method.
+ */
if (num_updated > 1)
{
tmp_tables = (TABLE **) sql_calloc(sizeof(TABLE *) * (num_updated - 1));
@@ -454,7 +466,7 @@ multi_update::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
{
if (!table_ref->shared)
continue;
-// Here we have to add row offset as an additional field ...
+ // Here we have to add row offset as an additional field ...
if (!(temp_fields = (List_item *)sql_calloc(sizeof(List_item))))
{
error = 1; // A proper error message is due here
@@ -473,7 +485,8 @@ multi_update::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
"offset", table_ref->table, true,
default_charset_info);
temp_fields->push_front(new Item_field(((Field *)&offset)));
-// Here I make tmp tables
+
+ // Make a temporary table
int cnt=counter-1;
TMP_TABLE_PARAM tmp_table_param;
bzero((char*) &tmp_table_param,sizeof(tmp_table_param));
@@ -496,6 +509,7 @@ multi_update::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
counter++;
}
}
+ init_ftfuncs(thd,1);
error = 0; // Timestamps do not need to be restored, so far ...
DBUG_RETURN(0);
}
@@ -504,7 +518,8 @@ multi_update::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
void
multi_update::initialize_tables(JOIN *join)
{
-/* We skip it as it only makes a mess ...........
+#ifdef NOT_YET
+ We skip it as it only makes a mess ...........
TABLE_LIST *walk;
table_map tables_to_update_from=0;
for (walk= update_tables ; walk ; walk=walk->next)
@@ -517,14 +532,14 @@ multi_update::initialize_tables(JOIN *join)
{
if (tab->table->map & tables_to_update_from)
{
- We are going to update from this table
- walk->table=tab->table;
- walk=walk->next;
- if (tab == join->join_tab)
- tab->table->no_keyread=1;
+// We are going to update from this table
+ TABLE *tbl=walk->table=tab->table;
+ /* Don't use KEYREAD optimization on this table */
+ tbl->no_keyread=1;
+ walk=walk->next;
}
}
-*/
+#endif
}
@@ -552,7 +567,7 @@ bool multi_update::send_data(List<Item> &values)
List<Item> real_values(values);
for (uint counter = 0; counter < fields.elements; counter++)
real_values.pop();
-// We have skipped fields ....
+ // We have skipped fields ....
if (num_updated == 1)
{
for (table_being_updated=update_tables ;
@@ -566,7 +581,7 @@ bool multi_update::send_data(List<Item> &values)
if (table->status & (STATUS_NULL_ROW | STATUS_UPDATED))
return 0;
table->file->position(table->record[0]);
-// Only one table being updated receives a completely different treatment
+ // Only one table being updated receives a completely different treatment
table->status|= STATUS_UPDATED;
store_record(table,1);
if (fill_record(fields,real_values))
@@ -575,6 +590,7 @@ bool multi_update::send_data(List<Item> &values)
if (/* compare_record(table, query_id) && */
!(error=table->file->update_row(table->record[1], table->record[0])))
updated++;
+ table->file->extra(HA_EXTRA_NO_CACHE);
return error;
}
}
@@ -602,7 +618,7 @@ bool multi_update::send_data(List<Item> &values)
if (*int_ptr++ == (uint) (secure_counter + 1))
values_by_table.push_back(item);
}
-// Here I am breaking values as per each table
+ // Here I am breaking values as per each table
if (secure_counter < 0)
{
table->status|= STATUS_UPDATED;
@@ -612,7 +628,10 @@ bool multi_update::send_data(List<Item> &values)
found++;
if (/*compare_record(table, query_id) && */
!(error=table->file->update_row(table->record[1], table->record[0])))
+ {
updated++;
+ table->file->extra(HA_EXTRA_NO_CACHE);
+ }
else
{
table->file->print_error(error,MYF(0));
@@ -646,13 +665,13 @@ void multi_update::send_error(uint errcode,const char *err)
::send_error(&thd->net,errcode,err);
/* reset used flags */
-// update_tables->table->no_keyread=0;
+ // update_tables->table->no_keyread=0;
/* If nothing updated return */
if (!updated)
return;
- /* Somthing alredy updated consequently we have to invalidate cache */
+ /* Something already updated so we have to invalidate cache */
query_cache_invalidate3(thd, update_tables, 1);
/* Below can happen when thread is killed early ... */
@@ -668,7 +687,7 @@ void multi_update::send_error(uint errcode,const char *err)
if ((table_being_updated->table->file->has_transactions() &&
table_being_updated == update_tables) || !not_trans_safe)
ha_rollback_stmt(thd);
- else if (do_update)
+ else if (do_update && num_updated > 1)
VOID(do_updates(true));
}
@@ -677,8 +696,6 @@ int multi_update::do_updates (bool from_send_error)
{
int error = 0, counter = 0;
- if (num_updated == 1)
- return 0;
if (from_send_error)
{
/* Found out table number for 'table_being_updated' */
@@ -779,7 +796,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);
+ Query_log_event qinfo(thd, thd->query, thd->query_length);
/*
mysql_bin_log is not open if binlogging or replication
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 01894bfb7ad..8571cb9af6d 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -53,6 +53,12 @@ inline Item *or_or_concat(Item* A, Item* B)
Item *item;
List<Item> *item_list;
List<String> *string_list;
+ String *string;
+ key_part_spec *key_part;
+ TABLE_LIST *table_list;
+ udf_func *udf;
+ LEX_USER *lex_user;
+ sys_var *variable;
Key::Keytype key_type;
enum ha_key_alg key_alg;
enum db_type db_type;
@@ -60,13 +66,8 @@ inline Item *or_or_concat(Item* A, Item* B)
enum ha_rkey_function ha_rkey_mode;
enum enum_tx_isolation tx_isolation;
enum Item_cast cast_type;
- String *string;
- key_part_spec *key_part;
- TABLE_LIST *table_list;
- udf_func *udf;
- interval_type interval;
- LEX_USER *lex_user;
enum Item_udftype udf_type;
+ interval_type interval;
}
%{
@@ -82,7 +83,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token LAST_SYM
%token NEXT_SYM
%token PREV_SYM
-%token SQL_CALC_FOUND_ROWS
%token EQ
%token EQUAL_SYM
@@ -96,50 +96,56 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token SHIFT_RIGHT
%token SET_VAR
-%token AVG_SYM
-%token COUNT_SYM
-%token MAX_SYM
-%token MIN_SYM
-%token SUM_SYM
-%token STD_SYM
-%token ABORT_SYM
+%token ABORT_SYM
%token ADD
-%token ALTER
%token AFTER_SYM
-%token ANALYZE_SYM
-%token BEGIN_SYM
+%token ALTER
+%token ANALYZE_SYM
+%token AVG_SYM
+%token BEGIN_SYM
+%token BINLOG_SYM
%token CHANGE
-%token COMMENT_SYM
-%token COMMIT_SYM
+%token CLIENT_SYM
+%token COMMENT_SYM
+%token COMMIT_SYM
+%token COUNT_SYM
%token CREATE
%token CROSS
+%token CUBE_SYM
%token DELETE_SYM
%token DO_SYM
%token DROP
-%token INSERT
+%token EVENTS_SYM
+%token EXECUTE_SYM
%token FLUSH_SYM
-%token SELECT_SYM
-%token MASTER_SYM
-%token REPAIR
-%token RESET_SYM
-%token PURGE
-%token SLAVE
-%token IO_THREAD
-%token SQL_THREAD
-%token START_SYM
-%token STOP_SYM
-%token TRUNCATE_SYM
-%token ROLLBACK_SYM
-%token OPTIMIZE
-%token SHOW
-%token UPDATE_SYM
+%token INSERT
+%token IO_THREAD
%token KILL_SYM
%token LOAD
-%token LOCK_SYM
%token LOCKS_SYM
+%token LOCK_SYM
+%token MASTER_SYM
+%token MAX_SYM
+%token MIN_SYM
+%token OPTIMIZE
+%token PURGE
+%token REPAIR
+%token REPLICATION
+%token RESET_SYM
+%token ROLLBACK_SYM
+%token ROLLUP_SYM
+%token SELECT_SYM
+%token SHOW
+%token SLAVE
+%token SQL_THREAD
+%token START_SYM
+%token STD_SYM
+%token STOP_SYM
+%token SUM_SYM
+%token SUPER_SYM
+%token TRUNCATE_SYM
%token UNLOCK_SYM
-%token BINLOG_SYM
-%token EVENTS_SYM
+%token UPDATE_SYM
%token ACTION
%token AGGREGATE_SYM
@@ -148,9 +154,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token AS
%token ASC
%token AUTO_INC
-%token AUTOCOMMIT
%token AVG_ROW_LENGTH
-%token BACKUP_SYM
+%token BACKUP_SYM
%token BERKELEY_DB_SYM
%token BINARY
%token BIT_SYM
@@ -178,7 +183,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token DEFAULT
%token DELAYED_SYM
%token DELAY_KEY_WRITE_SYM
-%token DEMAND_SYM
%token DESC
%token DESCRIBE
%token DES_KEY_FILE
@@ -188,7 +192,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token ENABLE_SYM
%token ENCLOSED
%token ESCAPED
-%token DIRECTORY_SYM
+%token DIRECTORY_SYM
%token ESCAPE_SYM
%token EXISTS
%token EXTENDED_SYM
@@ -199,8 +203,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token FOREIGN
%token FROM
%token FULL
-%token FULLTEXT_SYM
-%token GLOBAL_SYM
+%token FULLTEXT_SYM
+%token GLOBAL_SYM
%token GRANT
%token GRANTS
%token GREATEST_SYM
@@ -220,7 +224,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token INNOBASE_SYM
%token INTO
%token IN_SYM
-%token ISOLATION
+%token ISOLATION
%token ISAM_SYM
%token ISSUER
%token JOIN_SYM
@@ -228,44 +232,45 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token KEY_SYM
%token LEADING
%token LEAST_SYM
-%token LEVEL_SYM
+%token LEVEL_SYM
%token LEX_HOSTNAME
%token LIKE
%token LINES
%token LOCAL_SYM
+%token LOG_SYM
%token LOGS_SYM
%token LONG_NUM
%token LONG_SYM
%token LOW_PRIORITY
-%token MASTER_HOST_SYM
-%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
-%token MASTER_SERVER_ID_SYM
-%token RELAY_LOG_FILE_SYM
-%token RELAY_LOG_POS_SYM
+%token MASTER_HOST_SYM
+%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
+%token MASTER_SERVER_ID_SYM
+%token RELAY_LOG_FILE_SYM
+%token RELAY_LOG_POS_SYM
%token MATCH
%token MAX_ROWS
-%token MAX_CONNECTIONS_PER_HOUR
-%token MAX_QUERIES_PER_HOUR
-%token MAX_UPDATES_PER_HOUR
+%token MAX_CONNECTIONS_PER_HOUR
+%token MAX_QUERIES_PER_HOUR
+%token MAX_UPDATES_PER_HOUR
%token MEDIUM_SYM
%token MERGE_SYM
%token MIN_ROWS
%token MYISAM_SYM
%token NATIONAL_SYM
%token NATURAL
-%token NEW_SYM
+%token NEW_SYM
%token NCHAR_SYM
%token NOT
+%token NO_FOREIGN_KEY_CHECKS
%token NO_SYM
%token NULL_SYM
%token NUM
-%token OFF
%token ON
%token OPEN_SYM
%token OPTION
@@ -275,7 +280,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token ORDER_SYM
%token OUTER
%token OUTFILE
-%token DUMPFILE
+%token DUMPFILE
%token PACK_KEYS_SYM
%token PARTIAL
%token PRIMARY_SYM
@@ -292,12 +297,13 @@ 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
%token REQUIRE_SYM
-%token RESOURCES
-%token RESTORE_SYM
+%token RESOURCES
+%token RESTORE_SYM
%token RESTRICT
%token REVOKE
%token ROWS_SYM
@@ -310,8 +316,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token SIMPLE_SYM
%token SHUTDOWN
%token SPATIAL_SYM
-%token SQL_CACHE_SYM
-%token SQL_NO_CACHE_SYM
%token SSL_SYM
%token STARTING
%token STATUS_SYM
@@ -334,7 +338,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token UDF_RETURNS_SYM
%token UDF_SONAME_SYM
%token UDF_SYM
-%token UNCOMMITTED_SYM
+%token UNCOMMITTED_SYM
%token UNDERSCORE_CHARSET
%token UNION_SYM
%token UNIQUE_SYM
@@ -347,8 +351,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token WHERE
%token WITH
%token WRITE_SYM
-%token X509_SYM
-%token COMPRESSED_SYM
+%token X509_SYM
+%token XOR
+%token COMPRESSED_SYM
%token ERRORS
%token SQL_ERROR_COUNT
@@ -358,7 +363,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token BIGINT
%token BLOB_SYM
%token CHAR_SYM
-%token CHANGED
+%token CHANGED
%token COALESCE
%token DATETIME
%token DATE_SYM
@@ -377,7 +382,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token MEDIUMTEXT
%token NUMERIC_SYM
%token PRECISION
-%token QUICK
+%token QUICK
%token REAL
%token SIGNED_SYM
%token SMALLINT
@@ -395,14 +400,14 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token VARYING
%token ZEROFILL
-%token AGAINST
+%token AGAINST
%token ATAN
%token BETWEEN_SYM
%token BIT_AND
%token BIT_OR
%token CASE_SYM
%token CONCAT
-%token CONCAT_WS
+%token CONCAT_WS
%token CURDATE
%token CURTIME
%token DATABASE
@@ -434,7 +439,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token HOUR_SYM
%token IDENTIFIED_SYM
%token IF
-%token INSERT_ID
%token INSERT_METHOD
%token INTERVAL_SYM
%token LAST_INSERT_ID
@@ -445,7 +449,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token MAKE_SET_SYM
%token MINUTE_SECOND_SYM
%token MINUTE_SYM
-%token MODE_SYM
+%token MODE_SYM
%token MODIFY_SYM
%token MONTH_SYM
%token MLINEFROMTEXT
@@ -481,31 +485,20 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token USER
%token WEEK_SYM
%token WHEN_SYM
-%token WORK_SYM
+%token WORK_SYM
%token YEAR_MONTH_SYM
%token YEAR_SYM
%token YEARWEEK
-%token BENCHMARK_SYM
-%token END
-%token THEN_SYM
-
-%token SQL_BIG_TABLES
-%token SQL_BIG_SELECTS
-%token SQL_SELECT_LIMIT
-%token SQL_MAX_JOIN_SIZE
-%token SQL_LOG_BIN
-%token SQL_LOG_OFF
-%token SQL_LOG_UPDATE
-%token SQL_LOW_PRIORITY_UPDATES
-%token SQL_SMALL_RESULT
+%token BENCHMARK_SYM
+%token END
+%token THEN_SYM
+
%token SQL_BIG_RESULT
+%token SQL_CACHE_SYM
+%token SQL_CALC_FOUND_ROWS
+%token SQL_NO_CACHE_SYM
+%token SQL_SMALL_RESULT
%token SQL_BUFFER_RESULT
-%token SQL_WARNINGS
-%token SQL_AUTO_IS_NULL
-%token SQL_SAFE_UPDATES
-%token SQL_QUERY_CACHE_TYPE_SYM
-%token SQL_QUOTE_SHOW_CREATE
-%token SQL_SLAVE_SKIP_COUNTER
%token ISSUER_SYM
%token SUBJECT_SYM
@@ -522,6 +515,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%left '-' '+'
%left '*' '/' '%'
%left NEG '~'
+%left XOR
+%left '^'
%right NOT
%right BINARY COLLATE_SYM
@@ -543,9 +538,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
text_string
%type <num>
- type int_type real_type order_dir opt_field_spec set_option lock_option
+ 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 delete_option
+ table_option opt_if_not_exists opt_var_type opt_var_ident_type
+ delete_option
%type <ulong_num>
ULONG_NUM raid_types merge_insert_types
@@ -557,7 +553,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
literal text_literal insert_ident order_ident
simple_ident select_item2 expr opt_expr opt_else sum_expr in_sum_expr
table_wild opt_pad no_in_expr expr_expr simple_expr no_and_expr
- using_list param_marker singleval_subselect singleval_subselect_init
+ using_list expr_or_default set_expr_or_default
+ param_marker singleval_subselect singleval_subselect_init
exists_subselect exists_subselect_init
%type <item_list>
@@ -588,7 +585,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%type <row_type> row_types
-%type <tx_isolation> tx_isolation isolation_types
+%type <tx_isolation> isolation_types
%type <ha_rkey_mode> handler_rkey_mode
@@ -600,6 +597,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%type <lex_user> user grant_user
+%type <variable> internal_variable_name
+
%type <NONE>
query verb_clause create change select do drop insert replace insert2
insert_values update delete truncate rename
@@ -703,8 +702,7 @@ change:
master_defs:
master_def
- |
- master_defs ',' master_def;
+ | master_defs ',' master_def;
master_def:
MASTER_HOST_SYM EQ TEXT_STRING
@@ -770,7 +768,7 @@ create:
lex->change=NullS;
bzero((char*) &lex->create_info,sizeof(lex->create_info));
lex->create_info.options=$2 | $4;
- lex->create_info.db_type= default_table_type;
+ lex->create_info.db_type= (enum db_type) lex->thd->variables.table_type;
lex->create_info.table_charset=NULL;
}
create2
@@ -1395,19 +1393,15 @@ slave:
lex->type = 0;
};
-slave_thread_opts: slave_thread_opt
- | slave_thread_opts ',' slave_thread_opt;
+slave_thread_opts:
+ slave_thread_opt
+ | slave_thread_opts ',' slave_thread_opt;
slave_thread_opt:
- /*empty*/ {}
- | SQL_THREAD
- {
- Lex->slave_thd_opt|=SLAVE_SQL;
- }
- | IO_THREAD
- {
- Lex->slave_thd_opt|=SLAVE_IO;
- };
+ /*empty*/ {}
+ | SQL_THREAD { Lex->slave_thd_opt|=SLAVE_SQL; }
+ | IO_THREAD { Lex->slave_thd_opt|=SLAVE_IO; }
+ ;
restore:
RESTORE_SYM table_or_tables
@@ -1418,6 +1412,7 @@ restore:
{
Lex->backup_dir = $6.str;
};
+
backup:
BACKUP_SYM table_or_tables
{
@@ -1558,22 +1553,51 @@ select_option_list:
select_option:
STRAIGHT_JOIN { Select->options|= SELECT_STRAIGHT_JOIN; }
- | HIGH_PRIORITY { if (Select != &Lex->select_lex) YYABORT; Lex->lock_option= TL_READ_HIGH_PRIORITY; }
+ | HIGH_PRIORITY
+ {
+ if (check_simple_select())
+ YYABORT;
+ Lex->lock_option= TL_READ_HIGH_PRIORITY;
+ }
| DISTINCT { Select->options|= SELECT_DISTINCT; }
| SQL_SMALL_RESULT { Select->options|= SELECT_SMALL_RESULT; }
| SQL_BIG_RESULT { Select->options|= SELECT_BIG_RESULT; }
- | SQL_BUFFER_RESULT { if (Select != &Lex->select_lex) YYABORT; Select->options|= OPTION_BUFFER_RESULT; }
- | SQL_CALC_FOUND_ROWS { if (Select != &Lex->select_lex) YYABORT; Select->options|= OPTION_FOUND_ROWS; }
- | SQL_NO_CACHE_SYM { if (Select != &Lex->select_lex) YYABORT; current_thd->safe_to_cache_query=0; }
- | SQL_CACHE_SYM { if (Select != &Lex->select_lex) YYABORT; Select->options |= OPTION_TO_QUERY_CACHE; }
- | ALL {};
+ | SQL_BUFFER_RESULT
+ {
+ if (check_simple_select())
+ YYABORT;
+ Select->options|= OPTION_BUFFER_RESULT;
+ }
+ | SQL_CALC_FOUND_ROWS
+ {
+ if (check_simple_select())
+ YYABORT;
+ Select->options|= OPTION_FOUND_ROWS;
+ }
+ | SQL_NO_CACHE_SYM { current_thd->safe_to_cache_query=0; }
+ | SQL_CACHE_SYM { Select->options|= OPTION_TO_QUERY_CACHE; }
+ | ALL {}
+ ;
select_lock_type:
/* empty */
| FOR_SYM UPDATE_SYM
- { if (Select != &Lex->select_lex) YYABORT; Lex->lock_option= TL_WRITE; current_thd->safe_to_cache_query=0; }
+ {
+ LEX *lex=Lex;
+ if (check_simple_select())
+ YYABORT;
+ lex->lock_option= TL_WRITE;
+ lex->thd->safe_to_cache_query=0;
+ }
| LOCK_SYM IN_SYM SHARE_SYM MODE_SYM
- { if (Select != &Lex->select_lex) YYABORT; Lex->lock_option= TL_READ_WITH_SHARED_LOCKS; current_thd->safe_to_cache_query=0; };
+ {
+ LEX *lex=Lex;
+ if (check_simple_select())
+ YYABORT;
+ lex->lock_option= TL_READ_WITH_SHARED_LOCKS;
+ lex->thd->safe_to_cache_query=0;
+ }
+ ;
select_item_list:
select_item_list ',' select_item
@@ -1633,6 +1657,7 @@ expr_expr:
{ $$= new Item_func_not(new Item_func_between($1,$4,$6)); }
| expr OR_OR_CONCAT expr { $$= or_or_concat($1,$3); }
| expr OR expr { $$= new Item_cond_or($1,$3); }
+ | expr XOR expr { $$= new Item_cond_xor($1,$3); }
| expr AND expr { $$= new Item_cond_and($1,$3); }
| expr LIKE simple_expr opt_escape { $$= new Item_func_like($1,$3,$4); }
| expr NOT LIKE simple_expr opt_escape { $$= new Item_func_not(new Item_func_like($1,$4,$5));}
@@ -1654,6 +1679,7 @@ expr_expr:
| expr '*' expr { $$= new Item_func_mul($1,$3); }
| expr '/' expr { $$= new Item_func_div($1,$3); }
| expr '|' expr { $$= new Item_func_bit_or($1,$3); }
+ | expr '^' expr { $$= new Item_func_bit_xor($1,$3); }
| expr '&' expr { $$= new Item_func_bit_and($1,$3); }
| expr '%' expr { $$= new Item_func_mod($1,$3); }
| expr '+' INTERVAL_SYM expr interval
@@ -1678,6 +1704,7 @@ no_in_expr:
{ $$= new Item_func_not(new Item_func_between($1,$4,$6)); }
| no_in_expr OR_OR_CONCAT expr { $$= or_or_concat($1,$3); }
| no_in_expr OR expr { $$= new Item_cond_or($1,$3); }
+ | no_in_expr XOR expr { $$= new Item_cond_xor($1,$3); }
| no_in_expr AND expr { $$= new Item_cond_and($1,$3); }
| no_in_expr LIKE simple_expr opt_escape { $$= new Item_func_like($1,$3,$4); }
| no_in_expr NOT LIKE simple_expr opt_escape { $$= new Item_func_not(new Item_func_like($1,$4,$5)); }
@@ -1699,6 +1726,7 @@ no_in_expr:
| no_in_expr '*' expr { $$= new Item_func_mul($1,$3); }
| no_in_expr '/' expr { $$= new Item_func_div($1,$3); }
| no_in_expr '|' expr { $$= new Item_func_bit_or($1,$3); }
+ | no_in_expr '^' expr { $$= new Item_func_bit_xor($1,$3); }
| no_in_expr '&' expr { $$= new Item_func_bit_and($1,$3); }
| no_in_expr '%' expr { $$= new Item_func_mod($1,$3); }
| no_in_expr '+' INTERVAL_SYM expr interval
@@ -1719,6 +1747,7 @@ no_and_expr:
{ $$= new Item_func_not(new Item_func_between($1,$4,$6)); }
| no_and_expr OR_OR_CONCAT expr { $$= or_or_concat($1,$3); }
| no_and_expr OR expr { $$= new Item_cond_or($1,$3); }
+ | no_and_expr XOR expr { $$= new Item_cond_xor($1,$3); }
| no_and_expr LIKE simple_expr opt_escape { $$= new Item_func_like($1,$3,$4); }
| no_and_expr NOT LIKE simple_expr opt_escape { $$= new Item_func_not(new Item_func_like($1,$4,$5)); }
| no_and_expr REGEXP expr { $$= new Item_func_regex($1,$3); }
@@ -1739,6 +1768,7 @@ no_and_expr:
| no_and_expr '*' expr { $$= new Item_func_mul($1,$3); }
| no_and_expr '/' expr { $$= new Item_func_div($1,$3); }
| no_and_expr '|' expr { $$= new Item_func_bit_or($1,$3); }
+ | no_and_expr '^' expr { $$= new Item_func_bit_xor($1,$3); }
| no_and_expr '&' expr { $$= new Item_func_bit_and($1,$3); }
| no_and_expr '%' expr { $$= new Item_func_mod($1,$3); }
| no_and_expr '+' INTERVAL_SYM expr interval
@@ -1752,16 +1782,19 @@ simple_expr:
| literal
| param_marker
| '@' ident_or_text SET_VAR expr
- { $$= new Item_func_set_user_var($2,$4);
+ {
+ $$= new Item_func_set_user_var($2,$4);
current_thd->safe_to_cache_query=0;
}
| '@' ident_or_text
- { $$= new Item_func_get_user_var($2);
+ {
+ $$= new Item_func_get_user_var($2);
current_thd->safe_to_cache_query=0;
}
- | '@' '@' ident_or_text
- { if (!($$= get_system_var($3))) YYABORT;
- current_thd->safe_to_cache_query=0;
+ | '@' '@' opt_var_ident_type ident_or_text
+ {
+ if (!($$= get_system_var((enum_var_type) $3, $4)))
+ YYABORT;
}
| sum_expr
| '-' expr %prec NEG { $$= new Item_func_neg($2); }
@@ -1914,6 +1947,10 @@ simple_expr:
{ $5->push_front($3); $$= new Item_func_max(*$5); }
| LEAST_SYM '(' expr ',' expr_list ')'
{ $5->push_front($3); $$= new Item_func_min(*$5); }
+ | LOG_SYM '(' expr ')'
+ { $$= new Item_func_log($3); }
+ | LOG_SYM '(' expr ',' expr ')'
+ { $$= new Item_func_log($3, $5); }
| LINEFROMTEXT '(' expr ')'
{ $$= new Item_func_geometry_from_text($3); }
| LINEFROMTEXT '(' expr ',' expr ')'
@@ -2232,7 +2269,8 @@ join_table:
{
SELECT_LEX *sel=Select;
if (!($$=add_table_to_list($2,$3,0,TL_UNLOCK, sel->use_index_ptr,
- sel->ignore_index_ptr))) YYABORT;
+ sel->ignore_index_ptr)))
+ YYABORT;
}
| '{' ident join_table LEFT OUTER JOIN_SYM join_table ON expr '}'
{ add_join_on($7,$9); $7->outer_join|=JOIN_TYPE_LEFT; $$=$7; }
@@ -2356,7 +2394,7 @@ opt_escape:
group_clause:
/* empty */
- | GROUP BY group_list;
+ | GROUP BY group_list olap_opt;
group_list:
group_list ',' order_ident order_dir
@@ -2364,6 +2402,26 @@ group_list:
| order_ident order_dir
{ if (add_group_to_list($1,(bool) $2)) YYABORT; };
+olap_opt:
+ /* empty */ {}
+ | WITH CUBE_SYM
+ {
+ LEX *lex=Lex;
+ lex->olap = true;
+ lex->select->olap= CUBE_TYPE;
+ net_printf(&lex->thd->net, ER_NOT_SUPPORTED_YET, "CUBE");
+ YYABORT; /* To be deleted in 4.1 */
+ }
+ | WITH ROLLUP_SYM
+ {
+ LEX *lex=Lex;
+ lex->olap = true;
+ lex->select->olap= ROLLUP_TYPE;
+ net_printf(&lex->thd->net, ER_NOT_SUPPORTED_YET, "ROLLUP");
+ YYABORT; /* To be deleted in 4.1 */
+ }
+ ;
+
/*
Order by statement in select
*/
@@ -2377,7 +2435,17 @@ order_clause:
{
LEX *lex=Lex;
if (lex->sql_command == SQLCOM_MULTI_UPDATE)
+ {
+ net_printf(&lex->thd->net, ER_WRONG_USAGE, "UPDATE", "ORDER BY");
+ YYABORT;
+ }
+ if (lex->select->olap != UNSPECIFIED_OLAP_TYPE)
+ {
+ net_printf(&lex->thd->net, ER_WRONG_USAGE,
+ "CUBE/ROLLUP",
+ "ORDER BY");
YYABORT;
+ }
} order_list;
order_list:
@@ -2396,14 +2464,29 @@ limit_clause:
/* empty */ {}
| LIMIT ULONG_NUM
{
+ LEX *lex=Lex;
+ if (lex->select->olap != UNSPECIFIED_OLAP_TYPE)
+ {
+ net_printf(&lex->thd->net, ER_WRONG_USAGE, "CUBE/ROLLUP",
+ "LIMIT");
+ YYABORT;
+ }
SELECT_LEX *sel=Select;
sel->select_limit= $2;
- sel->offset_limit=0L;
+ sel->offset_limit= 0L;
}
| LIMIT ULONG_NUM ',' ULONG_NUM
{
- SELECT_LEX *sel=Select;
- sel->select_limit= $4; sel->offset_limit=$2;
+ LEX *lex=Lex;
+ if (lex->select->olap != UNSPECIFIED_OLAP_TYPE)
+ {
+ net_printf(&lex->thd->net, ER_WRONG_USAGE, "CUBE/ROLLUP",
+ "LIMIT");
+ YYABORT;
+ }
+ SELECT_LEX *sel=lex->select;
+ sel->select_limit= $4;
+ sel->offset_limit= $2;
};
delete_limit_clause:
@@ -2411,7 +2494,10 @@ delete_limit_clause:
{
LEX *lex=Lex;
if (lex->sql_command == SQLCOM_MULTI_UPDATE)
+ {
+ net_printf(&lex->thd->net, ER_WRONG_USAGE, "DELETE", "LIMIT");
YYABORT;
+ }
lex->select->select_limit= HA_POS_ERROR;
}
| LIMIT ulonglong_num
@@ -2617,7 +2703,7 @@ ident_eq_list:
ident_eq_value;
ident_eq_value:
- simple_ident equal expr
+ simple_ident equal expr_or_default
{
LEX *lex=Lex;
if (lex->field_list.push_back($1) ||
@@ -2626,7 +2712,13 @@ ident_eq_value:
};
equal: EQ {}
- | SET_VAR {};
+ | SET_VAR {}
+ ;
+
+opt_equal:
+ /* empty */ {}
+ | equal {}
+ ;
no_braces:
'('
@@ -2646,16 +2738,22 @@ opt_values:
| values;
values:
- values ',' expr
+ values ',' expr_or_default
{
if (Lex->insert_list->push_back($3))
YYABORT;
}
- | expr
- {
- if (Lex->insert_list->push_back($1))
- YYABORT;
- };
+ | expr_or_default
+ {
+ if (Lex->insert_list->push_back($1))
+ YYABORT;
+ }
+ ;
+
+expr_or_default:
+ expr { $$= $1;}
+ | DEFAULT {$$= new Item_default(); }
+ ;
/* Update rows in a table */
@@ -2810,7 +2908,7 @@ show_param:
{
LEX *lex=Lex;
lex->sql_command = SQLCOM_SHOW_BINLOG_EVENTS;
- lex->select->select_limit= lex->thd->default_select_limit;
+ lex->select->select_limit= lex->thd->variables.select_limit;
lex->select->offset_limit= 0L;
} limit_clause
| keys_or_index FROM table_ident opt_db
@@ -2846,10 +2944,16 @@ show_param:
{ Lex->sql_command = SQLCOM_SHOW_ERRORS;}
| STATUS_SYM wild
{ Lex->sql_command= SQLCOM_SHOW_STATUS; }
+ | INNOBASE_SYM STATUS_SYM
+ { Lex->sql_command = SQLCOM_SHOW_INNODB_STATUS;}
| opt_full PROCESSLIST_SYM
{ Lex->sql_command= SQLCOM_SHOW_PROCESSLIST;}
- | VARIABLES wild
- { Lex->sql_command= SQLCOM_SHOW_VARIABLES; }
+ | opt_var_type VARIABLES wild
+ {
+ THD *thd= current_thd;
+ thd->lex.sql_command= SQLCOM_SHOW_VARIABLES;
+ thd->lex.option_type= (enum_var_type) $1;
+ }
| CHAR_SYM SET wild
{ Lex->sql_command= SQLCOM_SHOW_CHARSETS; }
| LOGS_SYM
@@ -2957,11 +3061,12 @@ flush_option:
| STATUS_SYM { Lex->type|= REFRESH_STATUS; }
| SLAVE { Lex->type|= REFRESH_SLAVE; }
| MASTER_SYM { Lex->type|= REFRESH_MASTER; }
- | DES_KEY_FILE { Lex->type|= REFRESH_DES_KEY_FILE; };
+ | DES_KEY_FILE { Lex->type|= REFRESH_DES_KEY_FILE; }
+ | RESOURCES { Lex->type|= REFRESH_USER_RESOURCES; };
opt_table_list:
- /* empty */ {}
- | table_list {};
+ /* empty */ {;}
+ | table_list {;};
reset:
RESET_SYM
@@ -3226,7 +3331,6 @@ keyword:
| AFTER_SYM {}
| AGAINST {}
| AGGREGATE_SYM {}
- | AUTOCOMMIT {}
| AUTO_INC {}
| AVG_ROW_LENGTH {}
| AVG_SYM {}
@@ -3242,18 +3346,19 @@ keyword:
| CHECKSUM_SYM {}
| CHECK_SYM {}
| CIPHER_SYM {}
+ | CLIENT_SYM {}
| CLOSE_SYM {}
| COMMENT_SYM {}
| COMMITTED_SYM {}
| COMMIT_SYM {}
| COMPRESSED_SYM {}
| CONCURRENT {}
+ | CUBE_SYM {}
| DATA_SYM {}
| DATETIME {}
| DATE_SYM {}
| DAY_SYM {}
| DELAY_KEY_WRITE_SYM {}
- | DEMAND_SYM {}
| DES_KEY_FILE {}
| DIRECTORY_SYM {}
| DO_SYM {}
@@ -3263,16 +3368,17 @@ keyword:
| ENUM {}
| ESCAPE_SYM {}
| EVENTS_SYM {}
+ | EXECUTE_SYM {}
| EXTENDED_SYM {}
| FAST_SYM {}
- | DISABLE_SYM {}
- | ENABLE_SYM {}
+ | DISABLE_SYM {}
+ | ENABLE_SYM {}
| FULL {}
| FILE_SYM {}
| FIRST_SYM {}
| FIXED_SYM {}
| FLUSH_SYM {}
- | GRANTS {}
+ | GRANTS {}
| GLOBAL_SYM {}
| HEAP_SYM {}
| HANDLER_SYM {}
@@ -3285,7 +3391,7 @@ keyword:
| ISSUER_SYM {}
| INNOBASE_SYM {}
| INSERT_METHOD {}
- | IO_THREAD {}
+ | IO_THREAD {}
| LAST_SYM {}
| LEVEL_SYM {}
| LOCAL_SYM {}
@@ -3300,9 +3406,9 @@ keyword:
| MASTER_USER_SYM {}
| MASTER_PASSWORD_SYM {}
| MASTER_CONNECT_RETRY_SYM {}
- | MAX_CONNECTIONS_PER_HOUR {}
- | MAX_QUERIES_PER_HOUR {}
- | MAX_UPDATES_PER_HOUR {}
+ | MAX_CONNECTIONS_PER_HOUR {}
+ | MAX_QUERIES_PER_HOUR {}
+ | MAX_UPDATES_PER_HOUR {}
| MEDIUM_SYM {}
| MERGE_SYM {}
| MINUTE_SYM {}
@@ -3316,7 +3422,6 @@ keyword:
| NEXT_SYM {}
| NEW_SYM {}
| NO_SYM {}
- | OFF {}
| OPEN_SYM {}
| PACK_KEYS_SYM {}
| PARTIAL {}
@@ -3326,20 +3431,22 @@ keyword:
| PROCESSLIST_SYM {}
| QUERY_SYM {}
| QUICK {}
- | RAID_0_SYM {}
+ | RAID_0_SYM {}
| RAID_CHUNKS {}
| RAID_CHUNKSIZE {}
- | RAID_STRIPED_SYM {}
+ | RAID_STRIPED_SYM {}
| RAID_TYPE {}
- | RELAY_LOG_FILE_SYM {}
- | RELAY_LOG_POS_SYM {}
+ | RELAY_LOG_FILE_SYM {}
+ | RELAY_LOG_POS_SYM {}
| RELOAD {}
| REPAIR {}
| REPEATABLE_SYM {}
+ | REPLICATION {}
| RESET_SYM {}
| RESOURCES {}
| RESTORE_SYM {}
| ROLLBACK_SYM {}
+ | ROLLUP_SYM {}
| ROWS_SYM {}
| ROW_FORMAT_SYM {}
| ROW_SYM {}
@@ -3350,16 +3457,17 @@ keyword:
| SIMPLE_SYM {}
| SHARE_SYM {}
| SHUTDOWN {}
- | SLAVE {}
+ | SLAVE {}
| SQL_CACHE_SYM {}
+ | SQL_BUFFER_RESULT {}
| SQL_NO_CACHE_SYM {}
- | SQL_QUERY_CACHE_TYPE_SYM {}
- | SQL_THREAD {}
+ | SQL_THREAD {}
| START_SYM {}
| STATUS_SYM {}
| STOP_SYM {}
| STRING_SYM {}
| SUBJECT_SYM {}
+ | SUPER_SYM {}
| TEMPORARY {}
| TEXT_SYM {}
| TRANSACTION_SYM {}
@@ -3372,7 +3480,8 @@ keyword:
| USE_FRM {}
| VARIABLES {}
| WORK_SYM {}
- | YEAR_SYM {};
+ | YEAR_SYM {}
+ ;
/* Option functions */
@@ -3381,11 +3490,8 @@ set:
{
LEX *lex=Lex;
lex->sql_command= SQLCOM_SET_OPTION;
- lex->select->options=lex->thd->options;
- lex->select->select_limit=lex->thd->default_select_limit;
- lex->tx_isolation=lex->thd->tx_isolation;
- lex->option_type=0;
- lex->option_list.empty();
+ lex->option_type=OPT_DEFAULT;
+ lex->var_list.empty();
}
option_value_list;
@@ -3394,154 +3500,90 @@ opt_option:
| OPTION {};
option_value_list:
- option_value
- | GLOBAL_SYM { Lex->option_type=1; } option_value
- | LOCAL_SYM { Lex->option_type=0; } option_value
- | option_value_list ',' option_value;
+ option_type option_value
+ | option_value_list ',' option_type option_value;
+
+option_type:
+ /* empty */ {}
+ | GLOBAL_SYM { Lex->option_type= OPT_GLOBAL; }
+ | LOCAL_SYM { Lex->option_type= OPT_SESSION; }
+ | SESSION_SYM { Lex->option_type= OPT_SESSION; }
+ ;
+
+opt_var_type:
+ /* empty */ { $$=OPT_SESSION; }
+ | GLOBAL_SYM { $$=OPT_GLOBAL; }
+ | LOCAL_SYM { $$=OPT_SESSION; }
+ | SESSION_SYM { $$=OPT_SESSION; }
+ ;
+
+opt_var_ident_type:
+ /* empty */ { $$=OPT_DEFAULT; }
+ | GLOBAL_SYM '.' { $$=OPT_GLOBAL; }
+ | LOCAL_SYM '.' { $$=OPT_SESSION; }
+ | SESSION_SYM '.' { $$=OPT_SESSION; }
+ ;
option_value:
- set_option equal NUM
- {
- SELECT_LEX *sel=Select;
- if (atoi($3.str) == 0)
- sel->options&= ~$1;
- else
- sel->options|= $1;
- }
- | set_isolation
- | AUTOCOMMIT equal NUM
- {
- SELECT_LEX *sel=Select;
- if (atoi($3.str) != 0) /* Test NOT AUTOCOMMIT */
- sel->options&= ~(OPTION_NOT_AUTO_COMMIT);
- else
- sel->options|= OPTION_NOT_AUTO_COMMIT;
- }
- | SQL_SELECT_LIMIT equal ULONG_NUM
- {
- Select->select_limit= $3;
- }
- | SQL_SELECT_LIMIT equal DEFAULT
- {
- Select->select_limit= HA_POS_ERROR;
- }
- | SQL_MAX_JOIN_SIZE equal ULONG_NUM
- {
- LEX *lex=Lex;
- lex->thd->max_join_size= $3;
- lex->select->options&= ~OPTION_BIG_SELECTS;
- }
- | SQL_MAX_JOIN_SIZE equal DEFAULT
- {
- current_thd->max_join_size= HA_POS_ERROR;
- }
- | TIMESTAMP equal ULONG_NUM
- {
- current_thd->set_time((time_t) $3);
- }
- | TIMESTAMP equal DEFAULT
+ '@' ident_or_text equal expr
{
- current_thd->user_time=0;
+ Lex->var_list.push_back(new set_var_user(new Item_func_set_user_var($2,$4)));
}
- | LAST_INSERT_ID equal ulonglong_num
- {
- current_thd->insert_id($3);
- }
- | INSERT_ID equal ulonglong_num
- {
- current_thd->next_insert_id=$3;
- }
- | CHAR_SYM SET IDENT
- {
- CONVERT *tmp;
- if (!(tmp=get_convert_set($3.str)))
+ | internal_variable_name equal set_expr_or_default
{
- net_printf(&current_thd->net,ER_UNKNOWN_CHARACTER_SET,$3.str);
- YYABORT;
+ LEX *lex=Lex;
+ lex->var_list.push_back(new set_var(lex->option_type, $1, $3));
}
- current_thd->convert_set=tmp;
- }
- | CHAR_SYM SET DEFAULT
+ | '@' '@' opt_var_ident_type internal_variable_name equal set_expr_or_default
+ {
+ LEX *lex=Lex;
+ lex->var_list.push_back(new set_var((enum_var_type) $3, $4, $6));
+ }
+ | TRANSACTION_SYM ISOLATION LEVEL_SYM isolation_types
+ {
+ LEX *lex=Lex;
+ lex->var_list.push_back(new set_var(lex->option_type,
+ find_sys_var("tx_isolation"),
+ new Item_int((int) $4)));
+ }
+ | CHAR_SYM SET opt_equal set_expr_or_default
{
- current_thd->convert_set=0;
+ LEX *lex=Lex;
+ lex->var_list.push_back(new set_var(lex->option_type,
+ find_sys_var("convert_character_set"),
+ $4));
}
| PASSWORD equal text_or_password
- {
- if (change_password(current_thd,current_thd->host,
- current_thd->priv_user,$3))
- YYABORT;
- }
- | PASSWORD FOR_SYM user equal text_or_password
- {
- if (change_password(current_thd,
- $3->host.str ? $3->host.str : current_thd->host,
- $3->user.str,$5))
- YYABORT;
- }
- | SQL_QUERY_CACHE_TYPE_SYM equal query_cache_type
- | SQL_ERROR_COUNT equal ULONG_NUM
- {
- LEX *lex = Lex;
- lex->thd->max_error_count = $3;
- }
- | SQL_WARNING_COUNT equal ULONG_NUM
- {
- LEX *lex = Lex;
- lex->thd->max_warning_count = $3;
- }
- | '@' ident_or_text equal expr
- {
- Item_func_set_user_var *item = new Item_func_set_user_var($2,$4);
- if (item->fix_fields(current_thd, 0, (Item**) &item) ||
- item->update())
- {
- send_error(&current_thd->net, ER_SET_CONSTANTS_ONLY);
- YYABORT;
- }
- }
- | SQL_SLAVE_SKIP_COUNTER equal ULONG_NUM
- {
- LOCK_ACTIVE_MI;
- pthread_mutex_lock(&active_mi->rli.run_lock);
- if (active_mi->rli.slave_running)
- send_error(&current_thd->net, ER_SLAVE_MUST_STOP);
- else
- {
- pthread_mutex_lock(&active_mi->rli.data_lock);
- active_mi->rli.slave_skip_counter = $3;
- pthread_mutex_unlock(&active_mi->rli.data_lock);
- }
- pthread_mutex_unlock(&active_mi->rli.run_lock);
- UNLOCK_ACTIVE_MI;
- }
- | ident equal DEFAULT
{
- LEX *lex=Lex;
- lex->option_list.push_back(new Set_option(lex->option_type,
- $1.str,$1.length,
- (Item*) 0));
- }
- | ident equal expr
+ THD *thd=current_thd;
+ LEX_USER *user;
+ if (!(user=(LEX_USER*) sql_alloc(sizeof(LEX_USER))))
+ YYABORT;
+ user->host.str=0;
+ user->user.str=thd->priv_user;
+ thd->lex.var_list.push_back(new set_var_password(user, $3));
+ }
+ | PASSWORD FOR_SYM user equal text_or_password
{
- THD *thd=current_thd;
- Item *item= $3;
- if (item->fix_fields(current_thd, 0, &item))
- {
- send_error(&thd->net, ER_SET_CONSTANTS_ONLY);
- YYABORT;
- }
- thd->lex.option_list.
- push_back(new Set_option(thd->lex.option_type,
- $1.str,$1.length,
- item));
- };
+ Lex->var_list.push_back(new set_var_password($3,$5));
+ }
-query_cache_type:
- NUM { current_thd->query_cache_type = set_zone(atoi($1.str),0,3); }
- | OFF { current_thd->query_cache_type = 0; }
- | ON { current_thd->query_cache_type = 1; }
- | DEMAND_SYM { current_thd->query_cache_type = 2; };
+internal_variable_name:
+ ident
+ {
+ sys_var *tmp=find_sys_var($1.str, $1.length);
+ if (!tmp)
+ YYABORT;
+ $$=tmp;
+ }
+isolation_types:
+ READ_SYM UNCOMMITTED_SYM { $$= ISO_READ_UNCOMMITTED; }
+ | READ_SYM COMMITTED_SYM { $$= ISO_READ_COMMITTED; }
+ | REPEATABLE_SYM READ_SYM { $$= ISO_REPEATABLE_READ; }
+ | SERIALIZABLE_SYM { $$= ISO_SERIALIZABLE; }
+ ;
+
text_or_password:
TEXT_STRING { $$=$1.str;}
| PASSWORD '(' TEXT_STRING ')'
@@ -3556,54 +3598,14 @@ text_or_password:
}
};
-set_option:
- SQL_BIG_TABLES { $$= OPTION_BIG_TABLES; }
- | SQL_BIG_SELECTS { $$= OPTION_BIG_SELECTS; }
- | SQL_LOG_OFF { $$= OPTION_LOG_OFF; }
- | SQL_LOG_UPDATE
- {
- $$= (opt_sql_bin_update)?
- OPTION_UPDATE_LOG|OPTION_BIN_LOG:
- OPTION_UPDATE_LOG ;
- }
- | SQL_LOG_BIN
- {
- $$= (opt_sql_bin_update)?
- OPTION_UPDATE_LOG|OPTION_BIN_LOG:
- OPTION_BIN_LOG ;
- }
- | SQL_WARNINGS { $$= OPTION_WARNINGS; }
- | SQL_LOW_PRIORITY_UPDATES { $$= OPTION_LOW_PRIORITY_UPDATES; }
- | SQL_AUTO_IS_NULL { $$= OPTION_AUTO_IS_NULL; }
- | SQL_SAFE_UPDATES { $$= OPTION_SAFE_UPDATES; }
- | SQL_BUFFER_RESULT { $$= OPTION_BUFFER_RESULT; }
- | SQL_QUOTE_SHOW_CREATE { $$= OPTION_QUOTE_SHOW_CREATE; };
+set_expr_or_default:
+ expr { $$=$1; }
+ | DEFAULT { $$=0; }
+ | ON { $$=new Item_string("ON",2); }
+ | ALL { $$=new Item_string("ALL",3); }
+ ;
-set_isolation:
- GLOBAL_SYM tx_isolation
- {
- if (check_process_priv())
- YYABORT;
- default_tx_isolation= $2;
- default_tx_isolation_name=tx_isolation_typelib.type_names[default_tx_isolation];
- }
- | SESSION_SYM tx_isolation
- {
- LEX *lex=Lex;
- lex->thd->session_tx_isolation= lex->tx_isolation= $2;
- }
- | tx_isolation
- { Lex->tx_isolation= $1; };
-
-tx_isolation:
- TRANSACTION_SYM ISOLATION LEVEL_SYM isolation_types { $$=$4; };
-
-isolation_types:
- READ_SYM UNCOMMITTED_SYM { $$= ISO_READ_UNCOMMITTED; }
- | READ_SYM COMMITTED_SYM { $$= ISO_READ_COMMITTED; }
- | REPEATABLE_SYM READ_SYM { $$= ISO_REPEATABLE_READ; }
- | SERIALIZABLE_SYM { $$= ISO_SERIALIZABLE; };
/* Lock function */
@@ -3705,6 +3707,7 @@ revoke:
lex->columns.empty();
lex->grant= lex->grant_tot_col=0;
lex->select->db=0;
+ bzero((char*) &lex->mqh, sizeof(lex->mqh));
}
grant_privileges ON opt_table FROM user_list;
@@ -3726,88 +3729,91 @@ grant:
grant_privileges:
grant_privilege_list {}
- | ALL PRIVILEGES { Lex->grant = UINT_MAX;}
- | ALL { Lex->grant = UINT_MAX;};
+ | ALL PRIVILEGES { Lex->grant = GLOBAL_ACLS;}
+ | ALL { Lex->grant = GLOBAL_ACLS;};
grant_privilege_list:
grant_privilege
| grant_privilege_list ',' grant_privilege;
grant_privilege:
- SELECT_SYM
- { Lex->which_columns = SELECT_ACL;}
- opt_column_list
- | INSERT
- { Lex->which_columns = INSERT_ACL; }
- opt_column_list
- | UPDATE_SYM
- { Lex->which_columns = UPDATE_ACL; }
- opt_column_list
- | DELETE_SYM { Lex->grant |= DELETE_ACL;}
- | REFERENCES { Lex->which_columns = REFERENCES_ACL;} opt_column_list
- | USAGE {}
+ SELECT_SYM { Lex->which_columns = SELECT_ACL;} opt_column_list
+ | INSERT { Lex->which_columns = INSERT_ACL;} opt_column_list
+ | UPDATE_SYM { Lex->which_columns = UPDATE_ACL; } opt_column_list
+ | REFERENCES { Lex->which_columns = REFERENCES_ACL;} opt_column_list
+ | DELETE_SYM { Lex->grant |= DELETE_ACL;}
+ | USAGE {}
| INDEX { Lex->grant |= INDEX_ACL;}
| ALTER { Lex->grant |= ALTER_ACL;}
| CREATE { Lex->grant |= CREATE_ACL;}
| DROP { Lex->grant |= DROP_ACL;}
+ | EXECUTE_SYM { Lex->grant |= EXECUTE_ACL;}
| RELOAD { Lex->grant |= RELOAD_ACL;}
| SHUTDOWN { Lex->grant |= SHUTDOWN_ACL;}
| PROCESS { Lex->grant |= PROCESS_ACL;}
| FILE_SYM { Lex->grant |= FILE_ACL;}
- | GRANT OPTION { Lex->grant |= GRANT_ACL;};
+ | GRANT OPTION { Lex->grant |= GRANT_ACL;}
+ | SHOW DATABASES { Lex->grant |= SHOW_DB_ACL;}
+ | SUPER_SYM { Lex->grant |= SUPER_ACL;}
+ | CREATE TEMPORARY TABLES { Lex->grant |= CREATE_TMP_ACL;}
+ | LOCK_SYM TABLES { Lex->grant |= LOCK_TABLES_ACL; }
+ | REPLICATION SLAVE { Lex->grant |= REPL_SLAVE_ACL;}
+ | REPLICATION CLIENT_SYM { Lex->grant |= REPL_CLIENT_ACL;}
+ ;
require_list: require_list_element AND require_list
| require_list_element ;
require_list_element: SUBJECT_SYM TEXT_STRING
- {
- LEX *lex=Lex;
- if (lex->x509_subject)
- {
- net_printf(&lex->thd->net,ER_DUP_ARGUMENT, "SUBJECT");
- YYABORT;
- }
- lex->x509_subject=$2.str;
- }
- | ISSUER_SYM TEXT_STRING
- {
- LEX *lex=Lex;
- if (lex->x509_issuer)
- {
- net_printf(&lex->thd->net,ER_DUP_ARGUMENT, "ISSUER");
- YYABORT;
- }
- lex->x509_issuer=$2.str;
- }
- | CIPHER_SYM TEXT_STRING
- {
- LEX *lex=Lex;
- if (lex->ssl_cipher)
- {
- net_printf(&lex->thd->net,ER_DUP_ARGUMENT, "CIPHER");
- YYABORT;
- }
- lex->ssl_cipher=$2.str;
- };
+ {
+ LEX *lex=Lex;
+ if (lex->x509_subject)
+ {
+ net_printf(&lex->thd->net,ER_DUP_ARGUMENT, "SUBJECT");
+ YYABORT;
+ }
+ lex->x509_subject=$2.str;
+ }
+ | ISSUER_SYM TEXT_STRING
+ {
+ LEX *lex=Lex;
+ if (lex->x509_issuer)
+ {
+ net_printf(&lex->thd->net,ER_DUP_ARGUMENT, "ISSUER");
+ YYABORT;
+ }
+ lex->x509_issuer=$2.str;
+ }
+ | CIPHER_SYM TEXT_STRING
+ {
+ LEX *lex=Lex;
+ if (lex->ssl_cipher)
+ {
+ net_printf(&lex->thd->net,ER_DUP_ARGUMENT, "CIPHER");
+ YYABORT;
+ }
+ lex->ssl_cipher=$2.str;
+ }
+ ;
opt_table:
'*'
{
LEX *lex=Lex;
lex->select->db=lex->thd->db;
- if (lex->grant == UINT_MAX)
+ if (lex->grant == GLOBAL_ACLS)
lex->grant = DB_ACLS & ~GRANT_ACL;
else if (lex->columns.elements)
{
- send_error(&lex->thd->net,ER_ILLEGAL_GRANT_FOR_TABLE);
- YYABORT;
+ send_error(&lex->thd->net,ER_ILLEGAL_GRANT_FOR_TABLE);
+ YYABORT;
}
}
| ident '.' '*'
{
LEX *lex=Lex;
lex->select->db = $1.str;
- if (lex->grant == UINT_MAX)
+ if (lex->grant == GLOBAL_ACLS)
lex->grant = DB_ACLS & ~GRANT_ACL;
else if (lex->columns.elements)
{
@@ -3819,8 +3825,8 @@ opt_table:
{
LEX *lex=Lex;
lex->select->db = NULL;
- if (lex->grant == UINT_MAX)
- lex->grant = GLOBAL_ACLS & ~GRANT_ACL;
+ if (lex->grant == GLOBAL_ACLS)
+ lex->grant= GLOBAL_ACLS & ~GRANT_ACL;
else if (lex->columns.elements)
{
send_error(&lex->thd->net,ER_ILLEGAL_GRANT_FOR_TABLE);
@@ -3832,14 +3838,19 @@ opt_table:
LEX *lex=Lex;
if (!add_table_to_list($1,NULL,0))
YYABORT;
- if (lex->grant == UINT_MAX)
+ if (lex->grant == GLOBAL_ACLS)
lex->grant = TABLE_ACLS & ~GRANT_ACL;
};
user_list:
- grant_user { if (Lex->users_list.push_back($1)) YYABORT;}
- | user_list ',' grant_user { if (Lex->users_list.push_back($3)) YYABORT;};
+ grant_user { if (Lex->users_list.push_back($1)) YYABORT;}
+ | user_list ',' grant_user
+ {
+ if (Lex->users_list.push_back($3))
+ YYABORT;
+ }
+ ;
grant_user:
@@ -3920,25 +3931,28 @@ grant_option_list:
grant_option:
GRANT OPTION { Lex->grant |= GRANT_ACL;}
- | MAX_QUERIES_PER_HOUR EQ ULONG_NUM
+ | MAX_QUERIES_PER_HOUR ULONG_NUM
{
- Lex->mqh.questions=$3;
+ Lex->mqh.questions=$2;
+ Lex->mqh.bits |= 1;
}
- | MAX_UPDATES_PER_HOUR EQ ULONG_NUM
+ | MAX_UPDATES_PER_HOUR ULONG_NUM
{
- Lex->mqh.updates=$3;
+ Lex->mqh.updates=$2;
+ Lex->mqh.bits |= 2;
}
- | MAX_CONNECTIONS_PER_HOUR EQ ULONG_NUM
+ | MAX_CONNECTIONS_PER_HOUR ULONG_NUM
{
- Lex->mqh.connections=$3;
- }
+ Lex->mqh.connections=$2;
+ Lex->mqh.bits |= 4;
+ };
begin:
BEGIN_SYM { Lex->sql_command = SQLCOM_BEGIN;} opt_work;
opt_work:
/* empty */ {}
- | WORK_SYM {};
+ | WORK_SYM {;};
commit:
COMMIT_SYM { Lex->sql_command = SQLCOM_COMMIT;};
@@ -3948,93 +3962,102 @@ rollback:
/*
-** UNIONS : glue selects together
+ UNIONS : glue selects together
*/
union:
- /* empty */ {}
- | union_list;
+ /* empty */ {}
+ | union_list;
union_list:
- UNION_SYM union_option
- {
- LEX *lex=Lex;
- if (lex->exchange)
- {
- /* Only the last SELECT can have INTO...... */
- net_printf(&lex->thd->net, ER_WRONG_USAGE,"UNION","INTO");
- YYABORT;
- }
- if (lex->select->linkage == GLOBAL_OPTIONS_TYPE ||
- mysql_new_select(lex, 0))
- YYABORT;
- lex->select->linkage=UNION_TYPE;
- }
- select_init;
+ UNION_SYM union_option
+ {
+ LEX *lex=Lex;
+ if (lex->exchange)
+ {
+ /* Only the last SELECT can have INTO...... */
+ net_printf(&lex->thd->net, ER_WRONG_USAGE, "UNION", "INTO");
+ YYABORT;
+ }
+ if (lex->select->linkage == GLOBAL_OPTIONS_TYPE)
+ {
+ send_error(&lex->thd->net, ER_SYNTAX_ERROR);
+ YYABORT;
+ }
+ if (mysql_new_select(lex))
+ YYABORT;
+ lex->select->linkage=UNION_TYPE;
+ }
+ select_init
+ ;
union_opt:
- union {}
- | optional_order_or_limit {};
+ union {}
+ | optional_order_or_limit {};
optional_order_or_limit:
- /* empty */ {}
- |
- {
- LEX *lex=Lex;
- if (!lex->select->braces)
- YYABORT;
- lex->select->master_unit()->global_parameters=
- lex->select->master_unit();
- /*
- Following type conversion looks like hack, but all that need SELECT_LEX
- fields always check linkage type.
- */
- lex->select= (SELECT_LEX*)lex->select->master_unit();
- lex->select->select_limit=lex->thd->default_select_limit;
- }
- opt_order_clause limit_clause;
+ /* empty */ {}
+ |
+ {
+ LEX *lex=Lex;
+ if (!lex->select->braces)
+ {
+ send_error(&lex->thd->net, ER_SYNTAX_ERROR);
+ YYABORT;
+ }
+ lex->select->master_unit()->global_parameters=
+ lex->select->master_unit();
+ /*
+ Following type conversion looks like hack, but all that need
+ SELECT_LEX fields always check linkage type.
+ */
+ lex->select= (SELECT_LEX*)lex->select->master_unit();
+ lex->select->select_limit=lex->thd->default_select_limit;
+ }
+ opt_order_clause limit_clause
+ ;
union_option:
- /* empty */ {}
- | ALL {Lex->union_option=1;};
+ /* empty */ {}
+ | ALL {Lex->union_option=1;};
singleval_subselect:
- subselect_start singleval_subselect_init
- subselect_end
- {
- $$= $2;
- };
+ subselect_start singleval_subselect_init
+ subselect_end
+ {
+ $$= $2;
+ };
singleval_subselect_init:
- select_init
- {
- $$= new Item_singleval_subselect(current_thd, Lex->select);
- };
+ select_init
+ {
+ $$= new Item_singleval_subselect(current_thd, Lex->select);
+ };
exists_subselect:
- subselect_start exists_subselect_init
- subselect_end
- {
- $$= $2;
- };
+ subselect_start exists_subselect_init
+ subselect_end
+ {
+ $$= $2;
+ };
exists_subselect_init:
- select_init
- {
- $$= new Item_exists_subselect(current_thd, Lex->select);
- };
+ select_init
+ {
+ $$= new Item_exists_subselect(current_thd, Lex->select);
+ };
subselect_start:
- '('
- {
- if (mysql_new_select(Lex, 1))
- YYABORT;
- };
+ '('
+ {
+ if (mysql_new_select(Lex, 1))
+ YYABORT;
+ };
subselect_end:
- ')'
- {
- LEX *lex=Lex;
- lex->select = lex->select->outer_select();
- };
+ ')'
+ {
+ LEX *lex=Lex;
+ lex->select = lex->select->outer_select();
+ };
diff --git a/sql/stacktrace.c b/sql/stacktrace.c
index d86d65f567e..1aba73dda33 100644
--- a/sql/stacktrace.c
+++ b/sql/stacktrace.c
@@ -145,7 +145,7 @@ terribly wrong...\n");
fprintf(stderr, "Warning: Alpha stacks are difficult -\
will be taking some wild guesses, stack trace may be incorrect or \
terminate abruptly\n");
- // On Alpha, we need to get pc
+ /* On Alpha, we need to get pc */
__asm __volatile__ ("bsr %0, do_next; do_next: "
:"=r"(pc)
:"r"(pc));
@@ -210,8 +210,8 @@ resolve it\n");
void write_core(int sig)
{
signal(sig, SIG_DFL);
- if (fork() != 0) exit(1); // Abort main program
- // Core will be written at exit
+ if (fork() != 0) exit(1); /* Abort main program */
+ /* Core will be written at exit */
}
#else
void write_core(int sig)
diff --git a/sql/structs.h b/sql/structs.h
index c4cb6c82209..c2ad4ef527e 100644
--- a/sql/structs.h
+++ b/sql/structs.h
@@ -50,14 +50,14 @@ typedef struct st_keyfile_info { /* used with ha_info() */
typedef struct st_key_part_info { /* Info about a key part */
Field *field;
uint offset; /* offset in record (from 0) */
- uint null_offset; // Offset to null_bit in record
+ uint null_offset; /* Offset to null_bit in record */
uint16 length; /* Length of key_part */
uint16 store_length;
uint16 key_type;
uint16 fieldnr; /* Fieldnum in UNIREG */
uint8 key_part_flag; /* 0 or HA_REVERSE_SORT */
uint8 type;
- uint8 null_bit; // Position to null_bit
+ uint8 null_bit; /* Position to null_bit */
} KEY_PART_INFO ;
@@ -124,33 +124,37 @@ typedef struct {
} INTERVAL;
-enum SHOW_TYPE { SHOW_LONG,SHOW_CHAR,SHOW_INT,SHOW_CHAR_PTR,SHOW_BOOL,
- SHOW_MY_BOOL,SHOW_OPENTABLES,SHOW_STARTTIME,SHOW_QUESTION,
- SHOW_LONG_CONST, SHOW_INT_CONST, SHOW_HAVE
+enum SHOW_TYPE
+{
+ SHOW_UNDEF,
+ SHOW_LONG, SHOW_LONGLONG, SHOW_INT, SHOW_CHAR, SHOW_CHAR_PTR, SHOW_BOOL,
+ SHOW_MY_BOOL, SHOW_OPENTABLES, SHOW_STARTTIME, SHOW_QUESTION,
+ SHOW_LONG_CONST, SHOW_INT_CONST, SHOW_HAVE, SHOW_SYS,
#ifdef HAVE_OPENSSL
- ,SHOW_SSL_CTX_SESS_ACCEPT, SHOW_SSL_CTX_SESS_ACCEPT_GOOD
- ,SHOW_SSL_GET_VERSION, SHOW_SSL_CTX_GET_SESSION_CACHE_MODE
- ,SHOW_SSL_CTX_SESS_CB_HITS, SHOW_SSL_CTX_SESS_ACCEPT_RENEGOTIATE
- ,SHOW_SSL_CTX_SESS_NUMBER, SHOW_SSL_SESSION_REUSED
- ,SHOW_SSL_CTX_SESS_GET_CACHE_SIZE, SHOW_SSL_GET_CIPHER
- ,SHOW_SSL_GET_DEFAULT_TIMEOUT, SHOW_SSL_GET_VERIFY_MODE
- ,SHOW_SSL_CTX_GET_VERIFY_MODE, SHOW_SSL_GET_VERIFY_DEPTH
- ,SHOW_SSL_CTX_GET_VERIFY_DEPTH, SHOW_SSL_CTX_SESS_CONNECT
- ,SHOW_SSL_CTX_SESS_CONNECT_RENEGOTIATE, SHOW_SSL_CTX_SESS_CONNECT_GOOD
- ,SHOW_SSL_CTX_SESS_HITS, SHOW_SSL_CTX_SESS_MISSES
- ,SHOW_SSL_CTX_SESS_TIMEOUTS, SHOW_SSL_CTX_SESS_CACHE_FULL
- ,SHOW_SSL_GET_CIPHER_LIST
+ SHOW_SSL_CTX_SESS_ACCEPT, SHOW_SSL_CTX_SESS_ACCEPT_GOOD,
+ SHOW_SSL_GET_VERSION, SHOW_SSL_CTX_GET_SESSION_CACHE_MODE,
+ SHOW_SSL_CTX_SESS_CB_HITS, SHOW_SSL_CTX_SESS_ACCEPT_RENEGOTIATE,
+ SHOW_SSL_CTX_SESS_NUMBER, SHOW_SSL_SESSION_REUSED,
+ SHOW_SSL_CTX_SESS_GET_CACHE_SIZE, SHOW_SSL_GET_CIPHER,
+ SHOW_SSL_GET_DEFAULT_TIMEOUT, SHOW_SSL_GET_VERIFY_MODE,
+ SHOW_SSL_CTX_GET_VERIFY_MODE, SHOW_SSL_GET_VERIFY_DEPTH,
+ SHOW_SSL_CTX_GET_VERIFY_DEPTH, SHOW_SSL_CTX_SESS_CONNECT,
+ SHOW_SSL_CTX_SESS_CONNECT_RENEGOTIATE, SHOW_SSL_CTX_SESS_CONNECT_GOOD,
+ SHOW_SSL_CTX_SESS_HITS, SHOW_SSL_CTX_SESS_MISSES,
+ SHOW_SSL_CTX_SESS_TIMEOUTS, SHOW_SSL_CTX_SESS_CACHE_FULL,
+ SHOW_SSL_GET_CIPHER_LIST,
#endif /* HAVE_OPENSSL */
- ,SHOW_RPL_STATUS, SHOW_SLAVE_RUNNING
+ SHOW_RPL_STATUS, SHOW_SLAVE_RUNNING
};
enum SHOW_COMP_OPTION { SHOW_OPTION_YES, SHOW_OPTION_NO, SHOW_OPTION_DISABLED};
+typedef int *(*update_var)(THD *, struct show_var_st *);
-struct show_var_st {
+typedef struct show_var_st {
const char *name;
char *value;
SHOW_TYPE type;
-};
+} SHOW_VAR;
struct show_table_type_st {
const char *type;
@@ -186,7 +190,7 @@ typedef struct st_lex_user {
typedef struct user_resources {
- uint questions, updates, connections;
+ uint questions, updates, connections, bits;
} USER_RESOURCES;
typedef struct user_conn {
diff --git a/sql/table.cc b/sql/table.cc
index 8a7604687e7..3e41da73109 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -136,7 +136,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
if (read_string(file,(gptr*) &disk_buff,key_info_length))
goto err_not_open; /* purecov: inspected */
outparam->keys=keys= disk_buff[0];
- outparam->keys_in_use= set_bits(key_map, keys);
+ outparam->keys_for_keyread= outparam->keys_in_use= set_bits(key_map, keys);
outparam->key_parts=key_parts=disk_buff[1];
n_length=keys*sizeof(KEY)+key_parts*sizeof(KEY_PART_INFO);
@@ -402,17 +402,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
}
}
if (reg_field->unireg_check == Field::NEXT_NUMBER)
- {
- if ((int) (outparam->next_number_index= (uint)
- find_ref_key(outparam,reg_field,
- &outparam->next_number_key_offset)) < 0)
- reg_field->unireg_check=Field::NONE; /* purecov: inspected */
- else
- {
- outparam->found_next_number_field=reg_field;
- reg_field->flags|=AUTO_INCREMENT_FLAG;
- }
- }
+ outparam->found_next_number_field= reg_field;
if (outparam->timestamp_field == reg_field)
outparam->timestamp_field_offset=i;
if (use_hash)
@@ -432,7 +422,17 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
for (uint key=0 ; key < outparam->keys ; key++,keyinfo++)
{
uint usable_parts=0;
+ ulong index_flags;
keyinfo->name=(char*) outparam->keynames.type_names[key];
+ /* Fix fulltext keys for old .frm files */
+ if (outparam->key_info[key].flags & HA_FULLTEXT)
+ outparam->key_info[key].algorithm= HA_KEY_ALG_FULLTEXT;
+
+ /* This has to be done after the above fulltext correction */
+ index_flags=outparam->file->index_flags(key);
+ if (!(index_flags & HA_KEY_READ_ONLY))
+ outparam->keys_for_keyread&= ~((key_map) 1 << key);
+
if (primary_key >= MAX_KEY && (keyinfo->flags & HA_NOSAME))
{
/*
@@ -493,15 +493,14 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
if (field->key_length() == key_part->length &&
field->type() != FIELD_TYPE_BLOB)
{
- if ((ha_option & HA_HAVE_KEY_READ_ONLY) &&
+ if ((index_flags & HA_HAVE_KEY_READ_ONLY) &&
(field->key_type() != HA_KEYTYPE_TEXT ||
(!(ha_option & HA_KEY_READ_WRONG_STR) &&
!(keyinfo->flags & HA_FULLTEXT))))
field->part_of_key|= ((key_map) 1 << key);
if ((field->key_type() != HA_KEYTYPE_TEXT ||
!(keyinfo->flags & HA_FULLTEXT)) &&
- !(outparam->file->index_flags(key) &
- HA_WRONG_ASCII_ORDER))
+ !(index_flags & HA_WRONG_ASCII_ORDER))
field->part_of_sortkey|= ((key_map) 1 << key);
}
if (!(key_part->key_part_flag & HA_REVERSE_SORT) &&
@@ -568,6 +567,20 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
bfill(outparam->null_flags+outparam->rec_buff_length*2,null_length,255);
}
+
+ if ((reg_field=outparam->found_next_number_field))
+ {
+ if ((int) (outparam->next_number_index= (uint)
+ find_ref_key(outparam,reg_field,
+ &outparam->next_number_key_offset)) < 0)
+ {
+ reg_field->unireg_check=Field::NONE; /* purecov: inspected */
+ outparam->found_next_number_field=0;
+ }
+ else
+ reg_field->flags|=AUTO_INCREMENT_FLAG;
+ }
+
if (outparam->blob_fields)
{
Field **ptr;
@@ -808,7 +821,7 @@ ulong make_new_entry(File file, uchar *fileinfo, TYPELIB *formnames,
int2store(fileinfo+8,names+1);
int2store(fileinfo+4,n_length+length);
- VOID(my_chsize(file,newpos,MYF(MY_WME))); /* Append file with '\0' */
+ VOID(my_chsize(file, newpos, 0, MYF(MY_WME)));/* Append file with '\0' */
DBUG_RETURN(newpos);
} /* make_new_entry */
@@ -1123,7 +1136,8 @@ bool check_db_name(const char *name)
}
}
#endif
- if (*name == '/' || *name == FN_LIBCHAR || *name == FN_EXTCHAR)
+ if (*name == '/' || *name == '\\' || *name == FN_LIBCHAR ||
+ *name == FN_EXTCHAR)
return 1;
name++;
}
diff --git a/sql/table.h b/sql/table.h
index b89701bfc8e..02abb090426 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -37,8 +37,8 @@ typedef struct st_grant_info
{
GRANT_TABLE *grant_table;
uint version;
- uint privilege;
- uint want_privilege;
+ ulong privilege;
+ ulong want_privilege;
} GRANT_INFO;
enum tmp_table_type {NO_TMP_TABLE=0, TMP_TABLE=1, TRANSACTIONAL_TMP_TABLE=2};
@@ -61,7 +61,8 @@ struct st_table {
uint uniques;
uint null_fields; /* number of null fields */
uint blob_fields; /* number of blob fields */
- key_map keys_in_use, keys_in_use_for_query;
+ key_map keys_in_use, keys_for_keyread;
+ key_map quick_keys, used_keys, keys_in_use_for_query;
KEY *key_info; /* data of keys in database */
TYPELIB keynames; /* Pointers to keynames */
ha_rows max_rows; /* create information */
@@ -120,7 +121,6 @@ struct st_table {
byte *record_pointers; /* If sorted in memory */
ha_rows found_records; /* How many records in sort */
ORDER *group;
- key_map quick_keys, used_keys;
ha_rows quick_rows[MAX_KEY];
uint quick_key_parts[MAX_KEY];
key_part_map const_key_parts[MAX_KEY];
@@ -136,7 +136,8 @@ struct st_table {
#define JOIN_TYPE_LEFT 1
#define JOIN_TYPE_RIGHT 2
-typedef struct st_table_list {
+typedef struct st_table_list
+{
struct st_table_list *next;
char *db,*name,*real_name;
uint32 db_length, real_name_length;
@@ -155,16 +156,18 @@ typedef struct st_table_list {
};
GRANT_INFO grant;
thr_lock_type lock_type;
- uint outer_join; /* Which join type */
- bool straight; /* optimize with prev table */
- bool updating; /* for replicate-do/ignore table */
- bool shared; /* Used twice in union */
- void *derived; /* SELECT_LEX_UNIT of derived table */
+ uint outer_join; /* Which join type */
+ bool straight; /* optimize with prev table */
+ bool updating; /* for replicate-do/ignore table */
+ bool shared; /* Used twice in union */
+ bool do_redirect; /* If *table has to be fixed in UNION */
+ void *derived; /* SELECT_LEX_UNIT of derived table */
} TABLE_LIST;
-typedef struct st_changed_table_list {
+typedef struct st_changed_table_list
+{
struct st_changed_table_list *next;
- char *key, *table_name;
+ char *key;
uint32 key_length;
} CHANGED_TABLE_LIST;
diff --git a/sql/time.cc b/sql/time.cc
index 2a791ccc30e..aadc32964ff 100644
--- a/sql/time.cc
+++ b/sql/time.cc
@@ -501,7 +501,7 @@ str_to_TIME(const char *str, uint length, TIME *l_time,bool fuzzy_date)
}
if (str != end && current_thd->count_cuted_fields)
{
- for ( ; str != end ; str++)
+ for (; str != end ; str++)
{
if (!my_isspace(system_charset_info,*str))
{
diff --git a/sql/udf_example.cc b/sql/udf_example.cc
index a5ec77f88e4..f5ff9fe67b5 100644
--- a/sql/udf_example.cc
+++ b/sql/udf_example.cc
@@ -271,7 +271,7 @@ char *metaphon(UDF_INIT *initid, UDF_ARGS *args, char *result,
* characters and converting to uppercase.
*-------------------------------------------------------*/
- for ( n = ntrans + 1, n_end = ntrans + sizeof(ntrans)-2;
+ for (n = ntrans + 1, n_end = ntrans + sizeof(ntrans)-2;
word != w_end && n < n_end; word++ )
if ( isalpha ( *word ))
*n++ = toupper ( *word );
@@ -324,7 +324,7 @@ char *metaphon(UDF_INIT *initid, UDF_ARGS *args, char *result,
KSflag = 0; /* state flag for KS translation */
- for ( metaph_end = result + MAXMETAPH, n_start = n;
+ for (metaph_end = result + MAXMETAPH, n_start = n;
n <= n_end && result < metaph_end; n++ )
{
@@ -402,7 +402,7 @@ char *metaphon(UDF_INIT *initid, UDF_ARGS *args, char *result,
n[2] != 'G' ) ?
(char)'J' : (char)'K';
else
- if( n[1] == 'H' &&
+ if ( n[1] == 'H' &&
!NOGHTOF( *( n - 3 )) &&
*( n - 4 ) != 'H')
*result++ = 'F';
@@ -440,7 +440,7 @@ char *metaphon(UDF_INIT *initid, UDF_ARGS *args, char *result,
case 'T': /* TIO, TIA = X ("sh" sound) */
/* TH = 0, ("th" sound ) */
- if( *( n + 1 ) == 'I' && ( n[2] == 'O'
+ if ( *( n + 1 ) == 'I' && ( n[2] == 'O'
|| n[2] == 'A') )
*result++ = 'X';
else
diff --git a/sql/uniques.cc b/sql/uniques.cc
index 3a26f610dc5..60905567ba0 100644
--- a/sql/uniques.cc
+++ b/sql/uniques.cc
@@ -22,7 +22,7 @@
The basic idea is as follows:
Store first all strings in a binary tree, ignoring duplicates.
- When the three uses more memory than 'max_heap_table_size',
+ When the tree uses more memory than 'max_heap_table_size',
write the tree (in sorted order) out to disk and start with a new tree.
When all data has been generated, merge the trees (removing any found
duplicates).
diff --git a/sql/unireg.cc b/sql/unireg.cc
index 57a1407ea06..8db9b871a39 100644
--- a/sql/unireg.cc
+++ b/sql/unireg.cc
@@ -105,7 +105,7 @@ int rea_create_table(my_string file_name,
fileinfo[26]= (uchar) test((create_info->max_rows == 1) &&
(create_info->min_rows == 1) && (keys == 0));
int2store(fileinfo+28,key_info_length);
- strnmov((char*) forminfo+47,create_info->comment ? create_info->comment : "",
+ strmake((char*) forminfo+47,create_info->comment ? create_info->comment : "",
60);
forminfo[46]=(uchar) strlen((char*)forminfo+47); // Length of comment
diff --git a/sql/unireg.h b/sql/unireg.h
index 5a61f4a6c12..2cfa709bbdc 100644
--- a/sql/unireg.h
+++ b/sql/unireg.h
@@ -46,6 +46,7 @@
#define MAX_DBKEY_LENGTH (FN_LEN*2+6) /* extra 4 bytes for slave tmp
* tables */
#define MAX_FIELD_NAME 34 /* Max colum name length +2 */
+#define MAX_SYS_VAR_LENGTH 32
#define MAX_KEY 32 /* Max used keys */
#define MAX_REF_PARTS 16 /* Max parts used as ref */
#define MAX_KEY_LENGTH 500 /* max possible key */
@@ -129,6 +130,10 @@ bfill((A)->null_flags,(A)->null_bytes,255);\
*/
#define MIN_TURBOBM_PATTERN_LEN 3
+/* Defines for binary logging */
+
+#define BIN_LOG_HEADER_SIZE 4
+
/* Include prototypes for unireg */
#include "mysqld_error.h"