summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/field.cc155
-rw-r--r--sql/filesort.cc4
-rw-r--r--sql/gen_lex_hash.cc2
-rw-r--r--sql/gstream.cc2
-rw-r--r--sql/ha_berkeley.cc4
-rw-r--r--sql/ha_berkeley.h3
-rw-r--r--sql/ha_heap.cc12
-rw-r--r--sql/ha_innodb.cc255
-rw-r--r--sql/ha_innodb.h2
-rw-r--r--sql/ha_isam.cc3
-rw-r--r--sql/ha_isammrg.cc12
-rw-r--r--sql/ha_myisam.cc46
-rw-r--r--sql/ha_myisammrg.cc66
-rw-r--r--sql/ha_myisammrg.h5
-rw-r--r--sql/handler.cc3
-rw-r--r--sql/handler.h3
-rw-r--r--sql/hash_filo.h4
-rw-r--r--sql/hostname.cc2
-rw-r--r--sql/item.cc52
-rw-r--r--sql/item.h8
-rw-r--r--sql/item_cmpfunc.cc128
-rw-r--r--sql/item_cmpfunc.h31
-rw-r--r--sql/item_func.cc111
-rw-r--r--sql/item_func.h23
-rw-r--r--sql/item_strfunc.cc28
-rw-r--r--sql/item_strfunc.h36
-rw-r--r--sql/item_subselect.cc27
-rw-r--r--sql/item_subselect.h27
-rw-r--r--sql/item_timefunc.cc113
-rw-r--r--sql/item_timefunc.h161
-rw-r--r--sql/lex.h11
-rw-r--r--sql/lock.cc12
-rw-r--r--sql/log.cc38
-rw-r--r--sql/log_event.cc155
-rw-r--r--sql/log_event.h50
-rw-r--r--sql/mini_client.cc4
-rw-r--r--sql/mysql_priv.h34
-rw-r--r--sql/mysqld.cc418
-rw-r--r--sql/nt_servc.cc28
-rw-r--r--sql/opt_range.cc154
-rw-r--r--sql/opt_sum.cc13
-rw-r--r--sql/procedure.h10
-rw-r--r--sql/repl_failsafe.cc9
-rw-r--r--sql/set_var.cc39
-rw-r--r--sql/set_var.h21
-rw-r--r--sql/share/czech/errmsg.txt6
-rw-r--r--sql/share/danish/errmsg.txt6
-rw-r--r--sql/share/dutch/errmsg.txt6
-rw-r--r--sql/share/english/errmsg.txt6
-rw-r--r--sql/share/estonian/errmsg.txt6
-rw-r--r--sql/share/french/errmsg.txt6
-rw-r--r--sql/share/german/errmsg.txt6
-rw-r--r--sql/share/greek/errmsg.txt6
-rw-r--r--sql/share/hungarian/errmsg.txt6
-rw-r--r--sql/share/italian/errmsg.txt6
-rw-r--r--sql/share/japanese/errmsg.txt6
-rw-r--r--sql/share/korean/errmsg.txt6
-rw-r--r--sql/share/norwegian-ny/errmsg.txt6
-rw-r--r--sql/share/norwegian/errmsg.txt6
-rw-r--r--sql/share/polish/errmsg.txt6
-rw-r--r--sql/share/portuguese/errmsg.txt6
-rw-r--r--sql/share/romanian/errmsg.txt6
-rw-r--r--sql/share/russian/errmsg.txt6
-rw-r--r--sql/share/serbian/errmsg.txt4
-rw-r--r--sql/share/slovak/errmsg.txt6
-rw-r--r--sql/share/spanish/errmsg.txt6
-rw-r--r--sql/share/swedish/errmsg.txt34
-rw-r--r--sql/share/ukrainian/errmsg.txt6
-rw-r--r--sql/slave.cc25
-rw-r--r--sql/slave.h4
-rw-r--r--sql/sql_acl.cc40
-rw-r--r--sql/sql_acl.h6
-rw-r--r--sql/sql_analyse.cc2
-rw-r--r--sql/sql_base.cc184
-rw-r--r--sql/sql_cache.cc129
-rw-r--r--sql/sql_cache.h4
-rw-r--r--sql/sql_class.cc123
-rw-r--r--sql/sql_class.h22
-rw-r--r--sql/sql_db.cc29
-rw-r--r--sql/sql_delete.cc130
-rw-r--r--sql/sql_derived.cc22
-rw-r--r--sql/sql_error.cc18
-rw-r--r--sql/sql_insert.cc54
-rw-r--r--sql/sql_lex.cc7
-rw-r--r--sql/sql_lex.h9
-rw-r--r--sql/sql_load.cc31
-rw-r--r--sql/sql_manager.cc2
-rw-r--r--sql/sql_parse.cc358
-rw-r--r--sql/sql_rename.cc2
-rw-r--r--sql/sql_repl.cc7
-rw-r--r--sql/sql_repl.h4
-rw-r--r--sql/sql_select.cc196
-rw-r--r--sql/sql_select.h3
-rw-r--r--sql/sql_show.cc12
-rw-r--r--sql/sql_string.cc339
-rw-r--r--sql/sql_string.h5
-rw-r--r--sql/sql_table.cc74
-rw-r--r--sql/sql_udf.cc4
-rw-r--r--sql/sql_union.cc8
-rw-r--r--sql/sql_update.cc116
-rw-r--r--sql/sql_yacc.yy312
-rw-r--r--sql/stacktrace.c2
-rw-r--r--sql/table.cc15
-rw-r--r--sql/table.h1
104 files changed, 2974 insertions, 1813 deletions
diff --git a/sql/field.cc b/sql/field.cc
index 73ef4439bc9..f2324a0a331 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -41,6 +41,11 @@
#include <floatingpoint.h>
#endif
+// Maximum allowed exponent value for converting string to decimal
+#define MAX_EXPONENT 1024
+
+
+
/*****************************************************************************
Instansiate templates and static variables
*****************************************************************************/
@@ -392,7 +397,7 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs)
const char *frac_digits_from, *frac_digits_end;
/* The sign of the exponent : will be 0 (means no exponent), '+' or '-' */
char expo_sign_char=0;
- uint exponent=0; // value of the exponent
+ uint exponent=0; // value of the exponent
/*
Pointers used when digits move from the left of the '.' to the
right of the '.' (explained below)
@@ -488,13 +493,17 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs)
else
expo_sign_char= '+';
/*
- Read digits of the exponent and compute its value
- 'exponent' overflow (e.g. if 1E10000000000000000) is not a problem
- (the value of the field will be overflow anyway, or 0 anyway,
- it does not change anything if the exponent is 2^32 or more
+ Read digits of the exponent and compute its value. We must care about
+ 'exponent' overflow, because as unsigned arithmetic is "modulo", big
+ exponents will become small (e.g. 1e4294967296 will become 1e0, and the
+ field will finally contain 1 instead of its max possible value).
*/
- for (;from!=end && my_isdigit(system_charset_info, (*from)); from++)
+ for (;from!=end && my_isdigit(system_charset_info, *from); from++)
+ {
exponent=10*exponent+(*from-'0');
+ if (exponent>MAX_EXPONENT)
+ break;
+ }
}
/*
@@ -536,6 +545,13 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs)
int_digits_added_zeros=2 (to make 1234500).
*/
+ /*
+ Below tmp_uint cannot overflow with small enough MAX_EXPONENT setting,
+ as int_digits_added_zeros<=exponent<4G and
+ (int_digits_end-int_digits_from)<=max_allowed_packet<=2G and
+ (frac_digits_from-int_digits_tail_from)<=max_allowed_packet<=2G
+ */
+
if (!expo_sign_char)
tmp_uint=tmp_dec+(uint)(int_digits_end-int_digits_from);
else if (expo_sign_char == '-')
@@ -544,7 +560,7 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs)
frac_digits_added_zeros=exponent-tmp_uint;
int_digits_end -= tmp_uint;
frac_digits_head_end=int_digits_end+tmp_uint;
- tmp_uint=tmp_dec+(uint)(int_digits_end-int_digits_from);
+ tmp_uint=tmp_dec+(uint)(int_digits_end-int_digits_from);
}
else // (expo_sign_char=='+')
{
@@ -571,9 +587,9 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs)
int_digits_added_zeros=0;
}
}
- tmp_uint=(tmp_dec+(uint)(int_digits_end-int_digits_from)
- +(uint)(frac_digits_from-int_digits_tail_from)+
- int_digits_added_zeros);
+ tmp_uint= (tmp_dec+(int_digits_end-int_digits_from)+
+ (uint)(frac_digits_from-int_digits_tail_from)+
+ int_digits_added_zeros);
}
/*
@@ -584,7 +600,7 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs)
If the sign is defined and '-', we need one position for it
*/
- if (field_length < tmp_uint + (int) (sign_char == '-'))
+ if (field_length < tmp_uint + (int) (sign_char == '-'))
{
// too big number, change to max or min number
Field_decimal::overflow(sign_char == '-');
@@ -647,69 +663,67 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs)
*pos--=' '; //fill with blanks
}
- if (tmp_dec) // This field has decimals
- {
- /*
- Write digits of the frac_% parts ;
- Depending on current_thd->count_cutted_fields, we may also want
- to know if some non-zero tail of these parts will
- be truncated (for example, 0.002->0.00 will generate a warning,
- while 0.000->0.00 will not)
- (and 0E1000000000 will not, while 1E-1000000000 will)
- */
+ /*
+ Write digits of the frac_% parts ;
+ Depending on current_thd->count_cutted_fields, we may also want
+ to know if some non-zero tail of these parts will
+ be truncated (for example, 0.002->0.00 will generate a warning,
+ while 0.000->0.00 will not)
+ (and 0E1000000000 will not, while 1E-1000000000 will)
+ */
- pos=to+(uint)(field_length-tmp_dec); // Calculate post to '.'
+ pos=to+(uint)(field_length-tmp_dec); // Calculate post to '.'
+ right_wall=to+field_length;
+ if (pos != right_wall)
*pos++='.';
- right_wall=to+field_length;
- if (expo_sign_char == '-')
+ if (expo_sign_char == '-')
+ {
+ while (frac_digits_added_zeros-- > 0)
{
- while (frac_digits_added_zeros-- > 0)
+ if (pos == right_wall)
{
- if (pos == right_wall)
- {
- if (current_thd->count_cuted_fields && !is_cuted_fields_incr)
- break; // Go on below to see if we lose non zero digits
- return 0;
- }
- *pos++='0';
+ if (current_thd->count_cuted_fields && !is_cuted_fields_incr)
+ break; // Go on below to see if we lose non zero digits
+ return 0;
}
- while (int_digits_end != frac_digits_head_end)
+ *pos++='0';
+ }
+ while (int_digits_end != frac_digits_head_end)
+ {
+ tmp_char= *int_digits_end++;
+ if (pos == right_wall)
{
- tmp_char= *int_digits_end++;
- if (pos == right_wall)
- {
- if (tmp_char != '0') // Losing a non zero digit ?
- {
- if (!is_cuted_fields_incr)
- current_thd->cuted_fields++;
- return 0;
- }
- continue;
- }
- *pos++= tmp_char;
+ if (tmp_char != '0') // Losing a non zero digit ?
+ {
+ if (!is_cuted_fields_incr)
+ current_thd->cuted_fields++;
+ return 0;
+ }
+ continue;
}
+ *pos++= tmp_char;
}
+ }
- for (;frac_digits_from!=frac_digits_end;)
+ for (;frac_digits_from!=frac_digits_end;)
+ {
+ tmp_char= *frac_digits_from++;
+ if (pos == right_wall)
{
- tmp_char= *frac_digits_from++;
- if (pos == right_wall)
+ if (tmp_char != '0') // Losing a non zero digit ?
{
- if (tmp_char != '0') // Losing a non zero digit ?
- {
- if (!is_cuted_fields_incr)
- current_thd->cuted_fields++;
- return 0;
- }
- continue;
+ if (!is_cuted_fields_incr)
+ current_thd->cuted_fields++;
+ return 0;
}
- *pos++= tmp_char;
+ continue;
}
-
- while (pos != right_wall)
- *pos++='0'; // Fill with zeros at right of '.'
+ *pos++= tmp_char;
}
+
+ while (pos != right_wall)
+ *pos++='0'; // Fill with zeros at right of '.'
return 0;
}
@@ -3930,12 +3944,12 @@ int Field_string::pack_cmp(const char *b, uint length)
}
-uint Field_string::packed_col_length(const char *ptr, uint length)
+uint Field_string::packed_col_length(const char *data_ptr, uint length)
{
if (length > 255)
- return uint2korr(ptr)+2;
+ return uint2korr(data_ptr)+2;
else
- return (uint) ((uchar) *ptr)+1;
+ return (uint) ((uchar) *data_ptr)+1;
}
uint Field_string::max_packed_col_length(uint max_length)
@@ -4162,12 +4176,12 @@ int Field_varstring::pack_cmp(const char *b, uint key_length)
(const uchar *)b,b_length);
}
-uint Field_varstring::packed_col_length(const char *ptr, uint length)
+uint Field_varstring::packed_col_length(const char *data_ptr, uint length)
{
if (length > 255)
- return uint2korr(ptr)+2;
+ return uint2korr(data_ptr)+2;
else
- return (uint) ((uchar) *ptr)+1;
+ return (uint) ((uchar) *data_ptr)+1;
}
uint Field_varstring::max_packed_col_length(uint max_length)
@@ -4698,12 +4712,12 @@ char *Field_blob::pack_key_from_key_image(char *to, const char *from,
return to+length;
}
-uint Field_blob::packed_col_length(const char *ptr, uint length)
+uint Field_blob::packed_col_length(const char *data_ptr, uint length)
{
if (length > 255)
- return uint2korr(ptr)+2;
+ return uint2korr(data_ptr)+2;
else
- return (uint) ((uchar) *ptr)+1;
+ return (uint) ((uchar) *data_ptr)+1;
}
uint Field_blob::max_packed_col_length(uint max_length)
@@ -5294,10 +5308,11 @@ Field *make_field(char *ptr, uint32 field_length,
return new Field_datetime(ptr,null_pos,null_bit,
unireg_check, field_name, table, field_charset);
case FIELD_TYPE_NULL:
- default: // Impossible (Wrong version)
return new Field_null(ptr,field_length,unireg_check,field_name,table, field_charset);
+ default: // Impossible (Wrong version)
+ break;
}
- return 0; // Impossible (Wrong version)
+ return 0;
}
diff --git a/sql/filesort.cc b/sql/filesort.cc
index 53af60b0370..fab666a1203 100644
--- a/sql/filesort.cc
+++ b/sql/filesort.cc
@@ -223,7 +223,7 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length,
if (error)
my_error(ER_FILSORT_ABORT,MYF(ME_ERROR+ME_WAITTANG));
else
- statistic_add(filesort_rows, records, &LOCK_status);
+ statistic_add(filesort_rows, (ulong) records, &LOCK_status);
*examined_rows= param.examined_rows;
#ifdef SKIP_DBUG_IN_FILESORT
DBUG_POP(); /* Ok to DBUG */
@@ -724,7 +724,7 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
org_max_rows=max_rows=param->max_rows;
if (init_queue(&queue,(uint) (Tb-Fb)+1,offsetof(BUFFPEK,key),0,
- (int (*) (void *, byte *,byte*))
+ (queue_compare)
(cmp=get_ptr_compare(sort_length)),(void*) &sort_length))
DBUG_RETURN(1); /* purecov: inspected */
for (buffpek= Fb ; buffpek <= Tb ; buffpek++)
diff --git a/sql/gen_lex_hash.cc b/sql/gen_lex_hash.cc
index 0d92397b616..7daab228093 100644
--- a/sql/gen_lex_hash.cc
+++ b/sql/gen_lex_hash.cc
@@ -320,7 +320,7 @@ and you are welcome to modify and redistribute it under the GPL license\n");
my_print_help(my_long_options);
}
-static my_bool
+extern "C" my_bool
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
char *argument __attribute__((unused)))
{
diff --git a/sql/gstream.cc b/sql/gstream.cc
index 5a58fef6744..bd2345212c3 100644
--- a/sql/gstream.cc
+++ b/sql/gstream.cc
@@ -99,7 +99,7 @@ int GTextReadStream::get_next_number(double *d)
char *endptr;
- *d = strtod(cur, &endptr);
+ *d = my_strtod(my_charset_latin1, cur, &endptr);
if(endptr)
{
diff --git a/sql/ha_berkeley.cc b/sql/ha_berkeley.cc
index 6d5b469a913..679642ca949 100644
--- a/sql/ha_berkeley.cc
+++ b/sql/ha_berkeley.cc
@@ -1931,7 +1931,7 @@ int ha_berkeley::delete_table(const char *name)
double ha_berkeley::scan_time()
{
- return records/3;
+ return rows2double(records/3);
}
ha_rows ha_berkeley::records_in_range(int keynr,
@@ -2206,7 +2206,7 @@ static BDB_SHARE *get_share(const char *table_name, TABLE *table)
if (!(share=(BDB_SHARE*) hash_search(&bdb_open_tables, (byte*) table_name,
length)))
{
- ha_rows *rec_per_key;
+ ulong *rec_per_key;
char *tmp_name;
DB **key_file;
u_int32_t *key_type;
diff --git a/sql/ha_berkeley.h b/sql/ha_berkeley.h
index 198664d0c06..f2a81d123f1 100644
--- a/sql/ha_berkeley.h
+++ b/sql/ha_berkeley.h
@@ -27,7 +27,8 @@
typedef struct st_berkeley_share {
ulonglong auto_ident;
- ha_rows rows, org_rows, *rec_per_key;
+ ha_rows rows, org_rows;
+ ulong *rec_per_key;
THR_LOCK lock;
pthread_mutex_t mutex;
char *table_name;
diff --git a/sql/ha_heap.cc b/sql/ha_heap.cc
index c06421617dd..4a3b9495f6f 100644
--- a/sql/ha_heap.cc
+++ b/sql/ha_heap.cc
@@ -245,7 +245,7 @@ int ha_heap::create(const char *name, TABLE *table,
{
uint key, parts, mem_per_row= 0;
uint auto_key= 0, auto_key_type= 0;
- ulong max_rows;
+ ha_rows max_rows;
HP_KEYDEF *keydef;
HA_KEYSEG *seg;
char buff[FN_REFLEN];
@@ -310,8 +310,8 @@ int ha_heap::create(const char *name, TABLE *table,
}
}
mem_per_row+= MY_ALIGN(table->reclength + 1, sizeof(char*));
- max_rows = (ulong) (current_thd->variables.max_heap_table_size /
- mem_per_row);
+ max_rows = (ha_rows) (current_thd->variables.max_heap_table_size /
+ mem_per_row);
HP_CREATE_INFO hp_create_info;
hp_create_info.auto_key= auto_key;
hp_create_info.auto_key_type= auto_key_type;
@@ -319,9 +319,9 @@ int ha_heap::create(const char *name, TABLE *table,
create_info->auto_increment_value - 1 : 0);
error= heap_create(fn_format(buff,name,"","",4+2),
table->keys,keydef, table->reclength,
- ((table->max_rows < max_rows && table->max_rows) ?
- table->max_rows : max_rows),
- table->min_rows, &hp_create_info);
+ (ulong) ((table->max_rows < max_rows && table->max_rows) ?
+ table->max_rows : max_rows),
+ (ulong) table->min_rows, &hp_create_info);
my_free((gptr) keydef, MYF(0));
if (file)
info(HA_STATUS_NO_LOCK | HA_STATUS_CONST | HA_STATUS_VARIABLE);
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index 9aa63cc1435..7787b543f34 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -40,17 +40,12 @@ InnoDB */
#include "ha_innodb.h"
-/* We must declare this here because we undef SAFE_MUTEX below */
pthread_mutex_t innobase_mutex;
/* Store MySQL definition of 'byte': in Linux it is char while InnoDB
uses unsigned char */
typedef byte mysql_byte;
-#ifdef SAFE_MUTEX
-#undef pthread_mutex_t
-#endif
-
#define INSIDE_HA_INNOBASE_CC
/* Include necessary InnoDB headers */
@@ -97,6 +92,8 @@ are determined in innobase_init below: */
char* innobase_data_home_dir = NULL;
char* innobase_log_group_home_dir = NULL;
char* innobase_log_arch_dir = NULL;
+/* The following has a midleading name: starting from 4.0.5 this also
+affects Windows */
char* innobase_unix_file_flush_method = NULL;
/* Below we have boolean-valued start-up parameters, and their default
@@ -253,6 +250,10 @@ convert_error_code_to_mysql(
} else if (error == (int) DB_TOO_BIG_RECORD) {
return(HA_ERR_TO_BIG_ROW);
+
+ } else if (error == (int) DB_CORRUPTION) {
+
+ return(HA_ERR_CRASHED);
} else {
return(-1); // Unknown error
}
@@ -346,7 +347,8 @@ check_trx_exists(
trx = trx_allocate_for_mysql();
trx->mysql_thd = thd;
-
+ trx->mysql_query_str = &((*thd).query);
+
thd->transaction.all.innobase_tid = trx;
/* The execution of a single SQL statement is denoted by
@@ -713,9 +715,10 @@ innobase_init(void)
DBUG_RETURN(TRUE);
}
- srv_unix_file_flush_method_str = (innobase_unix_file_flush_method ?
+
+ srv_file_flush_method_str = (innobase_unix_file_flush_method ?
innobase_unix_file_flush_method :
- (char*)"fdatasync");
+ NULL);
srv_n_log_groups = (ulint) innobase_mirrored_log_groups;
srv_n_log_files = (ulint) innobase_log_files_in_group;
@@ -725,8 +728,6 @@ innobase_init(void)
srv_log_buffer_size = (ulint) innobase_log_buffer_size;
srv_flush_log_at_trx_commit = (ulint) innobase_flush_log_at_trx_commit;
- srv_use_native_aio = 0;
-
srv_pool_size = (ulint) innobase_buffer_pool_size;
srv_mem_pool_size = (ulint) innobase_additional_mem_pool_size;
@@ -750,6 +751,14 @@ innobase_init(void)
default_charset_info->sort_order, 256);
}
+ /* Since we in this module access directly the fields of a trx
+ struct, and due to different headers and flags it might happen that
+ mutex_t has a different size in this module and in InnoDB
+ modules, we check at run time that the size is the same in
+ these compilation modules. */
+
+ srv_sizeof_trx_t_in_ha_innodb_cc = sizeof(trx_t);
+
err = innobase_start_or_create_for_mysql();
if (err != DB_SUCCESS) {
@@ -1147,15 +1156,15 @@ ha_innobase::open(
ib_table = dict_table_get_and_increment_handle_count(
norm_name, NULL);
if (NULL == ib_table) {
-
- sql_print_error("InnoDB error:\n\
-Cannot find table %s from the internal data dictionary\n\
-of InnoDB though the .frm file for the table exists. Maybe you\n\
-have deleted and recreated InnoDB data files but have forgotten\n\
-to delete the corresponding .frm files of InnoDB tables, or you\n\
-have moved .frm files to another database?\n\
-Look from section 15.1 of http://www.innodb.com/ibman.html\n\
-how you can resolve the problem.\n",
+ ut_print_timestamp(stderr);
+ fprintf(stderr, " InnoDB error:\n"
+"Cannot find table %s from the internal data dictionary\n"
+"of InnoDB though the .frm file for the table exists. Maybe you\n"
+"have deleted and recreated InnoDB data files but have forgotten\n"
+"to delete the corresponding .frm files of InnoDB tables, or you\n"
+"have moved .frm files to another database?\n"
+"Look from section 15.1 of http://www.innodb.com/ibman.html\n"
+"how you can resolve the problem.\n",
norm_name);
free_share(share);
@@ -1168,7 +1177,10 @@ how you can resolve the problem.\n",
((row_prebuilt_t*)innobase_prebuilt)->mysql_row_len = table->reclength;
- primary_key = MAX_KEY;
+ /* Looks like MySQL-3.23 sometimes has primary key number != 0 */
+
+ primary_key = table->primary_key;
+ key_used_on_scan = primary_key;
/* Allocate a buffer for a 'row reference'. A row reference is
a string of bytes of length ref_length which uniquely specifies
@@ -1177,13 +1189,14 @@ how you can resolve the problem.\n",
of length ref_length! */
if (!row_table_got_default_clust_index(ib_table)) {
+ if (primary_key >= MAX_KEY) {
+ fprintf(stderr,
+ "InnoDB: Error: table %s has a primary key in InnoDB\n"
+ "InnoDB: data dictionary, but not in MySQL!\n", name);
+ }
((row_prebuilt_t*)innobase_prebuilt)
->clust_index_was_generated = FALSE;
-
- primary_key = 0;
- key_used_on_scan = 0;
-
/*
MySQL allocates the buffer for ref. key_info->key_length
includes space for all key columns + one byte for each column
@@ -1192,8 +1205,14 @@ how you can resolve the problem.\n",
based on ref_length.
*/
- ref_length = table->key_info->key_length;
+ ref_length = table->key_info[primary_key].key_length;
} else {
+ if (primary_key != MAX_KEY) {
+ fprintf(stderr,
+ "InnoDB: Error: table %s has no primary key in InnoDB\n"
+ "InnoDB: data dictionary, but has one in MySQL!\n", name);
+ }
+
((row_prebuilt_t*)innobase_prebuilt)
->clust_index_was_generated = TRUE;
@@ -1501,7 +1520,8 @@ ha_innobase::store_key_val_for_row(
are equal
*/
bzero(buff, (ref_length- (uint) (buff - buff_start)));
- DBUG_RETURN(ref_length);
+
+ DBUG_RETURN((uint)(buff - buff_start));
}
/******************************************************************
@@ -1679,6 +1699,7 @@ ha_innobase::write_row(
longlong dummy;
ibool incremented_auto_inc_for_stat = FALSE;
ibool incremented_auto_inc_counter = FALSE;
+ ibool skip_auto_inc_decr;
DBUG_ENTER("ha_innobase::write_row");
@@ -1843,13 +1864,31 @@ ha_innobase::write_row(
if (error != DB_SUCCESS) {
/* If the insert did not succeed we restore the value of
the auto-inc counter we used; note that this behavior was
- introduced only in version 4.0.4 */
+ introduced only in version 4.0.4.
+ NOTE that a REPLACE command handles a duplicate key error
+ itself, and we must not decrement the autoinc counter
+ if we are performing a REPLACE statement.
+ NOTE 2: if there was an error, for example a deadlock,
+ which caused InnoDB to roll back the whole transaction
+ already in the call of row_insert_for_mysql(), we may no
+ longer have the AUTO-INC lock, and cannot decrement
+ the counter here. */
+
+ skip_auto_inc_decr = FALSE;
+
+ if (error == DB_DUPLICATE_KEY) {
+ ut_a(user_thd->query);
+ dict_accept(user_thd->query, "REPLACE",
+ &skip_auto_inc_decr);
+ }
- if (incremented_auto_inc_counter) {
+ if (!skip_auto_inc_decr && incremented_auto_inc_counter
+ && prebuilt->trx->auto_inc_lock) {
dict_table_autoinc_decrement(prebuilt->table);
}
- if (incremented_auto_inc_for_stat) {
+ if (!skip_auto_inc_decr && incremented_auto_inc_for_stat
+ && prebuilt->trx->auto_inc_lock) {
auto_inc_counter_for_this_stat--;
}
}
@@ -2181,8 +2220,16 @@ convert_search_mode_to_innobase(
case HA_READ_AFTER_KEY: return(PAGE_CUR_G);
case HA_READ_BEFORE_KEY: return(PAGE_CUR_L);
case HA_READ_PREFIX: return(PAGE_CUR_GE);
- case HA_READ_PREFIX_LAST: return(PAGE_CUR_LE);
- /* HA_READ_PREFIX_LAST does not yet work in InnoDB! */
+ case HA_READ_PREFIX_LAST:
+ /* ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: Warning: Using HA_READ_PREFIX_LAST\n"); */
+ return(PAGE_CUR_LE);
+
+ /* InnoDB does not yet support ..PREFIX_LAST!
+ We have to add a new search flag
+ PAGE_CUR_LE_OR_PREFIX to InnoDB. */
+
/* the above PREFIX flags mean that the last
field in the key value may just be a prefix
of the complete fixed length field */
@@ -2751,7 +2798,11 @@ ha_innobase::position(
that len is always fixed for this table. The following assertion
checks this. */
- ut_a(len == ref_length);
+ if (len != ref_length) {
+ fprintf(stderr,
+ "InnoDB: Error: stored ref len is %lu, but table ref len is %lu\n",
+ (ulint)len, (ulint)ref_length);
+ }
}
@@ -2935,16 +2986,21 @@ ha_innobase::create(
trx->check_unique_secondary = FALSE;
}
+ if (lower_case_table_names) {
+ srv_lower_case_table_names = TRUE;
+ } else {
+ srv_lower_case_table_names = FALSE;
+ }
fn_format(name2, name, "", "",2); // Remove the .frm extension
normalize_table_name(norm_name, name2);
- /* Latch the InnoDB data dictionary exclusive so that no deadlocks
+ /* Latch the InnoDB data dictionary exclusively so that no deadlocks
or lock waits can happen in it during a table create operation.
- (Drop table etc. do this latching in row0mysql.c.) */
+ Drop table etc. do this latching in row0mysql.c. */
- row_mysql_lock_data_dictionary();
+ row_mysql_lock_data_dictionary(trx);
/* Create the table definition in InnoDB */
@@ -2953,7 +3009,7 @@ ha_innobase::create(
if (error) {
innobase_commit_low(trx);
- row_mysql_unlock_data_dictionary();
+ row_mysql_unlock_data_dictionary(trx);
trx_free_for_mysql(trx);
@@ -2983,7 +3039,7 @@ ha_innobase::create(
if (error) {
innobase_commit_low(trx);
- row_mysql_unlock_data_dictionary();
+ row_mysql_unlock_data_dictionary(trx);
trx_free_for_mysql(trx);
@@ -2998,7 +3054,7 @@ ha_innobase::create(
(uint) primary_key_no))) {
innobase_commit_low(trx);
- row_mysql_unlock_data_dictionary();
+ row_mysql_unlock_data_dictionary(trx);
trx_free_for_mysql(trx);
@@ -3014,7 +3070,7 @@ ha_innobase::create(
innobase_commit_low(trx);
- row_mysql_unlock_data_dictionary();
+ row_mysql_unlock_data_dictionary(trx);
trx_free_for_mysql(trx);
@@ -3023,24 +3079,27 @@ ha_innobase::create(
}
}
- error = row_table_add_foreign_constraints(trx,
- create_info->create_statement, norm_name);
+ if (current_thd->query != NULL) {
+
+ error = row_table_add_foreign_constraints(trx,
+ current_thd->query, norm_name);
- error = convert_error_code_to_mysql(error, NULL);
+ error = convert_error_code_to_mysql(error, NULL);
- if (error) {
- innobase_commit_low(trx);
+ if (error) {
+ innobase_commit_low(trx);
- row_mysql_unlock_data_dictionary();
+ row_mysql_unlock_data_dictionary(trx);
- trx_free_for_mysql(trx);
+ trx_free_for_mysql(trx);
- DBUG_RETURN(error);
+ DBUG_RETURN(error);
+ }
}
innobase_commit_low(trx);
- row_mysql_unlock_data_dictionary();
+ row_mysql_unlock_data_dictionary(trx);
/* Flush the log to reduce probability that the .frm files and
the InnoDB data dictionary get out-of-sync if the user runs
@@ -3082,6 +3141,12 @@ ha_innobase::delete_table(
DBUG_ENTER("ha_innobase::delete_table");
+ if (lower_case_table_names) {
+ srv_lower_case_table_names = TRUE;
+ } else {
+ srv_lower_case_table_names = FALSE;
+ }
+
trx = trx_allocate_for_mysql();
name_len = strlen(name);
@@ -3095,7 +3160,7 @@ ha_innobase::delete_table(
/* Drop the table in InnoDB */
- error = row_drop_table_for_mysql(norm_name, trx, FALSE);
+ error = row_drop_table_for_mysql(norm_name, trx);
/* Flush the log to reduce probability that the .frm files and
the InnoDB data dictionary get out-of-sync if the user runs
@@ -3192,6 +3257,12 @@ ha_innobase::rename_table(
DBUG_ENTER("ha_innobase::rename_table");
+ if (lower_case_table_names) {
+ srv_lower_case_table_names = TRUE;
+ } else {
+ srv_lower_case_table_names = FALSE;
+ }
+
trx = trx_allocate_for_mysql();
name_len1 = strlen(from);
@@ -3318,7 +3389,7 @@ ha_innobase::estimate_number_of_rows(void)
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
dict_index_t* index;
ulonglong estimate;
- ulonglong data_file_length;
+ ulonglong local_data_file_length;
/* Warning: since it is not sure that MySQL calls external_lock
before calling this function, the trx field in prebuilt can be
@@ -3328,7 +3399,7 @@ ha_innobase::estimate_number_of_rows(void)
index = dict_table_get_first_index_noninline(prebuilt->table);
- data_file_length = ((ulonglong) index->stat_n_leaf_pages)
+ local_data_file_length = ((ulonglong) index->stat_n_leaf_pages)
* UNIV_PAGE_SIZE;
/* Calculate a minimum length for a clustered index record and from
@@ -3337,7 +3408,7 @@ ha_innobase::estimate_number_of_rows(void)
by a threshold factor, we must add a safety factor 2 in front
of the formula below. */
- estimate = 2 * data_file_length / dict_index_calc_min_rec_len(index);
+ estimate = 2 * local_data_file_length / dict_index_calc_min_rec_len(index);
DBUG_RETURN((ha_rows) estimate);
}
@@ -3374,12 +3445,21 @@ ha_innobase::info(
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
dict_table_t* ib_table;
dict_index_t* index;
- ulong rec_per_key;
+ ha_rows rec_per_key;
ulong j;
ulong i;
DBUG_ENTER("info");
+ /* If we are forcing recovery at a high level, we will suppress
+ statistics calculation on tables, because that may crash the
+ server if an index is badly corrupted. */
+
+ if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
+
+ return;
+ }
+
/* Warning: since it is not sure that MySQL calls external_lock
before calling this function, the trx field in prebuilt can be
obsolete! */
@@ -3426,7 +3506,7 @@ ha_innobase::info(
rec_per_key = records;
} else {
- rec_per_key = (ulong)(records /
+ rec_per_key = (ha_rows)(records /
index->stat_n_diff_key_vals[j + 1]);
}
@@ -3441,8 +3521,9 @@ ha_innobase::info(
rec_per_key = 1;
}
- table->key_info[i].rec_per_key[j]
- = rec_per_key;
+ table->key_info[i].rec_per_key[j]=
+ rec_per_key >= ~(ulong) 0 ? ~(ulong) 0 :
+ rec_per_key;
}
index = dict_table_get_next_index_noninline(index);
@@ -3641,7 +3722,6 @@ ha_innobase::reset(void)
return(0);
}
-
/**********************************************************************
When we create a temporary table inside MySQL LOCK TABLES, MySQL will
not call external_lock for the temporary table when it uses it. Instead,
@@ -3663,12 +3743,20 @@ ha_innobase::start_stmt(
innobase_release_stat_resources(trx);
trx_mark_sql_stat_end(trx);
+ if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
+ && trx->read_view) {
+ /* At low transaction isolation levels we let
+ each consistent read set its own snapshot */
+
+ read_view_close_for_mysql(trx);
+ }
+
auto_inc_counter_for_this_stat = 0;
prebuilt->sql_stat_start = TRUE;
prebuilt->hint_no_need_to_fetch_extra_cols = TRUE;
prebuilt->read_just_key = 0;
- if (prebuilt->select_lock_type == LOCK_NONE) {
+ if (!prebuilt->mysql_has_locked) {
/* This handle is for a temporary table created inside
this same LOCK TABLES; since MySQL does NOT call external_lock
in this case, we must use x-row locks inside InnoDB to be
@@ -3683,6 +3771,24 @@ ha_innobase::start_stmt(
}
/**********************************************************************
+Maps a MySQL trx isolation level code to the InnoDB isolation level code */
+inline
+ulint
+innobase_map_isolation_level(
+/*=========================*/
+ /* out: InnoDB isolation level */
+ enum_tx_isolation iso) /* in: MySQL isolation level code */
+{
+ switch(iso) {
+ case ISO_READ_COMMITTED: return(TRX_ISO_READ_COMMITTED);
+ case ISO_REPEATABLE_READ: return(TRX_ISO_REPEATABLE_READ);
+ case ISO_SERIALIZABLE: return(TRX_ISO_SERIALIZABLE);
+ case ISO_READ_UNCOMMITTED: return(TRX_ISO_READ_UNCOMMITTED);
+ default: ut_a(0); return(0);
+ }
+}
+
+/**********************************************************************
As MySQL will execute an external lock for every new table it uses when it
starts to process an SQL statement (an exception is when MySQL calls
start_stmt for the handle) we can use this function to store the pointer to
@@ -3703,6 +3809,7 @@ ha_innobase::external_lock(
trx_t* trx;
DBUG_ENTER("ha_innobase::external_lock");
+ DBUG_PRINT("enter",("lock_type: %d", lock_type));
update_thd(thd);
@@ -3727,8 +3834,15 @@ ha_innobase::external_lock(
thd->transaction.all.innodb_active_trans = 1;
trx->n_mysql_tables_in_use++;
+ prebuilt->mysql_has_locked = TRUE;
- if (thd->variables.tx_isolation == ISO_SERIALIZABLE
+ if (thd->variables.tx_isolation != ISO_REPEATABLE_READ) {
+ trx->isolation_level = innobase_map_isolation_level(
+ (enum_tx_isolation)
+ thd->variables.tx_isolation);
+ }
+
+ if (trx->isolation_level == TRX_ISO_SERIALIZABLE
&& prebuilt->select_lock_type == LOCK_NONE) {
/* To get serializable execution we let InnoDB
@@ -3744,6 +3858,7 @@ ha_innobase::external_lock(
}
} else {
trx->n_mysql_tables_in_use--;
+ prebuilt->mysql_has_locked = FALSE;
auto_inc_counter_for_this_stat = 0;
if (trx->n_mysql_tables_in_use == 0) {
@@ -3755,6 +3870,15 @@ ha_innobase::external_lock(
innobase_release_stat_resources(trx);
+ if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
+ && trx->read_view) {
+
+ /* At low transaction isolation levels we let
+ each consistent read set its own snapshot */
+
+ read_view_close_for_mysql(trx);
+ }
+
if (!(thd->options
& (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
@@ -3779,14 +3903,13 @@ innodb_show_status(
char* buf;
DBUG_ENTER("innodb_show_status");
-
+
if (innodb_skip) {
-
- fprintf(stderr,
- "Cannot call SHOW INNODB STATUS because skip-innodb is defined\n");
-
- DBUG_RETURN(-1);
- }
+ my_message(ER_NOT_SUPPORTED_YET,
+ "Cannot call SHOW INNODB STATUS because skip-innodb is defined",
+ MYF(0));
+ DBUG_RETURN(-1);
+ }
/* We let the InnoDB Monitor to output at most 100 kB of text, add
a safety margin of 10 kB for buffer overruns */
diff --git a/sql/ha_innodb.h b/sql/ha_innodb.h
index 357fb31b5e3..d2639f39c5b 100644
--- a/sql/ha_innodb.h
+++ b/sql/ha_innodb.h
@@ -96,7 +96,7 @@ class ha_innobase: public handler
ulong index_flags(uint idx) const
{
return (HA_READ_NEXT | HA_READ_PREV | HA_READ_ORDER |
- HA_KEY_READ_ONLY | HA_NOT_READ_PREFIX_LAST);
+ HA_KEY_READ_ONLY);
}
uint max_record_length() const { return HA_MAX_REC_LENGTH; }
uint max_keys() const { return MAX_KEY; }
diff --git a/sql/ha_isam.cc b/sql/ha_isam.cc
index 052e6a4b9ec..6fa54d18aac 100644
--- a/sql/ha_isam.cc
+++ b/sql/ha_isam.cc
@@ -380,7 +380,8 @@ int ha_isam::create(const char *name, register TABLE *form,
}
recinfo_pos->base.type= (int) FIELD_LAST; /* End of fieldinfo */
error=nisam_create(fn_format(buff,name,"","",2+4+16),form->keys,keydef,
- recinfo,form->max_rows,form->min_rows,0,0,0L);
+ recinfo,(ulong) form->max_rows, (ulong) form->min_rows,
+ 0, 0, 0L);
my_free((gptr) recinfo,MYF(0));
DBUG_RETURN(error);
diff --git a/sql/ha_isammrg.cc b/sql/ha_isammrg.cc
index b110ffba2f9..94e394e7665 100644
--- a/sql/ha_isammrg.cc
+++ b/sql/ha_isammrg.cc
@@ -190,13 +190,15 @@ THR_LOCK_DATA **ha_isammrg::store_lock(THD *thd,
THR_LOCK_DATA **to,
enum thr_lock_type lock_type)
{
- MRG_TABLE *table;
+ MRG_TABLE *open_table;
- for (table=file->open_tables ; table != file->end_table ; table++)
+ for (open_table=file->open_tables ;
+ open_table != file->end_table ;
+ open_table++)
{
- *(to++)= &table->table->lock;
- if (lock_type != TL_IGNORE && table->table->lock.type == TL_UNLOCK)
- table->table->lock.type=lock_type;
+ *(to++)= &open_table->table->lock;
+ if (lock_type != TL_IGNORE && open_table->table->lock.type == TL_UNLOCK)
+ open_table->table->lock.type=lock_type;
}
return to;
}
diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc
index c7f0ccf69ee..ae71e362875 100644
--- a/sql/ha_myisam.cc
+++ b/sql/ha_myisam.cc
@@ -576,7 +576,6 @@ int ha_myisam::repair(THD *thd, MI_CHECK &param, bool optimize)
}
if (!optimize ||
- //memcmp(file->state, & share->state.state, sizeof(MI_STATUS_INFO)) ||
((file->state->del || share->state.split != file->state->records) &&
(!(param.testflag & T_QUICK) ||
!(share->state.changed & STATE_NOT_OPTIMIZED_KEYS))))
@@ -635,7 +634,12 @@ int ha_myisam::repair(THD *thd, MI_CHECK &param, bool optimize)
STATE_CRASHED_ON_REPAIR);
file->update|=HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
}
- //file->save_state=file->s->state.state;
+ /*
+ the following 'if', thought conceptually wrong,
+ is a useful optimization nevertheless.
+ */
+ if (file->state != &file->s->state.state);
+ file->s->state.state = *file->state;
if (file->s->base.auto_key)
update_auto_increment_key(&param, file, 1);
if (optimize_done)
@@ -914,7 +918,7 @@ void ha_myisam::info(uint flag)
if (table->key_parts)
memcpy((char*) table->key_info[0].rec_per_key,
(char*) info.rec_per_key,
- sizeof(ulong)*table->key_parts);
+ sizeof(table->key_info[0].rec_per_key)*table->key_parts);
raid_type=info.raid_type;
raid_chunks=info.raid_chunks;
raid_chunksize=info.raid_chunksize;
@@ -1014,7 +1018,7 @@ void ha_myisam::update_create_info(HA_CREATE_INFO *create_info)
}
-int ha_myisam::create(const char *name, register TABLE *table,
+int ha_myisam::create(const char *name, register TABLE *table_arg,
HA_CREATE_INFO *info)
{
int error;
@@ -1026,20 +1030,20 @@ int ha_myisam::create(const char *name, register TABLE *table,
MI_KEYDEF *keydef;
MI_COLUMNDEF *recinfo,*recinfo_pos;
HA_KEYSEG *keyseg;
- uint options=table->db_options_in_use;
+ uint options=table_arg->db_options_in_use;
DBUG_ENTER("ha_myisam::create");
type=HA_KEYTYPE_BINARY; // Keep compiler happy
if (!(my_multi_malloc(MYF(MY_WME),
- &recinfo,(table->fields*2+2)*sizeof(MI_COLUMNDEF),
- &keydef, table->keys*sizeof(MI_KEYDEF),
+ &recinfo,(table_arg->fields*2+2)*sizeof(MI_COLUMNDEF),
+ &keydef, table_arg->keys*sizeof(MI_KEYDEF),
&keyseg,
- ((table->key_parts + table->keys) * sizeof(HA_KEYSEG)),
+ ((table_arg->key_parts + table_arg->keys) * sizeof(HA_KEYSEG)),
0)))
DBUG_RETURN(1);
- pos=table->key_info;
- for (i=0; i < table->keys ; i++, pos++)
+ pos=table_arg->key_info;
+ for (i=0; i < table_arg->keys ; i++, pos++)
{
keydef[i].flag= (pos->flags & (HA_NOSAME | HA_FULLTEXT | HA_SPATIAL));
keydef[i].key_alg=pos->algorithm == HA_KEY_ALG_UNDEF ?
@@ -1084,7 +1088,7 @@ int ha_myisam::create(const char *name, register TABLE *table,
{
keydef[i].seg[j].null_bit=field->null_bit;
keydef[i].seg[j].null_pos= (uint) (field->null_ptr-
- (uchar*) table->record[0]);
+ (uchar*) table_arg->record[0]);
}
else
{
@@ -1102,19 +1106,19 @@ int ha_myisam::create(const char *name, register TABLE *table,
keydef[i].seg[j].flag|=HA_BLOB_PART;
/* save number of bytes used to pack length */
keydef[i].seg[j].bit_start= (uint) (field->pack_length() -
- table->blob_ptr_size);
+ table_arg->blob_ptr_size);
}
}
keyseg+=pos->key_parts;
}
recpos=0; recinfo_pos=recinfo;
- while (recpos < (uint) table->reclength)
+ while (recpos < (uint) table_arg->reclength)
{
Field **field,*found=0;
- minpos=table->reclength; length=0;
+ minpos=table_arg->reclength; length=0;
- for (field=table->field ; *field ; field++)
+ for (field=table_arg->field ; *field ; field++)
{
if ((fieldpos=(*field)->offset()) >= recpos &&
fieldpos <= minpos)
@@ -1160,7 +1164,7 @@ int ha_myisam::create(const char *name, register TABLE *table,
{
recinfo_pos->null_bit=found->null_bit;
recinfo_pos->null_pos= (uint) (found->null_ptr-
- (uchar*) table->record[0]);
+ (uchar*) table_arg->record[0]);
}
else
{
@@ -1175,13 +1179,13 @@ int ha_myisam::create(const char *name, register TABLE *table,
}
MI_CREATE_INFO create_info;
bzero((char*) &create_info,sizeof(create_info));
- create_info.max_rows=table->max_rows;
- create_info.reloc_rows=table->min_rows;
+ create_info.max_rows=table_arg->max_rows;
+ create_info.reloc_rows=table_arg->min_rows;
create_info.auto_increment=(info->auto_increment_value ?
info->auto_increment_value -1 :
(ulonglong) 0);
- create_info.data_file_length= ((ulonglong) table->max_rows *
- table->avg_row_length);
+ create_info.data_file_length= ((ulonglong) table_arg->max_rows *
+ table_arg->avg_row_length);
create_info.raid_type=info->raid_type;
create_info.raid_chunks= (info->raid_chunks ? info->raid_chunks :
RAID_DEFAULT_CHUNKS);
@@ -1191,7 +1195,7 @@ int ha_myisam::create(const char *name, register TABLE *table,
create_info.index_file_name=info->index_file_name;
error=mi_create(fn_format(buff,name,"","",2+4),
- table->keys,keydef,
+ table_arg->keys,keydef,
(uint) (recinfo_pos-recinfo), recinfo,
0, (MI_UNIQUEDEF*) 0,
&create_info,
diff --git a/sql/ha_myisammrg.cc b/sql/ha_myisammrg.cc
index c35bf657445..07683dca73e 100644
--- a/sql/ha_myisammrg.cc
+++ b/sql/ha_myisammrg.cc
@@ -187,6 +187,19 @@ void ha_myisammrg::position(const byte *record)
ha_store_ptr(ref, ref_length, (my_off_t) position);
}
+ha_rows ha_myisammrg::records_in_range(int inx,
+ const byte *start_key,uint start_key_len,
+ enum ha_rkey_function start_search_flag,
+ const byte *end_key,uint end_key_len,
+ enum ha_rkey_function end_search_flag)
+{
+ return (ha_rows) myrg_records_in_range(file,
+ inx,
+ start_key,start_key_len,
+ start_search_flag,
+ end_key,end_key_len,
+ end_search_flag);
+}
void ha_myisammrg::info(uint flag)
{
@@ -262,13 +275,15 @@ THR_LOCK_DATA **ha_myisammrg::store_lock(THD *thd,
THR_LOCK_DATA **to,
enum thr_lock_type lock_type)
{
- MYRG_TABLE *table;
+ MYRG_TABLE *open_table;
- for (table=file->open_tables ; table != file->end_table ; table++)
+ for (open_table=file->open_tables ;
+ open_table != file->end_table ;
+ open_table++)
{
- *(to++)= &table->table->lock;
- if (lock_type != TL_IGNORE && table->table->lock.type == TL_UNLOCK)
- table->table->lock.type=lock_type;
+ *(to++)= &open_table->table->lock;
+ if (lock_type != TL_IGNORE && open_table->table->lock.type == TL_UNLOCK)
+ open_table->table->lock.type=lock_type;
}
return to;
}
@@ -279,14 +294,16 @@ void ha_myisammrg::update_create_info(HA_CREATE_INFO *create_info)
DBUG_ENTER("ha_myisammrg::update_create_info");
if (!(create_info->used_fields & HA_CREATE_USED_UNION))
{
- MYRG_TABLE *table;
+ MYRG_TABLE *open_table;
THD *thd=current_thd;
create_info->merge_list.next= &create_info->merge_list.first;
create_info->merge_list.elements=0;
- for (table=file->open_tables ; table != file->end_table ; table++)
+ for (open_table=file->open_tables ;
+ open_table != file->end_table ;
+ open_table++)
{
- char *name=table->table->filename;
+ char *name=open_table->table->filename;
char buff[FN_REFLEN];
TABLE_LIST *ptr;
if (!(ptr = (TABLE_LIST *) thd->calloc(sizeof(TABLE_LIST))))
@@ -323,7 +340,28 @@ int ha_myisammrg::create(const char *name, register TABLE *form,
sizeof(char*))))
DBUG_RETURN(1);
for (pos=table_names ; tables ; tables=tables->next)
- *pos++= tables->real_name;
+ {
+ char *table_name;
+ if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
+ {
+ TABLE **tbl=find_temporary_table(current_thd,
+ tables->db, tables->real_name);
+ if (!tbl)
+ {
+ table_name=sql_alloc(1+
+ my_snprintf(buff,FN_REFLEN,"%s/%s/%s",mysql_real_data_home,
+ tables->db, tables->real_name));
+ if (!table_name)
+ DBUG_RETURN(1);
+ strcpy(table_name, buff);
+ }
+ else
+ table_name=(*tbl)->path;
+ }
+ else
+ table_name=tables->real_name;
+ *pos++= table_name;
+ }
*pos=0;
DBUG_RETURN(myrg_create(fn_format(buff,name,"","",2+4+16),
(const char **) table_names,
@@ -340,13 +378,15 @@ void ha_myisammrg::append_create_info(String *packet)
packet->append(get_type(&merge_insert_method,file->merge_insert_method-1));
}
packet->append(" UNION=(",8);
- MYRG_TABLE *table,*first;
+ MYRG_TABLE *open_table,*first;
- for (first=table=file->open_tables ; table != file->end_table ; table++)
+ for (first=open_table=file->open_tables ;
+ open_table != file->end_table ;
+ open_table++)
{
- char *name=table->table->filename;
+ char *name= open_table->table->filename;
fn_format(buff,name,"","",3);
- if (table != first)
+ if (open_table != first)
packet->append(',');
packet->append(buff,(uint) strlen(buff));
}
diff --git a/sql/ha_myisammrg.h b/sql/ha_myisammrg.h
index b75d5360097..8e33b99e418 100644
--- a/sql/ha_myisammrg.h
+++ b/sql/ha_myisammrg.h
@@ -69,6 +69,11 @@ class ha_myisammrg: public handler
int rnd_next(byte *buf);
int rnd_pos(byte * buf, byte *pos);
void position(const byte *record);
+ ha_rows ha_myisammrg::records_in_range(int inx,
+ const byte *start_key,uint start_key_len,
+ enum ha_rkey_function start_search_flag,
+ const byte *end_key,uint end_key_len,
+ enum ha_rkey_function end_search_flag);
my_off_t row_position() { return myrg_position(file); }
void info(uint);
int extra(enum ha_extra_function operation);
diff --git a/sql/handler.cc b/sql/handler.cc
index f60c3449075..b2cf86a6abc 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -294,7 +294,8 @@ int ha_commit_trans(THD *thd, THD_TRANS* trans)
error=1;
}
else
- transaction_commited= 1;
+ if (!(thd->options & OPTION_BEGIN))
+ transaction_commited= 1;
trans->bdb_tid=0;
}
#endif
diff --git a/sql/handler.h b/sql/handler.h
index fbc27f4729b..6cbd83af282 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -153,7 +153,6 @@ typedef struct st_ha_create_information
CHARSET_INFO *table_charset;
char *comment,*password;
char *data_file_name, *index_file_name;
- char *create_statement;
ulonglong max_rows,min_rows;
ulonglong auto_increment_value;
ulong table_options;
@@ -230,7 +229,7 @@ public:
void change_table_ptr(TABLE *table_arg) { table=table_arg; }
virtual double scan_time()
{ return ulonglong2double(data_file_length) / IO_SIZE + 1; }
- virtual double read_time(ha_rows rows) { return rows; }
+ virtual double read_time(ha_rows rows) { return rows2double(rows); }
virtual bool fast_key_read() { return 0;}
virtual key_map keys_to_use_for_scanning() { return 0; }
virtual bool has_transactions(){ return 0;}
diff --git a/sql/hash_filo.h b/sql/hash_filo.h
index 4d746d9b9bd..f7384cc6e32 100644
--- a/sql/hash_filo.h
+++ b/sql/hash_filo.h
@@ -40,7 +40,7 @@ class hash_filo
{
const uint size, key_offset, key_length;
const hash_get_key get_key;
- void (*free_element)(void*);
+ hash_free_key free_element;
bool init;
hash_filo_element *first_link,*last_link;
@@ -49,7 +49,7 @@ public:
HASH cache;
hash_filo(uint size_arg, uint key_offset_arg , uint key_length_arg,
- hash_get_key get_key_arg,void (*free_element_arg)(void*))
+ hash_get_key get_key_arg, hash_free_key free_element_arg)
:size(size_arg), key_offset(key_offset_arg), key_length(key_length_arg),
get_key(get_key_arg), free_element(free_element_arg),init(0)
{
diff --git a/sql/hostname.cc b/sql/hostname.cc
index 3da752f3b64..609532a67d6 100644
--- a/sql/hostname.cc
+++ b/sql/hostname.cc
@@ -63,7 +63,7 @@ bool hostname_cache_init()
if (!(hostname_cache=new hash_filo(HOST_CACHE_SIZE, offset,
sizeof(struct in_addr),NULL,
- (void (*)(void*)) free)))
+ (hash_free_key) free)))
return 1;
hostname_cache->clear();
return 0;
diff --git a/sql/item.cc b/sql/item.cc
index 9c70dad045c..48ec11d02c2 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -42,6 +42,20 @@ Item::Item()
decimals=0; max_length=0;
next=current_thd->free_list; // Put in free list
current_thd->free_list=this;
+ loop_id= 0;
+}
+
+bool Item::check_loop(uint id)
+{
+ DBUG_ENTER("Item::check_loop");
+ DBUG_PRINT("info", ("id %u, name %s", id, name));
+ if (loop_id == id)
+ {
+ DBUG_PRINT("info", ("id match"));
+ DBUG_RETURN(1);
+ }
+ loop_id= id;
+ DBUG_RETURN(0);
}
void Item::set_name(const char *str,uint length)
@@ -444,13 +458,16 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
cause error ER_NON_UNIQ_ERROR in find_field_in_tables.
*/
SELECT_LEX *last= 0;
- for (SELECT_LEX *sl= thd->lex.current_select->outer_select();
- sl;
- sl= sl->outer_select())
- if ((tmp= find_field_in_tables(thd, this,
- (last= sl)->get_table_list(),
- 0)) != not_found_field)
- break;
+
+ // Prevent using outer fields in subselects, that is not supported now
+ if (thd->lex.current_select->linkage != DERIVED_TABLE_TYPE)
+ for (SELECT_LEX *sl= thd->lex.current_select->outer_select();
+ sl;
+ sl= sl->outer_select())
+ if ((tmp= find_field_in_tables(thd, this,
+ (last= sl)->get_table_list(),
+ 0)) != not_found_field)
+ break;
if (!tmp)
return -1;
else if (tmp == not_found_field)
@@ -812,10 +829,18 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
if (!ref)
{
SELECT_LEX *sl= thd->lex.current_select->outer_select();
+ /*
+ Finding only in current select will be performed for selects that have
+ not outer one and for derived tables (which not support using outer
+ fields for now)
+ */
if ((ref= find_item_in_list(this,
*(thd->lex.current_select->get_item_list()),
- (sl ? REPORT_EXCEPT_NOT_FOUND :
- REPORT_ALL_ERRORS))) ==
+ ((sl &&
+ thd->lex.current_select->linkage !=
+ DERIVED_TABLE_TYPE) ?
+ REPORT_EXCEPT_NOT_FOUND :
+ REPORT_ALL_ERRORS))) ==
(Item **)not_found_item)
{
/*
@@ -851,6 +876,7 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
{
depended_from= last;
thd->lex.current_select->mark_as_dependent(last);
+ thd->add_possible_loop(this);
}
}
else if (!ref)
@@ -862,6 +888,14 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
return 0;
}
+bool Item_ref::check_loop(uint id)
+{
+ DBUG_ENTER("Item_ref::check_loop");
+ if (Item_ident::check_loop(id))
+ DBUG_RETURN(1);
+ DBUG_RETURN((*ref)->check_loop(id));
+}
+
/*
** If item is a const function, calculate it and return a const item
** The original item is freed if not returned
diff --git a/sql/item.h b/sql/item.h
index fb6bed75d51..5eeaa22a2a2 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -20,10 +20,11 @@
#endif
struct st_table_list;
-void item_init(void); /* Init item functions */
+void item_init(void); /* Init item functions */
class Item {
- Item(const Item &); /* Prevent use of these */
+ uint loop_id; /* Used to find selfrefering loops */
+ Item(const Item &); /* Prevent use of these */
void operator=(Item &);
public:
static void *operator new(size_t size) {return (void*) sql_alloc((uint) size); }
@@ -88,6 +89,8 @@ public:
virtual CHARSET_INFO *charset() const { return str_value.charset(); };
virtual bool binary() const { return str_value.charset()->state & MY_CS_BINSORT ? 1 : 0 ; }
virtual void set_charset(CHARSET_INFO *cs) { str_value.set_charset(cs); }
+ virtual bool check_loop(uint id);
+ virtual void top_level_item() {}
};
@@ -434,6 +437,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(); }
+ bool check_loop(uint id);
};
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index b6ea4beb339..1065c8cf023 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -27,8 +27,8 @@
/*
Test functions
- These returns 0LL if false and 1LL if true and null if some arg is null
- 'AND' and 'OR' never return null
+ Most of these returns 0LL if false and 1LL if true and
+ NULL if some arg is NULL.
*/
longlong Item_func_not::val_int()
@@ -344,6 +344,14 @@ void Item_func_interval::update_used_tables()
const_item_cache&=item->const_item();
}
+bool Item_func_interval::check_loop(uint id)
+{
+ DBUG_ENTER("Item_func_interval::check_loop");
+ if (Item_func::check_loop(id))
+ DBUG_RETURN(1);
+ DBUG_RETURN(item->check_loop(id));
+}
+
void Item_func_between::fix_length_and_dec()
{
max_length=1;
@@ -354,13 +362,19 @@ void Item_func_between::fix_length_and_dec()
*/
if (!args[0] || !args[1] || !args[2])
return;
- cmp_type=args[0]->result_type();
- if (args[0]->binary())
+ cmp_type=item_cmp_type(args[0]->result_type(),
+ item_cmp_type(args[1]->result_type(),
+ args[2]->result_type()));
+ if (args[0]->binary() | args[1]->binary() | args[2]->binary())
string_compare=stringcmp;
else
string_compare=sortcmp;
- // Make a special case of compare with fields to get nicer DATE comparisons
+ /*
+ Make a special case of compare with date/time and longlong fields.
+ They are compared as integers, so for const item this time-consuming
+ conversion can be done only once, not for every single comparison
+ */
if (args[0]->type() == FIELD_ITEM)
{
Field *field=((Item_field*) args[0])->field;
@@ -776,6 +790,16 @@ Item_func_case::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
return 0;
}
+bool Item_func_case::check_loop(uint id)
+{
+ DBUG_ENTER("Item_func_case::check_loop");
+ if (Item_func::check_loop(id))
+ DBUG_RETURN(1);
+
+ DBUG_RETURN((first_expr && first_expr->check_loop(id)) ||
+ (else_expr && else_expr->check_loop(id)));
+}
+
void Item_func_case::update_used_tables()
{
Item_func::update_used_tables();
@@ -1123,6 +1147,8 @@ Item_cond::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
#endif
item= *li.ref(); // new current item
}
+ if (abort_on_null)
+ item->top_level_item();
if (item->fix_fields(thd, tables, li.ref()))
return 1; /* purecov: inspected */
used_tables_cache|=item->used_tables();
@@ -1137,6 +1163,20 @@ Item_cond::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
return 0;
}
+bool Item_cond::check_loop(uint id)
+{
+ DBUG_ENTER("Item_cond::check_loop");
+ if (Item_func::check_loop(id))
+ DBUG_RETURN(1);
+ List_iterator<Item> li(list);
+ Item *item;
+ while ((item= li++))
+ {
+ if (item->check_loop(id))
+ DBUG_RETURN(1);
+ }
+ DBUG_RETURN(0);
+}
void Item_cond::split_sum_func(List<Item> &fields)
{
@@ -1198,28 +1238,41 @@ void Item_cond::print(String *str)
str->append(')');
}
+/*
+ Evalution of AND(expr, expr, expr ...)
+
+ NOTES:
+ abort_if_null is set for AND expressions for which we don't care if the
+ result is NULL or 0. This is set for:
+ - WHERE clause
+ - HAVING clause
+ - IF(expression)
+
+ RETURN VALUES
+ 1 If all expressions are true
+ 0 If all expressions are false or if we find a NULL expression and
+ 'abort_on_null' is set.
+ NULL if all expression are either 1 or NULL
+*/
+
longlong Item_cond_and::val_int()
{
List_iterator_fast<Item> li(list);
Item *item;
+ null_value= 0;
while ((item=li++))
{
if (item->val_int() == 0)
{
- /*
- TODO: In case of NULL, ANSI would require us to continue evaluation
- until we get a FALSE value or run out of values; This would
- require a lot of unnecessary evaluation, which we skip for now
- */
- null_value=item->null_value;
- return 0;
+ if (abort_on_null || !(null_value= item->null_value))
+ return 0; // return FALSE
}
}
- null_value=0;
- return 1;
+ return null_value ? 0 : 1;
}
+
longlong Item_cond_or::val_int()
{
List_iterator_fast<Item> li(list);
@@ -1238,6 +1291,45 @@ longlong Item_cond_or::val_int()
return 0;
}
+/*
+ Create an AND expression from two expressions
+
+ SYNOPSIS
+ and_expressions()
+ a expression or NULL
+ b expression.
+ org_item Don't modify a if a == *org_item
+ If a == NULL, org_item is set to point at b,
+ to ensure that future calls will not modify b.
+
+ NOTES
+ This will not modify item pointed to by org_item or b
+ The idea is that one can call this in a loop and create and
+ 'and' over all items without modifying any of the original items.
+
+ RETURN
+ NULL Error
+ Item
+*/
+
+Item *and_expressions(Item *a, Item *b, Item **org_item)
+{
+ if (!a)
+ return (*org_item= b);
+ if (a == *org_item)
+ {
+ Item_cond *res;
+ if ((res= new Item_cond_and(a, b)))
+ res->used_tables_cache= a->used_tables() | b->used_tables();
+ return res;
+ }
+ if (((Item_cond_and*) a)->add(b))
+ return 0;
+ ((Item_cond_and*) a)->used_tables_cache|= b->used_tables();
+ return a;
+}
+
+
longlong Item_func_isnull::val_int()
{
/*
@@ -1281,10 +1373,10 @@ longlong Item_func_like::val_int()
set_charset(my_charset_bin);
if (canDoTurboBM)
return turboBM_matches(res->ptr(), res->length()) ? 1 : 0;
- if (binary())
- return wild_compare(*res,*res2,escape) ? 0 : 1;
- else
- return wild_case_compare(*res,*res2,escape) ? 0 : 1;
+ return my_wildcmp(charset(),
+ res->ptr(),res->ptr()+res->length(),
+ res2->ptr(),res2->ptr()+res2->length(),
+ escape,wild_one,wild_many) ? 0 : 1;
}
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index c0dcc2bba8f..f94c520cc15 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -186,6 +186,7 @@ public:
~Item_func_interval() { delete item; }
const char *func_name() const { return "interval"; }
void update_used_tables();
+ bool check_loop(uint id);
};
@@ -212,6 +213,11 @@ public:
longlong val_int();
String *val_str(String *str);
enum Item_result result_type () const { return cached_result_type; }
+ bool fix_fields(THD *thd,struct st_table_list *tlist, Item **ref)
+ {
+ args[0]->top_level_item();
+ return Item_func::fix_fields(thd, tlist, ref);
+ }
void fix_length_and_dec();
const char *func_name() const { return "if"; }
};
@@ -262,6 +268,7 @@ public:
void print(String *str);
bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref);
Item *find_item(String *str);
+ bool check_loop(uint id);
};
@@ -284,9 +291,9 @@ public:
virtual void set(uint pos,Item *item)=0;
virtual byte *get_value(Item *item)=0;
void sort()
- {
- qsort(base,used_count,size,compare);
- }
+ {
+ qsort(base,used_count,size,compare);
+ }
int find(Item *item);
};
@@ -424,6 +431,13 @@ class Item_func_in :public Item_int_func
enum Functype functype() const { return IN_FUNC; }
const char *func_name() const { return " IN "; }
void update_used_tables();
+ bool check_loop(uint id)
+ {
+ DBUG_ENTER("Item_func_in::check_loop");
+ if (Item_func::check_loop(id))
+ DBUG_RETURN(1);
+ DBUG_RETURN(item->check_loop(id));
+ }
};
@@ -548,10 +562,12 @@ class Item_cond :public Item_bool_func
{
protected:
List<Item> list;
+ bool abort_on_null;
public:
- Item_cond() : Item_bool_func() { const_item_cache=0; }
- Item_cond(Item *i1,Item *i2) :Item_bool_func()
- { list.push_back(i1); list.push_back(i2); }
+ /* Item_cond() is only used to create top level items */
+ Item_cond() : Item_bool_func(), abort_on_null(1) { const_item_cache=0; }
+ Item_cond(Item *i1,Item *i2) :Item_bool_func(), abort_on_null(0)
+ { list.push_back(i1); list.push_back(i2); }
~Item_cond() { list.delete_elements(); }
bool add(Item *item) { return list.push_back(item); }
bool fix_fields(THD *, struct st_table_list *, Item **ref);
@@ -563,6 +579,8 @@ public:
void print(String *str);
void split_sum_func(List<Item> &fields);
friend int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds);
+ bool check_loop(uint id);
+ void top_level_item() { abort_on_null=1; }
};
@@ -610,6 +628,7 @@ inline Item *and_conds(Item *a,Item *b)
return cond;
}
+Item *and_expressions(Item *a, Item *b, Item **org_item);
/**************************************************************
Spatial relations
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 543a96107dc..75260065be6 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -126,6 +126,22 @@ Item_func::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
return 0;
}
+bool Item_func::check_loop(uint id)
+{
+ DBUG_ENTER("Item_func::check_loop");
+ if (Item_result_field::check_loop(id))
+ DBUG_RETURN(1);
+ if (arg_count)
+ {
+ Item **arg,**arg_end;
+ for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
+ {
+ if ((*arg)->check_loop(id))
+ DBUG_RETURN(1);
+ }
+ }
+ DBUG_RETURN(0);
+}
void Item_func::split_sum_func(List<Item> &fields)
{
@@ -439,6 +455,25 @@ void Item_func_div::fix_length_and_dec()
maybe_null=1;
}
+
+/* Integer division */
+longlong Item_func_int_div::val_int()
+{
+ longlong value=args[0]->val_int();
+ longlong val2=args[1]->val_int();
+ if ((null_value= val2 == 0 || args[0]->null_value || args[1]->null_value))
+ return 0;
+ return value/val2;
+}
+
+
+void Item_func_int_div::fix_length_and_dec()
+{
+ max_length=args[0]->max_length - args[0]->decimals;
+ maybe_null=1;
+}
+
+
double Item_func_mod::val()
{
double value= floor(args[0]->val()+0.5);
@@ -752,13 +787,14 @@ double Item_func_rand::val()
}
else if (!thd->rand_used)
{
- // no need to send a Rand log event if seed was given eg: RAND(seed),
- // as it will be replicated in the query as such.
-
- // save the seed only the first time RAND() is used in the query
+ /*
+ No need to send a Rand log event if seed was given eg: RAND(seed),
+ as it will be replicated in the query as such.
- // once events are forwarded rather than recreated,
- // the following can be skipped if inside the slave thread
+ Save the seed only the first time RAND() is used in the query
+ Once events are forwarded rather than recreated,
+ the following can be skipped if inside the slave thread
+ */
thd->rand_used=1;
thd->rand_saved_seed1=thd->rand.seed1;
thd->rand_saved_seed2=thd->rand.seed2;
@@ -1571,7 +1607,7 @@ void item_user_lock_release(ULL *ull)
tmp.copy(command, strlen(command), tmp.charset());
tmp.append(ull->key,ull->key_length);
tmp.append("\")");
- Query_log_event qev(current_thd,tmp.ptr(), tmp.length());
+ Query_log_event qev(current_thd, tmp.ptr(), tmp.length(),1);
qev.error_code=0; // this query is always safe to run on slave
mysql_bin_log.write(&qev);
}
@@ -2016,13 +2052,13 @@ void Item_func_set_user_var::print(String *str)
user_var_entry *Item_func_get_user_var::get_entry()
{
- if (!entry || ! entry->value)
+ if (!var_entry || ! var_entry->value)
{
null_value=1;
return 0;
}
null_value=0;
- return entry;
+ return var_entry;
}
@@ -2091,8 +2127,8 @@ void Item_func_get_user_var::fix_length_and_dec()
maybe_null=1;
decimals=NOT_FIXED_DEC;
max_length=MAX_BLOB_WIDTH;
- if ((entry= get_variable(&thd->user_vars, name, 0)))
- const_var_flag= thd->query_id != entry->update_query_id;
+ if ((var_entry= get_variable(&thd->user_vars, name, 0)))
+ const_var_flag= thd->query_id != var_entry->update_query_id;
}
@@ -2264,23 +2300,36 @@ bool Item_func_match::fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
return 0;
}
+bool Item_func_match::check_loop(uint id)
+{
+ DBUG_ENTER("Item_func_match::check_loop");
+ if (Item_real_func::check_loop(id))
+ DBUG_RETURN(1);
+
+ List_iterator<Item> li(fields);
+ Item *item;
+ while ((item= li++))
+ if (item->check_loop(id))
+ DBUG_RETURN(1);
+ DBUG_RETURN(0);
+}
bool Item_func_match::fix_index()
{
List_iterator_fast<Item> li(fields);
Item_field *item;
- uint ft_to_key[MAX_KEY], ft_cnt[MAX_KEY], fts=0, key;
+ uint ft_to_key[MAX_KEY], ft_cnt[MAX_KEY], fts=0, keynr;
uint max_cnt=0, mkeys=0;
- if (this->key == NO_SUCH_KEY)
+ if (key == NO_SUCH_KEY)
return 0;
- for (key=0 ; key<table->keys ; key++)
+ for (keynr=0 ; keynr < table->keys ; keynr++)
{
- if ((table->key_info[key].flags & HA_FULLTEXT) &&
- (table->keys_in_use_for_query & (((key_map)1) << key)))
+ if ((table->key_info[keynr].flags & HA_FULLTEXT) &&
+ (table->keys_in_use_for_query & (((key_map)1) << keynr)))
{
- ft_to_key[fts]=key;
+ ft_to_key[fts]=keynr;
ft_cnt[fts]=0;
fts++;
}
@@ -2291,45 +2340,45 @@ bool Item_func_match::fix_index()
while ((item=(Item_field*)(li++)))
{
- for (key=0 ; key<fts ; key++)
+ for (keynr=0 ; keynr < fts ; keynr++)
{
- KEY *ft_key=&table->key_info[ft_to_key[key]];
+ KEY *ft_key=&table->key_info[ft_to_key[keynr]];
uint key_parts=ft_key->key_parts;
for (uint part=0 ; part < key_parts ; part++)
{
if (item->field->eq(ft_key->key_part[part].field))
- ft_cnt[key]++;
+ ft_cnt[keynr]++;
}
}
}
- for (key=0 ; key<fts ; key++)
+ for (keynr=0 ; keynr < fts ; keynr++)
{
- if (ft_cnt[key] > max_cnt)
+ if (ft_cnt[keynr] > max_cnt)
{
mkeys=0;
- max_cnt=ft_cnt[mkeys]=ft_cnt[key];
- ft_to_key[mkeys]=ft_to_key[key];
+ max_cnt=ft_cnt[mkeys]=ft_cnt[keynr];
+ ft_to_key[mkeys]=ft_to_key[keynr];
continue;
}
- if (max_cnt && ft_cnt[key] == max_cnt)
+ if (max_cnt && ft_cnt[keynr] == max_cnt)
{
mkeys++;
- ft_cnt[mkeys]=ft_cnt[key];
- ft_to_key[mkeys]=ft_to_key[key];
+ ft_cnt[mkeys]=ft_cnt[keynr];
+ ft_to_key[mkeys]=ft_to_key[keynr];
continue;
}
}
- for (key=0 ; key<=mkeys ; key++)
+ for (keynr=0 ; keynr <= mkeys ; keynr++)
{
// for now, partial keys won't work. SerG
if (max_cnt < fields.elements ||
- max_cnt < table->key_info[ft_to_key[key]].key_parts)
+ max_cnt < table->key_info[ft_to_key[keynr]].key_parts)
continue;
- this->key=ft_to_key[key];
+ key=ft_to_key[keynr];
return 0;
}
@@ -2337,7 +2386,7 @@ bool Item_func_match::fix_index()
err:
if (mode == FT_BOOL)
{
- this->key=NO_SUCH_KEY;
+ key=NO_SUCH_KEY;
return 0;
}
my_printf_error(ER_FT_MATCHING_KEY_NOT_FOUND,
diff --git a/sql/item_func.h b/sql/item_func.h
index 1e1f2ba39fc..b659a6d69d2 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -128,6 +128,7 @@ public:
bool is_null() { (void) val_int(); return null_value; }
friend class udf_handler;
Field *tmp_table_field(TABLE *t_arg);
+ bool check_loop(uint id);
};
@@ -253,6 +254,18 @@ public:
};
+class Item_func_int_div :public Item_num_op
+{
+public:
+ Item_func_int_div(Item *a,Item *b) :Item_num_op(a,b)
+ { hybrid_type=INT_RESULT; }
+ double val() { return (double) val_int(); }
+ longlong val_int();
+ const char *func_name() const { return "DIV"; }
+ void fix_length_and_dec();
+};
+
+
class Item_func_mod :public Item_num_op
{
public:
@@ -606,6 +619,13 @@ public:
const_item_cache&= item->const_item();
with_sum_func= with_sum_func || item->with_sum_func;
}
+ bool check_loop(uint id)
+ {
+ DBUG_ENTER("Item_func_field::check_loop");
+ if (Item_int_func::check_loop(id))
+ DBUG_RETURN(1);
+ DBUG_RETURN(item->check_loop(id));
+ }
};
@@ -898,7 +918,7 @@ public:
class Item_func_get_user_var :public Item_func
{
LEX_STRING name;
- user_var_entry *entry;
+ user_var_entry *var_entry;
bool const_var_flag;
public:
@@ -971,6 +991,7 @@ public:
bool fix_index();
void init_search(bool no_order);
+ bool check_loop(uint id);
};
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index e7d16387a00..133a2f4baeb 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -1380,17 +1380,25 @@ String *Item_func_database::val_str(String *str)
if (!current_thd->db)
str->length(0);
else
- str->set((const char*) current_thd->db,(uint) strlen(current_thd->db), default_charset_info);
+ str->copy((const char*) current_thd->db,(uint) strlen(current_thd->db), system_charset_info, thd_charset());
return str;
}
String *Item_func_user::val_str(String *str)
{
- THD *thd=current_thd;
- if (str->copy((const char*) thd->user,(uint) strlen(thd->user), system_charset_info) ||
- str->append('@') ||
- str->append(thd->host ? thd->host : thd->ip ? thd->ip : ""))
- return &empty_string;
+ THD *thd=current_thd;
+ CHARSET_INFO *cs=thd_charset();
+ const char *host=thd->host ? thd->host : thd->ip ? thd->ip : "";
+ uint32 res_length=(strlen(thd->user)+strlen(host)+10) * cs->mbmaxlen;
+
+ if (str->alloc(res_length))
+ {
+ null_value=1;
+ return 0;
+ }
+ res_length=cs->snprintf(cs, (char*)str->ptr(), res_length, "%s@%s",thd->user,host);
+ str->length(res_length);
+ str->set_charset(cs);
return str;
}
@@ -1942,7 +1950,7 @@ String *Item_func_conv_charset::val_str(String *str)
s=(const uchar*)arg->ptr();
se=s+arg->length();
- dmaxlen=arg->length()*(to->mbmaxlen?to->mbmaxlen:1)+1;
+ dmaxlen=arg->length()*to->mbmaxlen+1;
str->alloc(dmaxlen);
d0=d=(unsigned char*)str->ptr();
de=d+dmaxlen;
@@ -1984,7 +1992,7 @@ outp:
void Item_func_conv_charset::fix_length_and_dec()
{
- max_length = args[0]->max_length*(conv_charset->mbmaxlen?conv_charset->mbmaxlen:1);
+ max_length = args[0]->max_length*conv_charset->mbmaxlen;
set_charset(conv_charset);
}
@@ -2016,7 +2024,7 @@ String *Item_func_conv_charset3::val_str(String *str)
s=(const uchar*)arg->ptr();
se=s+arg->length();
- dmaxlen=arg->length()*(to_charset->mbmaxlen?to_charset->mbmaxlen:1)+1;
+ dmaxlen=arg->length()*to_charset->mbmaxlen+1;
str->alloc(dmaxlen);
d0=d=(unsigned char*)str->ptr();
de=d+dmaxlen;
@@ -2134,7 +2142,7 @@ String *Item_func_charset::val_str(String *str)
if ((null_value=(args[0]->null_value || !res->charset())))
return 0;
- str->copy(res->charset()->name,strlen(res->charset()->name),default_charset_info);
+ str->copy(res->charset()->name,strlen(res->charset()->name),my_charset_latin1,thd_charset());
return str;
}
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index 03e58705ce5..0b0afc2de96 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -108,6 +108,13 @@ public:
|| Item_func::fix_fields(thd, tlist, ref));
}
const char *func_name() const { return "concat_ws"; }
+ bool check_loop(uint id)
+ {
+ DBUG_ENTER("Item_func_concat_ws::check_loop");
+ if (Item_str_func::check_loop(id))
+ DBUG_RETURN(1);
+ DBUG_RETURN(separator->check_loop(id));
+ }
};
class Item_func_reverse :public Item_str_func
@@ -326,7 +333,11 @@ class Item_func_database :public Item_str_func
public:
Item_func_database() {}
String *val_str(String *);
- void fix_length_and_dec() { max_length= MAX_FIELD_NAME; }
+ void fix_length_and_dec()
+ {
+ max_length= MAX_FIELD_NAME * thd_charset()->mbmaxlen;
+ set_charset(thd_charset());
+ }
const char *func_name() const { return "database"; }
};
@@ -335,7 +346,11 @@ class Item_func_user :public Item_str_func
public:
Item_func_user() {}
String *val_str(String *);
- void fix_length_and_dec() { max_length= USERNAME_LENGTH+HOSTNAME_LENGTH+1; }
+ void fix_length_and_dec()
+ {
+ max_length= (USERNAME_LENGTH+HOSTNAME_LENGTH+1)*thd_charset()->mbmaxlen;
+ set_charset(thd_charset());
+ }
const char *func_name() const { return "user"; }
};
@@ -369,6 +384,13 @@ public:
void fix_length_and_dec();
void update_used_tables();
const char *func_name() const { return "elt"; }
+ bool check_loop(uint id)
+ {
+ DBUG_ENTER("Item_func_elt::check_loop");
+ if (Item_str_func::check_loop(id))
+ DBUG_RETURN(1);
+ DBUG_RETURN(item->check_loop(id));
+ }
};
@@ -389,6 +411,13 @@ public:
void fix_length_and_dec();
void update_used_tables();
const char *func_name() const { return "make_set"; }
+ bool check_loop(uint id)
+ {
+ DBUG_ENTER("Item_func_make_set::check_loop");
+ if (Item_str_func::check_loop(id))
+ DBUG_RETURN(1);
+ DBUG_RETURN(item->check_loop(id));
+ }
};
@@ -583,7 +612,8 @@ public:
const char *func_name() const { return "charset"; }
void fix_length_and_dec()
{
- max_length=20; // should be enough
+ max_length=40; // should be enough
+ set_charset(thd_charset());
};
};
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 703173b191c..1f1944026ef 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -33,7 +33,7 @@ SUBSELECT TODO:
#include "sql_select.h"
Item_subselect::Item_subselect():
- Item(), engine_owner(1), value_assigned(0)
+ Item_result_field(), engine_owner(1), value_assigned(0)
{
assign_null();
/*
@@ -95,6 +95,15 @@ bool Item_subselect::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
return res;
}
+bool Item_subselect::check_loop(uint id)
+{
+ DBUG_ENTER("Item_subselect::check_loop");
+ if (Item_result_field::check_loop(id))
+ DBUG_RETURN(1);
+
+ DBUG_RETURN(engine->check_loop(id));
+}
+
void Item_subselect::fix_length_and_dec()
{
engine->fix_length_and_dec();
@@ -228,6 +237,7 @@ subselect_single_select_engine::subselect_single_select_engine(THD *thd,
thd->fatal_error= 1;
my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
}
+ unit->item= item;
this->select_lex= select_lex;
}
@@ -353,3 +363,18 @@ bool subselect_union_engine::depended()
{
return unit->dependent;
}
+
+bool subselect_single_select_engine::check_loop(uint id)
+{
+ DBUG_ENTER("subselect_single_select_engine::check_loop");
+ DBUG_RETURN(join->check_loop(id));
+}
+
+bool subselect_union_engine::check_loop(uint id)
+{
+ DBUG_ENTER("subselect_union_engine::check_loop");
+ for (SELECT_LEX *sl= unit->first_select(); sl; sl= sl->next_select())
+ if (sl->join && sl->join->check_loop(id))
+ DBUG_RETURN(1);
+ DBUG_RETURN(0);
+}
diff --git a/sql/item_subselect.h b/sql/item_subselect.h
index 33f82982708..3ad6c68a6ba 100644
--- a/sql/item_subselect.h
+++ b/sql/item_subselect.h
@@ -28,7 +28,7 @@ class subselect_engine;
/* base class for subselects */
-class Item_subselect :public Item
+class Item_subselect :public Item_result_field
{
my_bool engine_owner; /* Is this item owner of engine */
my_bool value_assigned; /* value already assigned to subselect */
@@ -70,6 +70,7 @@ public:
bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref);
virtual void fix_length_and_dec();
table_map used_tables() const;
+ bool check_loop(uint id);
friend class select_subselect;
};
@@ -116,6 +117,7 @@ public:
Item *new_item() { return new Item_singleval_subselect(this); }
enum Item_result result_type() const { return res_type; }
void fix_length_and_dec();
+
friend class select_singleval_subselect;
};
@@ -175,6 +177,7 @@ public:
virtual uint cols()= 0; /* return number of columnss in select */
virtual bool depended()= 0; /* depended from outer select */
enum Item_result type() { return res_type; }
+ virtual bool check_loop(uint id)= 0;
};
class subselect_single_select_engine: public subselect_engine
@@ -188,11 +191,12 @@ public:
subselect_single_select_engine(THD *thd, st_select_lex *select,
select_subselect *result,
Item_subselect *item);
- virtual int prepare();
- virtual void fix_length_and_dec();
- virtual int exec();
- virtual uint cols();
- virtual bool depended();
+ int prepare();
+ void fix_length_and_dec();
+ int exec();
+ uint cols();
+ bool depended();
+ bool check_loop(uint id);
};
class subselect_union_engine: public subselect_engine
@@ -203,9 +207,10 @@ public:
st_select_lex_unit *u,
select_subselect *result,
Item_subselect *item);
- virtual int prepare();
- virtual void fix_length_and_dec();
- virtual int exec();
- virtual uint cols();
- virtual bool depended();
+ int prepare();
+ void fix_length_and_dec();
+ int exec();
+ uint cols();
+ bool depended();
+ bool check_loop(uint id);
};
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index 8a1bd0be291..7c085a1b25a 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -153,14 +153,17 @@ longlong Item_func_month::val_int()
String* Item_func_monthname::val_str(String* str)
{
- uint month=(uint) Item_func_month::val_int();
+ uint month=(uint) Item_func_month::val_int();
if (!month) // This is also true for NULL
{
null_value=1;
return (String*) 0;
}
null_value=0;
- return &month_names[month-1];
+
+ String *m=&month_names[month-1];
+ str->copy(m->ptr(), m->length(), m->charset(), thd_charset());
+ return str;
}
// Returns the quarter of the year
@@ -195,15 +198,28 @@ longlong Item_func_second::val_int()
}
-// Returns the week of year in the range of 0 - 53
+/*
+ Returns the week of year.
+
+ The bits in week_format has the following meaning:
+ 0 If not set: USA format: Sunday is first day of week
+ If set: ISO format: Monday is first day of week
+ 1 If not set: Week is in range 0-53
+ If set Week is in range 1-53.
+*/
longlong Item_func_week::val_int()
{
uint year;
+ uint week_format;
TIME ltime;
if (get_arg0_date(&ltime,0))
return 0;
- return (longlong) calc_week(&ltime, 0, args[1]->val_int() == 0, &year);
+ week_format= (uint) args[1]->val_int();
+ return (longlong) calc_week(&ltime,
+ (week_format & 2) != 0,
+ (week_format & 1) == 0,
+ &year);
}
@@ -213,7 +229,7 @@ longlong Item_func_yearweek::val_int()
TIME ltime;
if (get_arg0_date(&ltime,0))
return 0;
- week=calc_week(&ltime, 1, args[1]->val_int() == 0, &year);
+ week=calc_week(&ltime, 1, (args[1]->val_int() & 1) == 0, &year);
return week+year*100;
}
@@ -234,7 +250,10 @@ String* Item_func_dayname::val_str(String* str)
uint weekday=(uint) val_int(); // Always Item_func_daynr()
if (null_value)
return (String*) 0;
- return &day_names[weekday];
+
+ String *d=&day_names[weekday];
+ str->copy(d->ptr(), d->length(), d->charset(), thd_charset());
+ return str;
}
@@ -396,16 +415,16 @@ String *Item_date::val_str(String *str)
return (String*) 0;
if (!value) // zero daynr
{
- str->copy("0000-00-00",10,my_charset_latin1);
+ str->copy("0000-00-00",10,my_charset_latin1,thd_charset());
return str;
}
- if (str->alloc(11))
- return &empty_string; /* purecov: inspected */
- sprintf((char*) str->ptr(),"%04d-%02d-%02d",
+
+ char tmpbuff[11];
+ sprintf(tmpbuff,"%04d-%02d-%02d",
(int) (value/10000L) % 10000,
(int) (value/100)%100,
(int) (value%100));
- str->length(10);
+ str->copy(tmpbuff,10,my_charset_latin1,thd_charset());
return str;
}
@@ -442,7 +461,10 @@ void Item_func_curdate::fix_length_and_dec()
{
struct tm tm_tmp,*start;
time_t query_start=current_thd->query_start();
- decimals=0; max_length=10;
+
+ set_charset(thd_charset());
+ decimals=0;
+ max_length=10*thd_charset()->mbmaxlen;
localtime_r(&query_start,&tm_tmp);
start=&tm_tmp;
value=(longlong) ((ulong) ((uint) start->tm_year+1900)*10000L+
@@ -467,27 +489,48 @@ bool Item_func_curdate::get_date(TIME *res,
return 0;
}
+String *Item_func_curtime::val_str(String *str)
+{
+ str_value.set(buff,buff_length,thd_charset());
+ return &str_value;
+}
+
void Item_func_curtime::fix_length_and_dec()
{
struct tm tm_tmp,*start;
time_t query_start=current_thd->query_start();
- decimals=0; max_length=8;
+ CHARSET_INFO *cs=thd_charset();
+
+ decimals=0;
+ max_length=8*cs->mbmaxlen;
localtime_r(&query_start,&tm_tmp);
start=&tm_tmp;
+ set_charset(cs);
value=(longlong) ((ulong) ((uint) start->tm_hour)*10000L+
(ulong) (((uint) start->tm_min)*100L+
(uint) start->tm_sec));
- buff_length= my_sprintf(buff, (buff,"%02d:%02d:%02d",
+
+ buff_length=cs->snprintf(cs,buff,sizeof(buff),"%02d:%02d:%02d",
(int) start->tm_hour,
(int) start->tm_min,
- (int) start->tm_sec));
+ (int) start->tm_sec);
+}
+
+String *Item_func_now::val_str(String *str)
+{
+ str_value.set(buff,buff_length,thd_charset());
+ return &str_value;
}
void Item_func_now::fix_length_and_dec()
{
struct tm tm_tmp,*start;
time_t query_start=current_thd->query_start();
- decimals=0; max_length=19;
+ CHARSET_INFO *cs=thd_charset();
+
+ decimals=0;
+ max_length=19*cs->mbmaxlen;
+ set_charset(cs);
localtime_r(&query_start,&tm_tmp);
start=&tm_tmp;
value=((longlong) ((ulong) ((uint) start->tm_year+1900)*10000L+
@@ -496,13 +539,14 @@ void Item_func_now::fix_length_and_dec()
(longlong) ((ulong) ((uint) start->tm_hour)*10000L+
(ulong) (((uint) start->tm_min)*100L+
(uint) start->tm_sec)));
- buff_length= (uint) my_sprintf(buff, (buff,"%04d-%02d-%02d %02d:%02d:%02d",
+
+ buff_length= (uint) cs->snprintf(cs,buff, sizeof(buff),"%04d-%02d-%02d %02d:%02d:%02d",
((int) (start->tm_year+1900)) % 10000,
(int) start->tm_mon+1,
(int) start->tm_mday,
(int) start->tm_hour,
(int) start->tm_min,
- (int) start->tm_sec));
+ (int) start->tm_sec);
/* For getdate */
ltime.year= start->tm_year+1900;
ltime.month= start->tm_mon+1;
@@ -533,7 +577,7 @@ int Item_func_now::save_in_field(Field *to)
String *Item_func_sec_to_time::val_str(String *str)
{
- char buff[23];
+ char buff[23*2];
const char *sign="";
longlong seconds=(longlong) args[0]->val_int();
ulong length;
@@ -547,7 +591,7 @@ String *Item_func_sec_to_time::val_str(String *str)
uint sec= (uint) ((ulonglong) seconds % 3600);
length= my_sprintf(buff,(buff,"%s%02lu:%02u:%02u",sign,(long) (seconds/3600),
sec/60, sec % 60));
- str->copy(buff, length, my_charset_latin1);
+ str->copy(buff, length, my_charset_latin1, thd_charset());
return str;
}
@@ -891,20 +935,26 @@ String *Item_func_from_unixtime::val_str(String *str)
{
struct tm tm_tmp,*start;
time_t tmp=(time_t) args[0]->val_int();
+ uint32 l;
+ CHARSET_INFO *cs=thd_charset();
+
if ((null_value=args[0]->null_value))
return 0;
localtime_r(&tmp,&tm_tmp);
start=&tm_tmp;
- if (str->alloc(20))
+
+ l=20*cs->mbmaxlen+32;
+ if (str->alloc(l))
return str; /* purecov: inspected */
- sprintf((char*) str->ptr(),"%04d-%02d-%02d %02d:%02d:%02d",
+ l=cs->snprintf(cs,(char*) str->ptr(),l,"%04d-%02d-%02d %02d:%02d:%02d",
(int) start->tm_year+1900,
(int) start->tm_mon+1,
(int) start->tm_mday,
(int) start->tm_hour,
(int) start->tm_min,
(int) start->tm_sec);
- str->length(19);
+ str->length(l);
+ str->set_charset(cs);
return str;
}
@@ -1035,26 +1085,31 @@ bool Item_date_add_interval::get_date(TIME *ltime, bool fuzzy_date)
String *Item_date_add_interval::val_str(String *str)
{
TIME ltime;
+ CHARSET_INFO *cs=thd_charset();
+ uint32 l;
if (Item_date_add_interval::get_date(&ltime,0))
return 0;
if (ltime.time_type == TIMESTAMP_DATE)
{
- if (str->alloc(11))
+ l=11*cs->mbmaxlen+32;
+ if (str->alloc(l))
goto null_date;
- sprintf((char*) str->ptr(),"%04d-%02d-%02d",
+ l=cs->snprintf(cs,(char*) str->ptr(),l,"%04d-%02d-%02d",
ltime.year,ltime.month,ltime.day);
- str->length(10);
+ str->length(l);
}
else
{
- if (str->alloc(20))
+ l=20*cs->mbmaxlen+32;
+ if (str->alloc(l))
goto null_date;
- sprintf((char*) str->ptr(),"%04d-%02d-%02d %02d:%02d:%02d",
+ l=cs->snprintf(cs,(char*) str->ptr(),l,"%04d-%02d-%02d %02d:%02d:%02d",
ltime.year,ltime.month,ltime.day,
ltime.hour,ltime.minute,ltime.second);
- str->length(19);
+ str->length(l);
}
+ str->set_charset(cs);
return str;
null_date:
diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h
index de2860d24ef..07cdfde115b 100644
--- a/sql/item_timefunc.h
+++ b/sql/item_timefunc.h
@@ -27,7 +27,10 @@ public:
Item_func_period_add(Item *a,Item *b) :Item_int_func(a,b) {}
longlong val_int();
const char *func_name() const { return "period_add"; }
- void fix_length_and_dec() { max_length=6; }
+ void fix_length_and_dec()
+ {
+ max_length=6*thd_charset()->mbmaxlen;
+ }
};
@@ -37,7 +40,11 @@ public:
Item_func_period_diff(Item *a,Item *b) :Item_int_func(a,b) {}
longlong val_int();
const char *func_name() const { return "period_diff"; }
- void fix_length_and_dec() { decimals=0; max_length=6; }
+ void fix_length_and_dec()
+ {
+ decimals=0;
+ max_length=6*thd_charset()->mbmaxlen;
+ }
};
@@ -47,7 +54,12 @@ public:
Item_func_to_days(Item *a) :Item_int_func(a) {}
longlong val_int();
const char *func_name() const { return "to_days"; }
- void fix_length_and_dec() { decimals=0; max_length=6; maybe_null=1; }
+ void fix_length_and_dec()
+ {
+ decimals=0;
+ max_length=6*thd_charset()->mbmaxlen;
+ maybe_null=1;
+ }
};
@@ -57,7 +69,12 @@ public:
Item_func_dayofmonth(Item *a) :Item_int_func(a) {}
longlong val_int();
const char *func_name() const { return "dayofmonth"; }
- void fix_length_and_dec() { decimals=0; max_length=2; maybe_null=1; }
+ void fix_length_and_dec()
+ {
+ decimals=0;
+ max_length=2*thd_charset()->mbmaxlen;
+ maybe_null=1;
+ }
};
@@ -74,7 +91,13 @@ public:
}
const char *func_name() const { return "month"; }
enum Item_result result_type () const { return INT_RESULT; }
- void fix_length_and_dec() { decimals=0; max_length=2; maybe_null=1; }
+ void fix_length_and_dec()
+ {
+ set_charset(thd_charset());
+ decimals=0;
+ max_length=2*thd_charset()->mbmaxlen;
+ maybe_null=1;
+ }
};
@@ -85,7 +108,13 @@ public:
const char *func_name() const { return "monthname"; }
String *val_str(String *str);
enum Item_result result_type () const { return STRING_RESULT; }
- void fix_length_and_dec() { decimals=0; max_length=10; maybe_null=1; }
+ void fix_length_and_dec()
+ {
+ set_charset(thd_charset());
+ decimals=0;
+ max_length=10*thd_charset()->mbmaxlen;
+ maybe_null=1;
+ }
};
@@ -95,7 +124,12 @@ public:
Item_func_dayofyear(Item *a) :Item_int_func(a) {}
longlong val_int();
const char *func_name() const { return "dayofyear"; }
- void fix_length_and_dec() { decimals=0; max_length=3; maybe_null=1; }
+ void fix_length_and_dec()
+ {
+ decimals=0;
+ max_length=3*thd_charset()->mbmaxlen;
+ maybe_null=1;
+ }
};
@@ -105,7 +139,12 @@ public:
Item_func_hour(Item *a) :Item_int_func(a) {}
longlong val_int();
const char *func_name() const { return "hour"; }
- void fix_length_and_dec() { decimals=0; max_length=2; maybe_null=1; }
+ void fix_length_and_dec()
+ {
+ decimals=0;
+ max_length=2*thd_charset()->mbmaxlen;
+ maybe_null=1;
+ }
};
@@ -115,7 +154,12 @@ public:
Item_func_minute(Item *a) :Item_int_func(a) {}
longlong val_int();
const char *func_name() const { return "minute"; }
- void fix_length_and_dec() { decimals=0; max_length=2; maybe_null=1; }
+ void fix_length_and_dec()
+ {
+ decimals=0;
+ max_length=2*thd_charset()->mbmaxlen;
+ maybe_null=1;
+ }
};
@@ -125,7 +169,12 @@ public:
Item_func_quarter(Item *a) :Item_int_func(a) {}
longlong val_int();
const char *func_name() const { return "quarter"; }
- void fix_length_and_dec() { decimals=0; max_length=1; maybe_null=1; }
+ void fix_length_and_dec()
+ {
+ decimals=0;
+ max_length=1*thd_charset()->mbmaxlen;
+ maybe_null=1;
+ }
};
@@ -135,7 +184,12 @@ public:
Item_func_second(Item *a) :Item_int_func(a) {}
longlong val_int();
const char *func_name() const { return "second"; }
- void fix_length_and_dec() { decimals=0; max_length=2; maybe_null=1; }
+ void fix_length_and_dec()
+ {
+ decimals=0;
+ max_length=2*thd_charset()->mbmaxlen;
+ maybe_null=1;
+ }
};
@@ -145,7 +199,12 @@ public:
Item_func_week(Item *a,Item *b) :Item_int_func(a,b) {}
longlong val_int();
const char *func_name() const { return "week"; }
- void fix_length_and_dec() { decimals=0; max_length=2; maybe_null=1; }
+ void fix_length_and_dec()
+ {
+ decimals=0;
+ max_length=2*thd_charset()->mbmaxlen;
+ maybe_null=1;
+ }
};
class Item_func_yearweek :public Item_int_func
@@ -154,7 +213,12 @@ public:
Item_func_yearweek(Item *a,Item *b) :Item_int_func(a,b) {}
longlong val_int();
const char *func_name() const { return "yearweek"; }
- void fix_length_and_dec() { decimals=0; max_length=6; maybe_null=1; }
+ void fix_length_and_dec()
+ {
+ decimals=0;
+ max_length=6*thd_charset()->mbmaxlen;
+ maybe_null=1;
+ }
};
@@ -164,7 +228,12 @@ public:
Item_func_year(Item *a) :Item_int_func(a) {}
longlong val_int();
const char *func_name() const { return "year"; }
- void fix_length_and_dec() { decimals=0; max_length=4; maybe_null=1; }
+ void fix_length_and_dec()
+ {
+ decimals=0;
+ max_length=4*thd_charset()->mbmaxlen;
+ maybe_null=1;
+ }
};
@@ -176,13 +245,20 @@ public:
:Item_func(a), odbc_type(type_arg) {}
longlong val_int();
double val() { return (double) val_int(); }
- String *val_str(String *str) {
+ String *val_str(String *str)
+ {
str->set(val_int(), thd_charset());
return null_value ? 0 : str;
}
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; }
+ void fix_length_and_dec()
+ {
+ set_charset(thd_charset());
+ decimals=0;
+ max_length=1*thd_charset()->mbmaxlen;
+ maybe_null=1;
+ }
};
class Item_func_dayname :public Item_func_weekday
@@ -192,7 +268,13 @@ class Item_func_dayname :public Item_func_weekday
const char *func_name() const { return "dayname"; }
String *val_str(String *str);
enum Item_result result_type () const { return STRING_RESULT; }
- void fix_length_and_dec() { decimals=0; max_length=9; maybe_null=1; }
+ void fix_length_and_dec()
+ {
+ set_charset(thd_charset());
+ decimals=0;
+ max_length=9*thd_charset()->mbmaxlen;
+ maybe_null=1;
+ }
};
@@ -206,7 +288,8 @@ public:
const char *func_name() const { return "timestamp"; }
void fix_length_and_dec()
{
- decimals=0; max_length=10;
+ decimals=0;
+ max_length=10*thd_charset()->mbmaxlen;
}
};
@@ -219,7 +302,8 @@ public:
const char *func_name() const { return "time_to_sec"; }
void fix_length_and_dec()
{
- decimals=0; max_length=10;
+ decimals=0;
+ max_length=10*thd_charset()->mbmaxlen;
}
};
@@ -235,7 +319,12 @@ public:
String *val_str(String *str);
double val() { return (double) val_int(); }
const char *func_name() const { return "date"; }
- void fix_length_and_dec() { decimals=0; max_length=10; }
+ void fix_length_and_dec()
+ {
+ set_charset(thd_charset());
+ decimals=0;
+ max_length=10*thd_charset()->mbmaxlen;
+ }
int save_in_field(Field *to);
void make_field(Send_field *tmp_field)
{
@@ -269,7 +358,7 @@ public:
class Item_func_curtime :public Item_func
{
longlong value;
- char buff[9];
+ char buff[9*2+32];
uint buff_length;
public:
Item_func_curtime() :Item_func() {}
@@ -277,8 +366,7 @@ public:
enum Item_result result_type () const { return STRING_RESULT; }
double val() { return (double) value; }
longlong val_int() { return value; }
- String *val_str(String *str)
- { str_value.set(buff,buff_length,default_charset_info); return &str_value; }
+ String *val_str(String *str);
const char *func_name() const { return "curtime"; }
void fix_length_and_dec();
void make_field(Send_field *tmp_field)
@@ -309,7 +397,7 @@ public:
class Item_func_now :public Item_date_func
{
longlong value;
- char buff[20];
+ char buff[20*2+32]; // +32 to make my_snprintf_{8bit|ucs2} happy
uint buff_length;
TIME ltime;
public:
@@ -319,8 +407,7 @@ public:
double val() { return (double) value; }
longlong val_int() { return value; }
int save_in_field(Field *to);
- String *val_str(String *str)
- { str_value.set(buff,buff_length,default_charset_info); return &str_value; }
+ String *val_str(String *str);
const char *func_name() const { return "now"; }
void fix_length_and_dec();
bool get_date(TIME *res,bool fuzzy_date);
@@ -359,7 +446,12 @@ class Item_func_from_unixtime :public Item_date_func
longlong val_int();
String *val_str(String *str);
const char *func_name() const { return "from_unixtime"; }
- void fix_length_and_dec() { decimals=0; max_length=19; }
+ void fix_length_and_dec()
+ {
+ set_charset(thd_charset());
+ decimals=0;
+ max_length=19*thd_charset()->mbmaxlen;
+ }
// enum Item_result result_type () const { return STRING_RESULT; }
bool get_date(TIME *res,bool fuzzy_date);
};
@@ -372,7 +464,12 @@ public:
double val() { return (double) Item_func_sec_to_time::val_int(); }
longlong val_int();
String *val_str(String *);
- void fix_length_and_dec() { maybe_null=1; max_length=13; }
+ void fix_length_and_dec()
+ {
+ set_charset(thd_charset());
+ maybe_null=1;
+ max_length=13*thd_charset()->mbmaxlen;
+ }
const char *func_name() const { return "sec_to_time"; }
void make_field(Send_field *tmp_field)
{
@@ -404,7 +501,13 @@ public:
:Item_date_func(a,b),int_type(type_arg), date_sub_interval(neg_arg) {}
String *val_str(String *);
const char *func_name() const { return "date_add_interval"; }
- void fix_length_and_dec() { maybe_null=1; max_length=19; value.alloc(32);}
+ void fix_length_and_dec()
+ {
+ set_charset(thd_charset());
+ maybe_null=1;
+ max_length=19*thd_charset()->mbmaxlen;
+ value.alloc(32);
+ }
double val() { return (double) val_int(); }
longlong val_int();
bool get_date(TIME *res,bool fuzzy_date);
diff --git a/sql/lex.h b/sql/lex.h
index 0cbbf7cc1de..35a2decfc03 100644
--- a/sql/lex.h
+++ b/sql/lex.h
@@ -76,6 +76,7 @@ static SYMBOL symbols[] = {
{ "BOTH", SYM(BOTH),0,0},
{ "BTREE", SYM(BTREE_SYM),0,0},
{ "BY", SYM(BY),0,0},
+ { "BYTE", SYM(BYTE_SYM), 0, 0},
{ "CACHE", SYM(CACHE_SYM),0,0},
{ "CASCADE", SYM(CASCADE),0,0},
{ "CASE", SYM(CASE_SYM),0,0},
@@ -126,8 +127,10 @@ static SYMBOL symbols[] = {
{ "DISABLE", SYM(DISABLE_SYM),0,0},
{ "DISTINCT", SYM(DISTINCT),0,0},
{ "DISTINCTROW", SYM(DISTINCT),0,0}, /* Access likes this */
+ { "DIV", SYM(DIV_SYM),0,0},
{ "DO", SYM(DO_SYM),0,0},
{ "DOUBLE", SYM(DOUBLE_SYM),0,0},
+ { "DUAL", SYM(DUAL_SYM),0,0},
{ "DROP", SYM(DROP),0,0},
{ "DUMPFILE", SYM(DUMPFILE),0,0},
{ "DYNAMIC", SYM(DYNAMIC_SYM),0,0},
@@ -153,6 +156,7 @@ static SYMBOL symbols[] = {
{ "FLOAT4", SYM(FLOAT_SYM),0,0},
{ "FLOAT8", SYM(DOUBLE_SYM),0,0},
{ "FLUSH", SYM(FLUSH_SYM),0,0},
+ { "FALSE", SYM(FALSE_SYM),0,0},
{ "FOREIGN", SYM(FOREIGN),0,0},
{ "RAID_TYPE", SYM(RAID_TYPE),0,0},
{ "RAID_CHUNKS", SYM(RAID_CHUNKS),0,0},
@@ -247,6 +251,7 @@ static SYMBOL symbols[] = {
{ "MIN_ROWS", SYM(MIN_ROWS),0,0},
{ "MINUTE", SYM(MINUTE_SYM),0,0},
{ "MINUTE_SECOND", SYM(MINUTE_SECOND_SYM),0,0},
+ { "MOD", SYM(MOD_SYM),0,0},
{ "MODE", SYM(MODE_SYM),0,0},
{ "MODIFY", SYM(MODIFY_SYM),0,0},
{ "MONTH", SYM(MONTH_SYM),0,0},
@@ -262,6 +267,7 @@ static SYMBOL symbols[] = {
{ "NOT", SYM(NOT),0,0},
{ "NULL", SYM(NULL_SYM),0,0},
{ "NUMERIC", SYM(NUMERIC_SYM),0,0},
+ { "OFFSET", SYM(OFFSET_SYM),0,0},
{ "ON", SYM(ON),0,0},
{ "OPEN", SYM(OPEN_SYM),0,0},
{ "OPTIMIZE", SYM(OPTIMIZE),0,0},
@@ -313,6 +319,7 @@ static SYMBOL symbols[] = {
{ "RTREE", SYM(RTREE_SYM),0,0},
{ "SECOND", SYM(SECOND_SYM),0,0},
{ "SELECT", SYM(SELECT_SYM),0,0},
+ { "SERIAL", SYM(SERIAL_SYM),0,0},
{ "SERIALIZABLE", SYM(SERIALIZABLE_SYM),0,0},
{ "SESSION", SYM(SESSION_SYM),0,0},
{ "SET", SYM(SET),0,0},
@@ -356,6 +363,7 @@ static SYMBOL symbols[] = {
{ "TRAILING", SYM(TRAILING),0,0},
{ "TRANSACTION", SYM(TRANSACTION_SYM),0,0},
{ "TRUNCATE", SYM(TRUNCATE_SYM),0,0},
+ { "TRUE", SYM(TRUE_SYM),0,0},
{ "TO", SYM(TO_SYM),0,0},
{ "TYPE", SYM(TYPE_SYM),0,0},
{ "TYPES", SYM(TYPES_SYM),0,0},
@@ -369,8 +377,10 @@ static SYMBOL symbols[] = {
{ "USING", SYM(USING),0,0},
{ "UPDATE", SYM(UPDATE_SYM),0,0},
{ "USAGE", SYM(USAGE),0,0},
+ { "VALUE", SYM(VALUE_SYM),0,0},
{ "VALUES", SYM(VALUES),0,0},
{ "VARCHAR", SYM(VARCHAR),0,0},
+ { "VARCHARACTER", SYM(VARCHAR),0,0},
{ "VARIABLES", SYM(VARIABLES),0,0},
{ "VARYING", SYM(VARYING),0,0},
{ "VARBINARY", SYM(VARBINARY),0,0},
@@ -499,7 +509,6 @@ static SYMBOL sql_functions[] = {
{ "MD5", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_md5)},
{ "MID", SYM(SUBSTRING),0,0}, /* unireg function */
{ "MIN", SYM(MIN_SYM),0,0},
- { "MOD", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_mod)},
{ "MLINEFROMTEXT", SYM(MLINEFROMTEXT),0,0},
{ "MPOINTFROMTEXT", SYM(MPOINTFROMTEXT),0,0},
{ "MPOLYFROMTEXT", SYM(MPOLYFROMTEXT),0,0},
diff --git a/sql/lock.cc b/sql/lock.cc
index 3b2444c8e9d..74d1109b203 100644
--- a/sql/lock.cc
+++ b/sql/lock.cc
@@ -80,7 +80,7 @@ extern HASH open_cache;
static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table,uint count,
bool unlock, TABLE **write_locked);
-static int lock_external(TABLE **table,uint count);
+static int lock_external(THD *thd, TABLE **table,uint count);
static int unlock_external(THD *thd, TABLE **table,uint count);
static void print_lock_error(int error);
@@ -116,14 +116,14 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd,TABLE **tables,uint count)
}
thd->proc_info="System lock";
- if (lock_external(tables,count))
+ if (lock_external(thd, tables, count))
{
my_free((gptr) sql_lock,MYF(0));
sql_lock=0;
thd->proc_info=0;
break;
}
- thd->proc_info=0;
+ thd->proc_info="Table lock";
thd->locked=1;
if (thr_multi_lock(sql_lock->locks,sql_lock->lock_count))
{
@@ -142,6 +142,7 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd,TABLE **tables,uint count)
thd->locked=0;
break;
}
+ thd->proc_info=0;
/* some table was altered or deleted. reopen tables marked deleted */
mysql_unlock_tables(thd,sql_lock);
@@ -151,6 +152,7 @@ retry:
if (wait_for_tables(thd))
break; // Couldn't open tables
}
+ thd->proc_info=0;
if (thd->killed)
{
my_error(ER_SERVER_SHUTDOWN,MYF(0));
@@ -166,15 +168,15 @@ retry:
}
-static int lock_external(TABLE **tables,uint count)
+static int lock_external(THD *thd, TABLE **tables, uint count)
{
reg1 uint i;
int lock_type,error;
- THD *thd=current_thd;
DBUG_ENTER("lock_external");
for (i=1 ; i <= count ; i++, tables++)
{
+ DBUG_ASSERT((*tables)->reginfo.lock_type >= TL_READ);
lock_type=F_WRLCK; /* Lock exclusive */
if ((*tables)->db_stat & HA_READ_ONLY ||
((*tables)->reginfo.lock_type >= TL_READ &&
diff --git a/sql/log.cc b/sql/log.cc
index 286dba3f79b..0e1af8e5dae 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -1026,9 +1026,13 @@ bool MYSQL_LOG::write(THD *thd,enum enum_server_command command,
bool MYSQL_LOG::write(Log_event* event_info)
{
bool error=0;
+ DBUG_ENTER("MYSQL_LOG::write(event)");
if (!inited) // Can't use mutex if not init
- return 0;
+ {
+ DBUG_PRINT("error",("not initied"));
+ DBUG_RETURN(0);
+ }
pthread_mutex_lock(&LOCK_log);
/* In most cases this is only called if 'is_open()' is true */
@@ -1036,7 +1040,7 @@ bool MYSQL_LOG::write(Log_event* event_info)
{
bool should_rotate = 0;
THD *thd=event_info->thd;
- const char* db = event_info->get_db();
+ const char *local_db = event_info->get_db();
#ifdef USING_TRANSACTIONS
IO_CACHE *file = ((event_info->get_cache_stmt()) ?
&thd->transaction.trans_log :
@@ -1046,10 +1050,11 @@ bool MYSQL_LOG::write(Log_event* event_info)
#endif
if ((thd && !(thd->options & OPTION_BIN_LOG) &&
(thd->master_access & SUPER_ACL)) ||
- (db && !db_ok(db, binlog_do_db, binlog_ignore_db)))
+ (local_db && !db_ok(local_db, binlog_do_db, binlog_ignore_db)))
{
VOID(pthread_mutex_unlock(&LOCK_log));
- return 0;
+ DBUG_PRINT("error",("!db_ok"));
+ DBUG_RETURN(0);
}
error=1;
@@ -1087,7 +1092,7 @@ bool MYSQL_LOG::write(Log_event* event_info)
char buf[1024] = "SET CHARACTER SET ";
char* p = strend(buf);
p = strmov(p, thd->variables.convert_set->name);
- Query_log_event e(thd, buf, (ulong)(p - buf));
+ Query_log_event e(thd, buf, (ulong)(p - buf), 0);
e.set_log_pos(this);
if (e.write(file))
goto err;
@@ -1135,7 +1140,7 @@ err:
}
pthread_mutex_unlock(&LOCK_log);
- return error;
+ DBUG_RETURN(error);
}
@@ -1165,6 +1170,7 @@ uint MYSQL_LOG::next_file_id()
bool MYSQL_LOG::write(THD *thd, IO_CACHE *cache)
{
VOID(pthread_mutex_lock(&LOCK_log));
+ DBUG_ENTER("MYSQL_LOG::write(cache");
if (is_open()) // Should always be true
{
@@ -1223,7 +1229,7 @@ bool MYSQL_LOG::write(THD *thd, IO_CACHE *cache)
signal_update();
}
VOID(pthread_mutex_unlock(&LOCK_log));
- return 0;
+ DBUG_RETURN(0);
err:
if (!write_error)
@@ -1232,7 +1238,7 @@ err:
sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno);
}
VOID(pthread_mutex_unlock(&LOCK_log));
- return 1;
+ DBUG_RETURN(1);
}
@@ -1242,7 +1248,7 @@ err:
*/
bool MYSQL_LOG::write(THD *thd,const char *query, uint query_length,
- time_t query_start)
+ time_t query_start_arg)
{
bool error=0;
if (is_open())
@@ -1260,7 +1266,7 @@ bool MYSQL_LOG::write(THD *thd,const char *query, uint query_length,
VOID(pthread_mutex_unlock(&LOCK_log));
return 0;
}
- if ((specialflag & SPECIAL_LONG_LOG_FORMAT) || query_start)
+ if ((specialflag & SPECIAL_LONG_LOG_FORMAT) || query_start_arg)
{
current_time=time(NULL);
if (current_time != last_time)
@@ -1288,13 +1294,13 @@ bool MYSQL_LOG::write(THD *thd,const char *query, uint query_length,
thd->ip ? thd->ip : "") == (uint) -1)
tmp_errno=errno;
}
- if (query_start)
+ if (query_start_arg)
{
/* For slow query log */
if (my_b_printf(&log_file,
"# Query_time: %lu Lock_time: %lu Rows_sent: %lu Rows_examined: %lu\n",
- (ulong) (current_time - query_start),
- (ulong) (thd->time_after_lock - query_start),
+ (ulong) (current_time - query_start_arg),
+ (ulong) (thd->time_after_lock - query_start_arg),
(ulong) thd->sent_row_count,
(ulong) thd->examined_row_count) == (uint) -1)
tmp_errno=errno;
@@ -1321,11 +1327,11 @@ bool MYSQL_LOG::write(THD *thd,const char *query, uint query_length,
}
if (thd->query_start_used)
{
- if (query_start != thd->query_start())
+ if (query_start_arg != thd->query_start())
{
- query_start=thd->query_start();
+ query_start_arg=thd->query_start();
end=strmov(end,",timestamp=");
- end=int10_to_str((long) query_start,end,10);
+ end=int10_to_str((long) query_start_arg,end,10);
}
}
if (end != buff)
diff --git a/sql/log_event.cc b/sql/log_event.cc
index c168c951c8f..d9ee832f7d3 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -235,22 +235,25 @@ const char* Log_event::get_type_str()
****************************************************************************/
#ifndef MYSQL_CLIENT
-Log_event::Log_event(THD* thd_arg, uint16 flags_arg)
- :exec_time(0), flags(flags_arg), cached_event_len(0),
- temp_buf(0), thd(thd_arg)
+Log_event::Log_event(THD* thd_arg, uint16 flags_arg, bool using_trans)
+ :temp_buf(0), exec_time(0), cached_event_len(0), flags(flags_arg),
+ thd(thd_arg)
{
- if (thd)
- {
- server_id = thd->server_id;
- when = thd->start_time;
- log_pos = thd->log_pos;
- }
- else
- {
- server_id = ::server_id;
- when = time(NULL);
- log_pos =0;
- }
+ server_id= thd->server_id;
+ when= thd->start_time;
+ log_pos= thd->log_pos;
+ cache_stmt= (using_trans &&
+ (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)));
+}
+
+
+Log_event::Log_event()
+ :temp_buf(0), exec_time(0), cached_event_len(0), flags(0), cache_stmt(0),
+ thd(0)
+{
+ server_id= ::server_id;
+ when= time(NULL);
+ log_pos= 0;
}
#endif // !MYSQL_CLIENT
@@ -260,7 +263,7 @@ Log_event::Log_event(THD* thd_arg, uint16 flags_arg)
****************************************************************************/
Log_event::Log_event(const char* buf, bool old_format)
- :cached_event_len(0), temp_buf(0)
+ :temp_buf(0), cached_event_len(0), cache_stmt(0)
{
when = uint4korr(buf);
server_id = uint4korr(buf + SERVER_ID_OFFSET);
@@ -330,11 +333,11 @@ void Log_event::init_show_field_list(List<Item>* field_list)
Only called by SHOW BINLOG EVENTS
****************************************************************************/
-int Log_event::net_send(THD* thd, const char* log_name, my_off_t pos)
+int Log_event::net_send(THD* thd_arg, const char* log_name, my_off_t pos)
{
- String* packet = &thd->packet;
- const char* p = strrchr(log_name, FN_LIBCHAR);
- const char* event_type;
+ String* packet = &thd_arg->packet;
+ const char *p= strrchr(log_name, FN_LIBCHAR);
+ const char *event_type;
if (p)
log_name = p + 1;
@@ -346,7 +349,7 @@ int Log_event::net_send(THD* thd, const char* log_name, my_off_t pos)
net_store_data(packet, server_id);
net_store_data(packet, (longlong) log_pos);
pack_info(packet);
- return my_net_write(&thd->net, (char*) packet->ptr(), packet->length());
+ return my_net_write(&thd_arg->net, (char*) packet->ptr(), packet->length());
}
#endif // !MYSQL_CLIENT
@@ -725,12 +728,10 @@ int Query_log_event::write_data(IO_CACHE* file)
#ifndef MYSQL_CLIENT
Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg,
ulong query_length, bool using_trans)
- :Log_event(thd_arg), data_buf(0), query(query_arg), db(thd_arg->db),
- q_len((uint32) query_length),
+ :Log_event(thd_arg, 0, using_trans), data_buf(0), query(query_arg),
+ db(thd_arg->db), q_len((uint32) query_length),
error_code(thd_arg->killed ? ER_SERVER_SHUTDOWN: thd_arg->net.last_errno),
- thread_id(thd_arg->thread_id),
- cache_stmt(using_trans &&
- (thd_arg->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))
+ thread_id(thd_arg->thread_id)
{
time_t end_time;
time(&end_time);
@@ -1155,18 +1156,19 @@ int Load_log_event::write_data_body(IO_CACHE* file)
****************************************************************************/
#ifndef MYSQL_CLIENT
-Load_log_event::Load_log_event(THD* thd, sql_exchange* ex,
- const char* db_arg, const char* table_name_arg,
- List<Item>& fields_arg,
- 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)
+Load_log_event::Load_log_event(THD *thd_arg, sql_exchange *ex,
+ const char *db_arg, const char *table_name_arg,
+ List<Item> &fields_arg,
+ enum enum_duplicates handle_dup,
+ bool using_trans)
+ :Log_event(thd_arg, 0, using_trans), thread_id(thd_arg->thread_id),
+ num_fields(0), fields(0), field_lens(0),field_block_len(0),
+ table_name(table_name_arg ? table_name_arg : ""),
+ db(db_arg), fname(ex->file_name)
{
time_t end_time;
time(&end_time);
- exec_time = (ulong) (end_time - thd->start_time);
+ exec_time = (ulong) (end_time - thd_arg->start_time);
/* db can never be a zero pointer in 4.0 */
db_len = (uint32) strlen(db);
table_name_len = (uint32) strlen(table_name);
@@ -1236,11 +1238,11 @@ Load_log_event::Load_log_event(THD* thd, sql_exchange* ex,
constructed event.
****************************************************************************/
-Load_log_event::Load_log_event(const char* buf, int event_len,
- bool old_format):
- Log_event(buf, old_format),num_fields(0),fields(0),
- field_lens(0),field_block_len(0),
- table_name(0),db(0),fname(0)
+Load_log_event::Load_log_event(const char *buf, int event_len,
+ bool old_format)
+ :Log_event(buf, old_format),num_fields(0),fields(0),
+ field_lens(0),field_block_len(0),
+ table_name(0),db(0),fname(0)
{
if (!event_len) // derived class, will call copy_log_event() itself
return;
@@ -1390,14 +1392,14 @@ void Load_log_event::print(FILE* file, bool short_form, char* last_db)
****************************************************************************/
#ifndef MYSQL_CLIENT
-void Load_log_event::set_fields(List<Item> &fields)
+void Load_log_event::set_fields(List<Item> &field_list)
{
uint i;
- const char* field = this->fields;
- for (i = 0; i < num_fields; i++)
+ const char* field = fields;
+ for (i= 0; i < num_fields; i++)
{
- fields.push_back(new Item_field(db, table_name, field));
- field += field_lens[i] + 1;
+ field_list.push_back(new Item_field(db, table_name, field));
+ field+= field_lens[i] + 1;
}
}
#endif // !MYSQL_CLIENT
@@ -1458,8 +1460,8 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli)
ex.field_term->length(0);
ex.skip_lines = skip_lines;
- List<Item> fields;
- set_fields(fields);
+ List<Item> field_list;
+ set_fields(field_list);
thd->slave_proxy_id = thd->thread_id;
if (net)
{
@@ -1470,7 +1472,7 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli)
*/
thd->net.pkt_nr = net->pkt_nr;
}
- if (mysql_load(thd, &ex, &tables, fields, handle_dup, net != 0,
+ if (mysql_load(thd, &ex, &tables, field_list, handle_dup, net != 0,
TL_WRITE))
thd->query_error = 1;
if (thd->cuted_fields)
@@ -1795,14 +1797,12 @@ int Intvar_log_event::exec_event(struct st_relay_log_info* rli)
#ifndef MYSQL_CLIENT
void Rand_log_event::pack_info(String* packet)
{
- char buf1[256], buf[22];
- String tmp(buf1, sizeof(buf1), system_charset_info);
- tmp.length(0);
- tmp.append("randseed1=");
- tmp.append(llstr(seed1, buf));
- tmp.append(",randseed2=");
- tmp.append(llstr(seed2, buf));
- net_store_data(packet, tmp.ptr(), tmp.length());
+ char buf1[256], *pos;
+ pos= strmov(buf1,"rand_seed1=");
+ pos= int10_to_str((long) seed1, pos, 10);
+ pos= strmov(pos, ",rand_seed2=");
+ pos= int10_to_str((long) seed2, pos, 10);
+ net_store_data(packet, buf1, (uint) (pos-buf1));
}
#endif // !MYSQL_CLIENT
@@ -1846,8 +1846,8 @@ void Rand_log_event::print(FILE* file, bool short_form, char* last_db)
print_header(file);
fprintf(file, "\tRand\n");
}
- fprintf(file, "SET RAND SEED1=%s;\n", llstr(seed1, llbuff));
- fprintf(file, "SET RAND SEED2=%s;\n", llstr(seed2, llbuff));
+ fprintf(file, "SET @@RAND_SEED1=%s, @@RAND_SEED2=%s;\n",
+ llstr(seed1, llbuff),llstr(seed2, llbuff));
fflush(file);
}
#endif // MYSQL_CLIENT
@@ -1860,8 +1860,8 @@ void Rand_log_event::print(FILE* file, bool short_form, char* last_db)
#ifndef MYSQL_CLIENT
int Rand_log_event::exec_event(struct st_relay_log_info* rli)
{
- thd->rand.seed1 = seed1;
- thd->rand.seed2 = seed2;
+ thd->rand.seed1= (ulong) seed1;
+ thd->rand.seed2= (ulong) seed2;
rli->inc_pending(get_event_len());
return 0;
}
@@ -1907,8 +1907,8 @@ void Slave_log_event::pack_info(String* packet)
****************************************************************************/
#ifndef MYSQL_CLIENT
Slave_log_event::Slave_log_event(THD* thd_arg,
- struct st_relay_log_info* rli):
- Log_event(thd_arg),mem_pool(0),master_host(0)
+ struct st_relay_log_info* rli)
+ :Log_event(thd_arg, 0, 0), mem_pool(0), master_host(0)
{
DBUG_ENTER("Slave_log_event");
if (!rli->inited) // QQ When can this happen ?
@@ -2120,11 +2120,13 @@ int Stop_log_event::exec_event(struct st_relay_log_info* rli)
****************************************************************************/
#ifndef MYSQL_CLIENT
-Create_file_log_event::Create_file_log_event(THD* thd_arg, sql_exchange* ex,
- const char* db_arg, const char* table_name_arg,
- List<Item>& fields_arg, enum enum_duplicates handle_dup,
- char* block_arg, uint block_len_arg)
- :Load_log_event(thd_arg,ex,db_arg,table_name_arg,fields_arg,handle_dup),
+Create_file_log_event::
+Create_file_log_event(THD* thd_arg, sql_exchange* ex,
+ const char* db_arg, const char* table_name_arg,
+ List<Item>& fields_arg, enum enum_duplicates handle_dup,
+ char* block_arg, uint block_len_arg, bool using_trans)
+ :Load_log_event(thd_arg,ex,db_arg,table_name_arg,fields_arg,handle_dup,
+ using_trans),
fake_base(0),block(block_arg),block_len(block_len_arg),
file_id(thd_arg->file_id = mysql_bin_log.next_file_id())
{
@@ -2327,9 +2329,10 @@ err:
****************************************************************************/
#ifndef MYSQL_CLIENT
Append_block_log_event::Append_block_log_event(THD* thd_arg, char* block_arg,
- uint block_len_arg)
- :Log_event(thd_arg), block(block_arg),block_len(block_len_arg),
- file_id(thd_arg->file_id)
+ uint block_len_arg,
+ bool using_trans)
+ :Log_event(thd_arg,0, using_trans), block(block_arg),
+ block_len(block_len_arg), file_id(thd_arg->file_id)
{
}
#endif // !MYSQL_CLIENT
@@ -2447,8 +2450,8 @@ err:
****************************************************************************/
#ifndef MYSQL_CLIENT
-Delete_file_log_event::Delete_file_log_event(THD* thd_arg)
- :Log_event(thd_arg),file_id(thd_arg->file_id)
+Delete_file_log_event::Delete_file_log_event(THD *thd_arg, bool using_trans)
+ :Log_event(thd_arg, 0, using_trans),file_id(thd_arg->file_id)
{
}
#endif // !MYSQL_CLIENT
@@ -2545,8 +2548,8 @@ int Delete_file_log_event::exec_event(struct st_relay_log_info* rli)
****************************************************************************/
#ifndef MYSQL_CLIENT
-Execute_load_log_event::Execute_load_log_event(THD* thd_arg)
- :Log_event(thd_arg),file_id(thd_arg->file_id)
+Execute_load_log_event::Execute_load_log_event(THD *thd_arg, bool using_trans)
+ :Log_event(thd_arg, 0, using_trans), file_id(thd_arg->file_id)
{
}
#endif // !MYSQL_CLIENT
@@ -2556,8 +2559,8 @@ Execute_load_log_event::Execute_load_log_event(THD* thd_arg)
Execute_load_log_event ctor
****************************************************************************/
-Execute_load_log_event::Execute_load_log_event(const char* buf,int len)
- :Log_event(buf, 0),file_id(0)
+Execute_load_log_event::Execute_load_log_event(const char* buf, int len)
+ :Log_event(buf, 0), file_id(0)
{
if ((uint)len < EXEC_LOAD_EVENT_OVERHEAD)
return;
diff --git a/sql/log_event.h b/sql/log_event.h
index bf04c480729..20a134ab3cc 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -247,18 +247,19 @@ struct st_relay_log_info;
class Log_event
{
public:
+ my_off_t log_pos;
+ char *temp_buf;
time_t when;
ulong exec_time;
uint32 server_id;
- my_off_t log_pos;
+ uint cached_event_len;
uint16 flags;
- int cached_event_len;
- char* temp_buf;
-
+ bool cache_stmt;
#ifndef MYSQL_CLIENT
THD* thd;
- Log_event(THD* thd_arg, uint16 flags_arg = 0);
+ Log_event(THD* thd_arg, uint16 flags_arg, bool cache_stmt);
+ Log_event();
// if mutex is 0, the read will proceed without mutex
static Log_event* read_log_event(IO_CACHE* file,
pthread_mutex_t* log_lock,
@@ -301,7 +302,7 @@ public:
{ return 0; }
virtual Log_event_type get_type_code() = 0;
virtual bool is_valid() = 0;
- virtual bool get_cache_stmt() { return 0; }
+ inline bool get_cache_stmt() { return cache_stmt; }
Log_event(const char* buf, bool old_format);
virtual ~Log_event() { free_temp_buf();}
void register_temp_buf(char* buf) { temp_buf = buf; }
@@ -350,14 +351,12 @@ public:
uint16 error_code;
ulong thread_id;
#ifndef MYSQL_CLIENT
- bool cache_stmt;
Query_log_event(THD* thd_arg, const char* query_arg, ulong query_length,
- bool using_trans=0);
+ bool using_trans);
const char* get_db() { return db; }
void pack_info(String* packet);
int exec_event(struct st_relay_log_info* rli);
- bool get_cache_stmt() { return cache_stmt; }
#else
void print(FILE* file, bool short_form = 0, char* last_db = 0);
#endif
@@ -445,14 +444,15 @@ public:
const char* fname;
uint32 skip_lines;
sql_ex_info sql_ex;
-
+
#ifndef MYSQL_CLIENT
String field_lens_buf;
String fields_buf;
Load_log_event(THD* thd, sql_exchange* ex, const char* db_arg,
const char* table_name_arg,
- List<Item>& fields_arg, enum enum_duplicates handle_dup);
+ List<Item>& fields_arg, enum enum_duplicates handle_dup,
+ bool using_trans);
void set_fields(List<Item> &fields_arg);
void pack_info(String* packet);
const char* get_db() { return db; }
@@ -468,8 +468,10 @@ public:
Load_log_event(const char* buf, int event_len, bool old_format);
~Load_log_event()
{}
- Log_event_type get_type_code() { return sql_ex.new_format() ?
- NEW_LOAD_EVENT: LOAD_EVENT; }
+ Log_event_type get_type_code()
+ {
+ return sql_ex.new_format() ? NEW_LOAD_EVENT: LOAD_EVENT;
+ }
int write_data_header(IO_CACHE* file);
int write_data_body(IO_CACHE* file);
bool is_valid() { return table_name != 0; }
@@ -500,7 +502,7 @@ public:
char server_version[ST_SERVER_VER_LEN];
#ifndef MYSQL_CLIENT
- Start_log_event() :Log_event((THD*)0),binlog_version(BINLOG_VERSION)
+ Start_log_event() :Log_event(), binlog_version(BINLOG_VERSION)
{
created = (uint32) when;
memcpy(server_version, ::server_version, ST_SERVER_VER_LEN);
@@ -538,7 +540,7 @@ public:
#ifndef MYSQL_CLIENT
Intvar_log_event(THD* thd_arg,uchar type_arg, ulonglong val_arg)
- :Log_event(thd_arg),val(val_arg),type(type_arg)
+ :Log_event(),val(val_arg),type(type_arg)
{}
void pack_info(String* packet);
int exec_event(struct st_relay_log_info* rli);
@@ -570,7 +572,7 @@ class Rand_log_event: public Log_event
#ifndef MYSQL_CLIENT
Rand_log_event(THD* thd_arg, ulonglong seed1_arg, ulonglong seed2_arg)
- :Log_event(thd_arg),seed1(seed1_arg),seed2(seed2_arg)
+ :Log_event(thd_arg,0,0),seed1(seed1_arg),seed2(seed2_arg)
{}
void pack_info(String* packet);
int exec_event(struct st_relay_log_info* rli);
@@ -596,7 +598,7 @@ class Stop_log_event: public Log_event
{
public:
#ifndef MYSQL_CLIENT
- Stop_log_event() :Log_event((THD*)0)
+ Stop_log_event() :Log_event()
{}
int exec_event(struct st_relay_log_info* rli);
#else
@@ -628,8 +630,9 @@ public:
bool alloced;
#ifndef MYSQL_CLIENT
Rotate_log_event(THD* thd_arg, const char* new_log_ident_arg,
- uint ident_len_arg = 0,ulonglong pos_arg = 4)
- : Log_event(thd_arg), new_log_ident(new_log_ident_arg),
+ uint ident_len_arg = 0,
+ ulonglong pos_arg = LOG_EVENT_OFFSET)
+ :Log_event(thd_arg,0,0), new_log_ident(new_log_ident_arg),
pos(pos_arg),ident_len(ident_len_arg ? ident_len_arg :
(uint) strlen(new_log_ident_arg)), alloced(0)
{}
@@ -678,7 +681,8 @@ public:
const char* table_name_arg,
List<Item>& fields_arg,
enum enum_duplicates handle_dup,
- char* block_arg, uint block_len_arg);
+ char* block_arg, uint block_len_arg,
+ bool using_trans);
void pack_info(String* packet);
int exec_event(struct st_relay_log_info* rli);
#else
@@ -728,7 +732,7 @@ public:
#ifndef MYSQL_CLIENT
Append_block_log_event(THD* thd, char* block_arg,
- uint block_len_arg);
+ uint block_len_arg, bool using_trans);
int exec_event(struct st_relay_log_info* rli);
void pack_info(String* packet);
#else
@@ -754,7 +758,7 @@ public:
uint file_id;
#ifndef MYSQL_CLIENT
- Delete_file_log_event(THD* thd);
+ Delete_file_log_event(THD* thd, bool using_trans);
void pack_info(String* packet);
int exec_event(struct st_relay_log_info* rli);
#else
@@ -780,7 +784,7 @@ public:
uint file_id;
#ifndef MYSQL_CLIENT
- Execute_load_log_event(THD* thd);
+ Execute_load_log_event(THD* thd, bool using_trans);
void pack_info(String* packet);
int exec_event(struct st_relay_log_info* rli);
#else
diff --git a/sql/mini_client.cc b/sql/mini_client.cc
index 52725f2acc0..7d3b10a34a9 100644
--- a/sql/mini_client.cc
+++ b/sql/mini_client.cc
@@ -297,11 +297,11 @@ static int mc_sock_connect(my_socket s, const struct sockaddr *name,
FD_SET(s, &sfds);
tv.tv_sec = (long) to;
tv.tv_usec = 0;
-#ifdef HPUX
+#ifdef HPUX10
res = select(s+1, NULL, (int*) &sfds, NULL, &tv);
#else
res = select(s+1, NULL, &sfds, NULL, &tv);
-#endif
+#endif /* HPUX10 */
if (res <= 0) /* Never became writable */
return(-1);
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index d41fedf8630..ed95338a7e3 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -86,6 +86,7 @@ char* query_table_status(THD *thd,const char *db,const char *table_name);
*/
#define MIN_FILE_LENGTH_TO_USE_ROW_CACHE (16L*1024*1024)
#define MIN_ROWS_TO_USE_TABLE_CACHE 100
+#define MIN_ROWS_TO_USE_BULK_INSERT 100
/*
The following is used to decide if MySQL should use table scanning
@@ -202,6 +203,11 @@ char* query_table_status(THD *thd,const char *db,const char *table_name);
#define MODE_SERIALIZABLE 16
#define MODE_ONLY_FULL_GROUP_BY 32
#define MODE_NO_UNSIGNED_SUBTRACTION 64
+#define MODE_POSTGRESQL 128
+#define MODE_ORACLE 256
+#define MODE_MSSQL 512
+#define MODE_DB2 1024
+#define MODE_SAPDB 2048
#define RAID_BLOCK_SIZE 1024
@@ -322,9 +328,8 @@ void mysql_init_multi_delete(LEX *lex);
void init_max_user_conn(void);
void init_update_queries(void);
void free_max_user_conn(void);
-pthread_handler_decl(handle_one_connection,arg);
-pthread_handler_decl(handle_bootstrap,arg);
-sig_handler end_thread_signal(int sig);
+extern "C" pthread_handler_decl(handle_one_connection,arg);
+extern "C" pthread_handler_decl(handle_bootstrap,arg);
void end_thread(THD *thd,bool put_in_cache);
void flush_thread_cache();
void mysql_execute_command(THD *thd);
@@ -400,8 +405,7 @@ int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit,
int mysql_explain_select(THD *thd, SELECT_LEX *sl, char const *type,
select_result *result);
int mysql_union(THD *thd, LEX *lex,select_result *result);
-int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *s, TABLE_LIST *t,
- bool tables_is_opened);
+int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *s, TABLE_LIST *t);
Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
Item_result_field ***copy_func, Field **from_field,
bool group,bool modify_item);
@@ -438,14 +442,12 @@ int mysql_drop_index(THD *thd, TABLE_LIST *table_list,
int mysql_update(THD *thd,TABLE_LIST *tables,List<Item> &fields,
List<Item> &values,COND *conds,
ORDER *order, ha_rows limit,
- enum enum_duplicates handle_duplicates,
- thr_lock_type lock_type);
+ enum enum_duplicates handle_duplicates);
int mysql_insert(THD *thd,TABLE_LIST *table,List<Item> &fields,
- List<List_item> &values, enum_duplicates flag,
- thr_lock_type lock_type);
+ List<List_item> &values, enum_duplicates flag);
void kill_delayed_threads(void);
int mysql_delete(THD *thd, TABLE_LIST *table, COND *conds, ORDER *order,
- ha_rows rows, thr_lock_type lock_type, ulong options);
+ ha_rows rows, ulong options);
int mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok=0);
TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type update);
TABLE *open_table(THD *thd,const char *db,const char *table,const char *alias,
@@ -606,7 +608,7 @@ int write_record(TABLE *table,COPY_INFO *info);
extern ulong volatile manager_status;
extern bool volatile manager_thread_in_use, mqh_used;
extern pthread_t manager_thread;
-pthread_handler_decl(handle_manager, arg);
+extern "C" pthread_handler_decl(handle_manager, arg);
/* sql_test.cc */
#ifndef DBUG_OFF
@@ -634,6 +636,8 @@ bool open_log(MYSQL_LOG *log, const char *hostname,
const char *index_file_name,
enum_log_type type, bool read_append = 0,
bool no_auto_events = 0);
+/* mysqld.cc */
+void clear_error_message(THD *thd);
/*
External variables
@@ -759,7 +763,7 @@ bool wait_for_locked_table_names(THD *thd, TABLE_LIST *table_list);
/* old unireg functions */
void unireg_init(ulong options);
-void unireg_end(int signal);
+void unireg_end(void);
int rea_create_table(THD *thd, my_string file_name,HA_CREATE_INFO *create_info,
List<create_field> &create_field,
uint key_count,KEY *key_info);
@@ -788,7 +792,7 @@ timestamp_type str_to_TIME(const char *str, uint length, TIME *l_time,
int test_if_number(char *str,int *res,bool allow_wildcards);
void change_byte(byte *,uint,char,char);
-void unireg_abort(int exit_code);
+extern "C" void unireg_abort(int exit_code);
void init_read_record(READ_RECORD *info, THD *thd, TABLE *reg_form,
SQL_SELECT *select,
int use_record_cache, bool print_errors);
@@ -819,10 +823,6 @@ bool check_column_name(const char *name);
bool check_table_name(const char *name, uint length);
char *get_field(MEM_ROOT *mem,TABLE *table,uint fieldnr);
int wild_case_compare(CHARSET_INFO *cs, const char *str,const char *wildstr);
-int wild_compare(const char *str,const char *str_end,
- const char *wildstr,const char *wildend,char escape);
-int wild_case_compare(CHARSET_INFO *cs, const char *str,const char *str_end,
- const char *wildstr,const char *wildend,char escape);
/* from hostname.cc */
struct in_addr;
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 1112d3e459a..cddae933318 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -179,10 +179,13 @@ static char szPipeName [ 257 ];
static SECURITY_ATTRIBUTES saPipeSecurity;
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 pthread_cond_t COND_handler_count;
+static uint handler_count;
static bool opt_console=0, start_mode=0, use_opt_args;
static int opt_argc;
static char **opt_argv;
@@ -276,7 +279,7 @@ static char* pidfile_name_ptr= pidfile_name;
static pthread_t select_thread;
static my_bool opt_noacl=0, opt_bootstrap=0, opt_myisam_log=0;
my_bool opt_safe_user_create = 0, opt_no_mix_types = 0;
-my_bool opt_safe_show_db=0, lower_case_table_names, opt_old_rpl_compat;
+my_bool lower_case_table_names, opt_old_rpl_compat;
my_bool opt_show_slave_auth_info, opt_sql_bin_update = 0;
my_bool opt_log_slave_updates= 0, opt_old_passwords=0;
@@ -335,13 +338,18 @@ ulong query_cache_limit=0;
Query_cache query_cache;
#endif
+#ifdef HAVE_SMEM
+static char *shared_memory_base_name=default_shared_memory_base_name;
+static bool opt_enable_shared_memory = 0;
+#endif
+
volatile ulong cached_thread_count=0;
// replication parameters, if master_host is not NULL, we are a slave
my_string master_user = (char*) "test", master_password = 0, master_host=0,
master_info_file = (char*) "master.info",
relay_log_info_file = (char*) "relay-log.info",
- master_ssl_key=0, master_ssl_cert=0;
+ master_ssl_key=0, master_ssl_cert=0, master_ssl_capath=0, master_ssl_cipher=0;
my_string report_user = 0, report_password = 0, report_host=0;
const char *localhost=LOCAL_HOST;
@@ -406,8 +414,12 @@ time_t start_time;
ulong opt_sql_mode = 0L;
const char *sql_mode_names[] =
-{ "REAL_AS_FLOAT", "PIPES_AS_CONCAT", "ANSI_QUOTES", "IGNORE_SPACE",
- "SERIALIZE","ONLY_FULL_GROUP_BY", "NO_UNSIGNED_SUBTRACTION",NullS };
+{
+ "REAL_AS_FLOAT", "PIPES_AS_CONCAT", "ANSI_QUOTES", "IGNORE_SPACE",
+ "SERIALIZE", "ONLY_FULL_GROUP_BY", "NO_UNSIGNED_SUBTRACTION",
+ "POSTGRESQL", "ORACLE", "MSSQL", "SAPDB",
+ NullS
+};
TYPELIB sql_mode_typelib= {array_elements(sql_mode_names)-1,"",
sql_mode_names};
@@ -446,20 +458,23 @@ pthread_cond_t eventShutdown;
#endif
static void start_signal_handler(void);
-static void *signal_hand(void *arg);
+extern "C" pthread_handler_decl(signal_hand, arg);
static void set_options(void);
static void get_options(int argc,char **argv);
static char *get_relative_path(const char *path);
static void fix_paths(void);
-static pthread_handler_decl(handle_connections_sockets,arg);
-static pthread_handler_decl(kill_server_thread,arg);
+extern "C" pthread_handler_decl(handle_connections_sockets,arg);
+extern "C" pthread_handler_decl(kill_server_thread,arg);
static int bootstrap(FILE *file);
static void close_server_sock();
static bool read_init_file(char *file_name);
#ifdef __NT__
-static pthread_handler_decl(handle_connections_namedpipes,arg);
+extern "C" pthread_handler_decl(handle_connections_namedpipes,arg);
#endif
-extern pthread_handler_decl(handle_slave,arg);
+#ifdef HAVE_SMEM
+static pthread_handler_decl(handle_connections_shared_memory,arg);
+#endif
+extern "C" pthread_handler_decl(handle_slave,arg);
#ifdef SET_RLIMIT_NOFILE
static uint set_maximum_open_files(uint max_file_limit);
#endif
@@ -766,14 +781,14 @@ static void __cdecl kill_server(int sig_ptr)
if (sig != MYSQL_KILL_SIGNAL && sig != 0)
unireg_abort(1); /* purecov: inspected */
else
- unireg_end(0);
+ unireg_end();
pthread_exit(0); /* purecov: deadcode */
RETURN_FROM_KILL_SERVER;
}
#ifdef USE_ONE_SIGNAL_HAND
-static pthread_handler_decl(kill_server_thread,arg __attribute__((unused)))
+extern "C" pthread_handler_decl(kill_server_thread,arg __attribute__((unused)))
{
SHUTDOWN_THD;
my_thread_init(); // Initialize new thread
@@ -788,7 +803,7 @@ static pthread_handler_decl(kill_server_thread,arg __attribute__((unused)))
#define sigset signal
#endif
-static sig_handler print_signal_warning(int sig)
+extern "C" sig_handler print_signal_warning(int sig)
{
if (!DBUG_IN_USE)
{
@@ -805,16 +820,33 @@ static sig_handler print_signal_warning(int sig)
#endif
}
+/*
+ cleanup all memory and end program nicely
-void unireg_end(int signal_number __attribute__((unused)))
+ SYNOPSIS
+ unireg_end()
+
+ NOTES
+ This function never returns.
+
+ If SIGNALS_DONT_BREAK_READ is defined, this function is called
+ by the main thread. To get MySQL to shut down nicely in this case
+ (Mac OS X) we have to call exit() instead if pthread_exit().
+*/
+
+void unireg_end(void)
{
clean_up();
my_thread_end();
+#ifdef SIGNALS_DONT_BREAK_READ
+ exit(0);
+#else
pthread_exit(0); // Exit is in main thread
+#endif
}
-void unireg_abort(int exit_code)
+extern "C" void unireg_abort(int exit_code)
{
DBUG_ENTER("unireg_abort");
if (exit_code)
@@ -860,6 +892,9 @@ void clean_up(bool print_message)
bitmap_free(&temp_pool);
free_max_user_conn();
end_slave_list();
+#ifdef USE_REGEX
+ regex_end();
+#endif
#if !defined(__WIN__) && !defined(EMBEDDED_LIBRARY)
if (!opt_bootstrap)
@@ -1161,7 +1196,7 @@ void close_connection(NET *net,uint errcode,bool lock)
/* Called when a thread is aborted */
/* ARGSUSED */
-sig_handler end_thread_signal(int sig __attribute__((unused)))
+extern "C" sig_handler end_thread_signal(int sig __attribute__((unused)))
{
THD *thd=current_thd;
DBUG_ENTER("end_thread_signal");
@@ -1252,7 +1287,7 @@ void flush_thread_cache()
*/
#ifdef THREAD_SPECIFIC_SIGPIPE
-static sig_handler abort_thread(int sig __attribute__((unused)))
+extern "C" sig_handler abort_thread(int sig __attribute__((unused)))
{
THD *thd=current_thd;
DBUG_ENTER("abort_thread");
@@ -1326,7 +1361,7 @@ static void start_signal_handler(void)
#define UNSAFE_DEFAULT_LINUX_THREADS 200
#endif
-static sig_handler handle_segfault(int sig)
+extern "C" sig_handler handle_segfault(int sig)
{
THD *thd=current_thd;
/*
@@ -1403,7 +1438,11 @@ information that should help you find out what is causing the crash.\n");
#endif /* HAVE_STACKTRACE */
if (test_flags & TEST_CORE_ON_SIGNAL)
+ {
+ fprintf(stderr, "Writing a core file\n");
+ fflush(stderr);
write_core(sig);
+ }
exit(1);
}
@@ -1511,7 +1550,7 @@ static void start_signal_handler(void)
/* This threads handles all signals and alarms */
/* ARGSUSED */
-static void *signal_hand(void *arg __attribute__((unused)))
+extern "C" void *signal_hand(void *arg __attribute__((unused)))
{
sigset_t set;
int sig;
@@ -1639,8 +1678,8 @@ static void *signal_hand(void *arg __attribute__((unused)))
/* ARGSUSED */
-static int my_message_sql(uint error, const char *str,
- myf MyFlags __attribute__((unused)))
+extern "C" int my_message_sql(uint error, const char *str,
+ myf MyFlags __attribute__((unused)))
{
THD *thd;
DBUG_ENTER("my_message_sql");
@@ -1660,6 +1699,17 @@ static int my_message_sql(uint error, const char *str,
DBUG_RETURN(0);
}
+
+/*
+ Forget last error message (if we got one)
+*/
+
+void clear_error_message(THD *thd)
+{
+ thd->net.last_error[0]= 0;
+}
+
+
#ifdef __WIN__
struct utsname
@@ -1675,7 +1725,7 @@ int uname(struct utsname *a)
#ifdef __WIN__
-pthread_handler_decl(handle_shutdown,arg)
+extern "C" pthread_handler_decl(handle_shutdown,arg)
{
MSG msg;
SHUTDOWN_THD;
@@ -1703,7 +1753,7 @@ int __stdcall handle_kill(ulong ctrl_type)
#endif
#ifdef OS2
-pthread_handler_decl(handle_shutdown,arg)
+extern "C" pthread_handler_decl(handle_shutdown,arg)
{
SHUTDOWN_THD;
my_thread_init();
@@ -1887,8 +1937,6 @@ int main(int argc, char **argv)
if (!ssl_acceptor_fd)
opt_use_ssl = 0;
}
- if (des_key_file)
- load_des_key_file(des_key_file);
#endif /* HAVE_OPENSSL */
#ifdef HAVE_LIBWRAP
@@ -1961,6 +2009,10 @@ int main(int argc, char **argv)
reset_floating_point_exceptions();
init_thr_lock();
init_slave_list();
+#ifdef HAVE_OPENSSL
+ if (des_key_file)
+ load_des_key_file(des_key_file);
+#endif /* HAVE_OPENSSL */
/* Setup log files */
if (opt_log)
@@ -1987,6 +2039,8 @@ int main(int argc, char **argv)
if (ha_init())
{
sql_print_error("Can't init databases");
+ if (unix_sock != INVALID_SOCKET)
+ unlink(mysql_unix_port);
exit(1);
}
ha_key_cache();
@@ -2022,10 +2076,12 @@ int main(int argc, char **argv)
pthread_key_create(&THR_MALLOC,NULL))
{
sql_print_error("Can't create thread-keys");
+ if (unix_sock != INVALID_SOCKET)
+ unlink(mysql_unix_port);
exit(1);
}
start_signal_handler(); // Creates pidfile
- if (acl_init(opt_noacl))
+ if (acl_init((THD*) 0, opt_noacl))
{
abort_loop=1;
select_thread_in_use=0;
@@ -2034,10 +2090,12 @@ int main(int argc, char **argv)
if (!opt_bootstrap)
(void) my_delete(pidfile_name,MYF(MY_WME)); // Not needed anymore
#endif
+ if (unix_sock != INVALID_SOCKET)
+ unlink(mysql_unix_port);
exit(1);
}
if (!opt_noacl)
- (void) grant_init();
+ (void) grant_init((THD*) 0);
init_max_user_conn();
init_update_queries();
@@ -2123,21 +2181,24 @@ The server will not act as a slave.");
printf(ER(ER_READY),my_progname,server_version,"");
fflush(stdout);
-
+#if defined(__NT__) || defined(HAVE_SMEM)
#ifdef __NT__
if (hPipe == INVALID_HANDLE_VALUE &&
- (!have_tcpip || opt_disable_networking))
+ (!have_tcpip || opt_disable_networking) &&
+ !opt_enable_shared_memory)
{
- sql_print_error("TCP/IP or --enable-named-pipe should be configured on NT OS");
+ sql_print_error("TCP/IP,--shared-memory or --named-pipe should be configured on NT OS");
unireg_abort(1);
}
else
+#endif
{
pthread_mutex_lock(&LOCK_thread_count);
(void) pthread_cond_init(&COND_handler_count,NULL);
{
pthread_t hThread;
handler_count=0;
+#ifdef __NT__
if (hPipe != INVALID_HANDLE_VALUE && opt_enable_named_pipe)
{
handler_count++;
@@ -2148,18 +2209,33 @@ The server will not act as a slave.");
handler_count--;
}
}
+#endif
+#ifdef HAVE_SMEM
+ if (opt_enable_shared_memory)
+ {
+ handler_count++;
+ if (pthread_create(&hThread,&connection_attrib,
+ handle_connections_shared_memory, 0))
+ {
+ sql_print_error("Warning: Can't create thread to handle shared memory");
+ handler_count--;
+ }
+ }
+#endif
if (have_tcpip && !opt_disable_networking)
{
handler_count++;
if (pthread_create(&hThread,&connection_attrib,
handle_connections_sockets, 0))
{
- sql_print_error("Warning: Can't create thread to handle named pipes");
+ sql_print_error("Warning: Can't create thread to handle tcp/ip");
handler_count--;
}
}
while (handler_count > 0)
+ {
pthread_cond_wait(&COND_handler_count,&LOCK_thread_count);
+ }
}
pthread_mutex_unlock(&LOCK_thread_count);
}
@@ -2488,7 +2564,7 @@ inline void kill_broken_server()
/* Handle new connections and spawn new process to handle them */
-pthread_handler_decl(handle_connections_sockets,arg __attribute__((unused)))
+extern "C" pthread_handler_decl(handle_connections_sockets,arg __attribute__((unused)))
{
my_socket sock,new_sock;
uint error_count=0;
@@ -2524,7 +2600,7 @@ pthread_handler_decl(handle_connections_sockets,arg __attribute__((unused)))
while (!abort_loop)
{
readFDs=clientFDs;
-#ifdef HPUX
+#ifdef HPUX10
if (select(max_used_connection,(int*) &readFDs,0,0,0) < 0)
continue;
#else
@@ -2538,7 +2614,7 @@ pthread_handler_decl(handle_connections_sockets,arg __attribute__((unused)))
MAYBE_BROKEN_SYSCALL
continue;
}
-#endif /* HPUX */
+#endif /* HPUX10 */
if (abort_loop)
{
MAYBE_BROKEN_SYSCALL;
@@ -2695,7 +2771,7 @@ pthread_handler_decl(handle_connections_sockets,arg __attribute__((unused)))
#ifdef __NT__
-pthread_handler_decl(handle_connections_namedpipes,arg)
+extern "C" pthread_handler_decl(handle_connections_namedpipes,arg)
{
HANDLE hConnectedPipe;
BOOL fConnected;
@@ -2777,6 +2853,219 @@ pthread_handler_decl(handle_connections_namedpipes,arg)
}
#endif /* __NT__ */
+/*
+ Thread of shared memory's service
+
+ SYNOPSIS
+ pthread_handler_decl()
+ handle_connections_shared_memory Thread handle
+ arg Arguments of thread
+*/
+#ifdef HAVE_SMEM
+pthread_handler_decl(handle_connections_shared_memory,arg)
+{
+/*
+ event_connect_request is event object for start connection actions
+ event_connect_answer is event object for confirm, that server put data
+ handle_connect_file_map is file-mapping object, use for create shared memory
+ handle_connect_map is pointer on shared memory
+ handle_map is pointer on shared memory for client
+ event_server_wrote,
+ event_server_read,
+ event_client_wrote,
+ event_client_read are events for transfer data between server and client
+ handle_file_map is file-mapping object, use for create shared memory
+*/
+ HANDLE handle_connect_file_map = NULL;
+ char *handle_connect_map = NULL;
+ HANDLE event_connect_request = NULL;
+ HANDLE event_connect_answer = NULL;
+ ulong smem_buffer_length = shared_memory_buffer_length + 4;
+ ulong connect_number = 1;
+ my_bool error_allow;
+ THD *thd;
+ char tmp[63];
+ char *suffix_pos;
+ char connect_number_char[22], *p;
+
+ my_thread_init();
+ DBUG_ENTER("handle_connections_shared_memorys");
+ DBUG_PRINT("general",("Waiting for allocated shared memory."));
+
+
+/*
+ The name of event and file-mapping events create agree next rule:
+ shared_memory_base_name+unique_part
+ Where:
+ shared_memory_base_name is unique value for each server
+ unique_part is unique value for each object (events and file-mapping)
+*/
+ suffix_pos = strxmov(tmp,shared_memory_base_name,"_",NullS);
+ strmov(suffix_pos, "CONNECT_REQUEST");
+ if ((event_connect_request = CreateEvent(NULL,FALSE,FALSE,tmp)) == 0)
+ {
+ sql_perror("Can't create shared memory service ! The request event don't create.");
+ goto error;
+ }
+ strmov(suffix_pos, "CONNECT_ANSWER");
+ if ((event_connect_answer = CreateEvent(NULL,FALSE,FALSE,tmp)) == 0)
+ {
+ sql_perror("Can't create shared memory service ! The answer event don't create.");
+ goto error;
+ }
+ strmov(suffix_pos, "CONNECT_DATA");
+ if ((handle_connect_file_map = CreateFileMapping(INVALID_HANDLE_VALUE,NULL,PAGE_READWRITE,
+ 0,sizeof(connect_number),tmp)) == 0)
+ {
+ sql_perror("Can't create shared memory service ! File mapping don't create.");
+ goto error;
+ }
+ if ((handle_connect_map = (char *)MapViewOfFile(handle_connect_file_map,FILE_MAP_WRITE,0,0,
+ sizeof(DWORD))) == 0)
+ {
+ sql_perror("Can't create shared memory service ! Map of memory don't create.");
+ goto error;
+ }
+
+
+ while (!abort_loop)
+ {
+/*
+ Wait a request from client
+*/
+ WaitForSingleObject(event_connect_request,INFINITE);
+ error_allow = FALSE;
+
+ HANDLE handle_client_file_map = NULL;
+ char *handle_client_map = NULL;
+ HANDLE event_client_wrote = NULL;
+ HANDLE event_client_read = NULL;
+ HANDLE event_server_wrote = NULL;
+ HANDLE event_server_read = NULL;
+
+ p = int2str(connect_number, connect_number_char, 10);
+/*
+ The name of event and file-mapping events create agree next rule:
+ shared_memory_base_name+unique_part+number_of_connection
+ Where:
+ shared_memory_base_name is uniquel value for each server
+ unique_part is unique value for each object (events and file-mapping)
+ number_of_connection is number of connection between server and client
+*/
+ suffix_pos = strxmov(tmp,shared_memory_base_name,"_",connect_number_char,"_",NullS);
+ strmov(suffix_pos, "DATA");
+ if ((handle_client_file_map = CreateFileMapping(INVALID_HANDLE_VALUE,NULL,
+ PAGE_READWRITE,0,smem_buffer_length,tmp)) == 0)
+ {
+ sql_perror("Can't create connection with client in shared memory service ! File mapping don't create.");
+ error_allow = TRUE;
+ goto errorconn;
+ }
+ if ((handle_client_map = (char*)MapViewOfFile(handle_client_file_map,FILE_MAP_WRITE,0,0,smem_buffer_length)) == 0)
+ {
+ sql_perror("Can't create connection with client in shared memory service ! Map of memory don't create.");
+ error_allow = TRUE;
+ goto errorconn;
+ }
+
+ strmov(suffix_pos, "CLIENT_WROTE");
+ if ((event_client_wrote = CreateEvent(NULL,FALSE,FALSE,tmp)) == 0)
+ {
+ sql_perror("Can't create connection with client in shared memory service ! CW event don't create.");
+ error_allow = TRUE;
+ goto errorconn;
+ }
+
+ strmov(suffix_pos, "CLIENT_READ");
+ if ((event_client_read = CreateEvent(NULL,FALSE,FALSE,tmp)) == 0)
+ {
+ sql_perror("Can't create connection with client in shared memory service ! CR event don't create.");
+ error_allow = TRUE;
+ goto errorconn;
+ }
+
+ strmov(suffix_pos, "SERVER_READ");
+ if ((event_server_read = CreateEvent(NULL,FALSE,FALSE,tmp)) == 0)
+ {
+ sql_perror("Can't create connection with client in shared memory service ! SR event don't create.");
+ error_allow = TRUE;
+ goto errorconn;
+ }
+
+ strmov(suffix_pos, "SERVER_WROTE");
+ if ((event_server_wrote = CreateEvent(NULL,FALSE,FALSE,tmp)) == 0)
+ {
+ sql_perror("Can't create connection with client in shared memory service ! SW event don't create.");
+ error_allow = TRUE;
+ goto errorconn;
+ }
+
+ if (abort_loop) break;
+ if ( !(thd = new THD))
+ {
+ error_allow = TRUE;
+ goto errorconn;
+ }
+
+/*
+Send number of connection to client
+*/
+ int4store(handle_connect_map, connect_number);
+
+/*
+ Send number of connection to client
+*/
+ if (!SetEvent(event_connect_answer))
+ {
+ sql_perror("Can't create connection with client in shared memory service ! Can't send answer event.");
+ error_allow = TRUE;
+ goto errorconn;
+ }
+
+/*
+ Set event that client should receive data
+*/
+ if (!SetEvent(event_client_read))
+ {
+ sql_perror("Can't create connection with client in shared memory service ! Can't set client to read's mode.");
+ error_allow = TRUE;
+ goto errorconn;
+ }
+ if (!(thd->net.vio = vio_new_win32shared_memory(&thd->net,handle_client_file_map,handle_client_map,event_client_wrote,
+ event_client_read,event_server_wrote,event_server_read)) ||
+ my_net_init(&thd->net, thd->net.vio))
+ {
+ close_connection(&thd->net,ER_OUT_OF_RESOURCES);
+ delete thd;
+ error_allow = TRUE;
+ }
+ /* host name is unknown */
+errorconn:
+ if (error_allow)
+ {
+ if (!handle_client_map) UnmapViewOfFile(handle_client_map);
+ if (!handle_client_file_map) CloseHandle(handle_client_file_map);
+ if (!event_server_wrote) CloseHandle(event_server_wrote);
+ if (!event_server_read) CloseHandle(event_server_read);
+ if (!event_client_wrote) CloseHandle(event_client_wrote);
+ if (!event_client_read) CloseHandle(event_client_read);
+ continue;
+ }
+ thd->host = my_strdup(localhost,MYF(0)); /* Host is unknown */
+ create_new_thread(thd);
+ uint4korr(connect_number++);
+ }
+error:
+ if (!handle_connect_map) UnmapViewOfFile(handle_connect_map);
+ if (!handle_connect_file_map) CloseHandle(handle_connect_file_map);
+ if (!event_connect_answer) CloseHandle(event_connect_answer);
+ if (!event_connect_request) CloseHandle(event_connect_request);
+ pthread_mutex_lock(&LOCK_thread_count);
+ pthread_mutex_unlock(&LOCK_thread_count);
+ DBUG_RETURN(0);
+}
+#endif /* HAVE_SMEM */
+
/******************************************************************************
** handle start options
@@ -2807,8 +3096,9 @@ enum options {
OPT_MASTER_PASSWORD, OPT_MASTER_PORT,
OPT_MASTER_INFO_FILE, OPT_MASTER_CONNECT_RETRY,
OPT_MASTER_RETRY_COUNT,
- OPT_MASTER_SSL, OPT_MASTER_SSL_KEY,
- OPT_MASTER_SSL_CERT,
+ OPT_MASTER_SSL, OPT_MASTER_SSL_KEY,
+ OPT_MASTER_SSL_CERT, OPT_MASTER_SSL_CAPATH,
+ OPT_MASTER_SSL_CIPHER,
OPT_SQL_BIN_UPDATE_SAME, OPT_REPLICATE_DO_DB,
OPT_REPLICATE_IGNORE_DB, OPT_LOG_SLAVE_UPDATES,
OPT_BINLOG_DO_DB, OPT_BINLOG_IGNORE_DB,
@@ -2887,6 +3177,8 @@ enum options {
OPT_BDB_CACHE_SIZE,
OPT_BDB_LOG_BUFFER_SIZE,
OPT_BDB_MAX_LOCK,
+ OPT_ENABLE_SHARED_MEMORY,
+ OPT_SHARED_MEMORY_BASE_NAME,
OPT_OLD_PASSWORDS
};
@@ -2994,6 +3286,11 @@ struct my_option my_long_options[] =
{"enable-pstack", OPT_DO_PSTACK, "Print a symbolic stack trace on failure",
(gptr*) &opt_do_pstack, (gptr*) &opt_do_pstack, 0, GET_BOOL, NO_ARG, 0, 0,
0, 0, 0, 0},
+#ifdef HAVE_SMEM
+ {"shared-memory", OPT_ENABLE_SHARED_MEMORY,
+ "Enable the shared memory.",(gptr*) &opt_enable_shared_memory, (gptr*) &opt_enable_shared_memory,
+ 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+#endif
{"exit-info", 'T', "Used for debugging; Use at your own risk!", 0, 0, 0,
GET_LONG, OPT_ARG, 0, 0, 0, 0, 0, 0},
{"flush", OPT_FLUSH, "Flush tables to disk between SQL commands", 0, 0, 0,
@@ -3119,6 +3416,14 @@ struct my_option my_long_options[] =
"Master SSL certificate file name. Only applies if you have enabled master-ssl.",
(gptr*) &master_ssl_cert, (gptr*) &master_ssl_cert, 0, GET_STR, OPT_ARG,
0, 0, 0, 0, 0, 0},
+ {"master-ssl-capath", OPT_MASTER_SSL_CAPATH,
+ "Master SSL CA path. Only applies if you have enabled master-ssl.",
+ (gptr*) &master_ssl_capath, (gptr*) &master_ssl_capath, 0, GET_STR, OPT_ARG,
+ 0, 0, 0, 0, 0, 0},
+ {"master-ssl-cipher", OPT_MASTER_SSL_CIPHER,
+ "Master SSL cipher. Only applies if you have enabled master-ssl.",
+ (gptr*) &master_ssl_cipher, (gptr*) &master_ssl_capath, 0, GET_STR, OPT_ARG,
+ 0, 0, 0, 0, 0, 0},
{"myisam-recover", OPT_MYISAM_RECOVER,
"Syntax: myisam-recover[=option[,option...]], where option can be DEFAULT, BACKUP or FORCE.",
(gptr*) &myisam_recover_options_str, (gptr*) &myisam_recover_options_str, 0,
@@ -3208,7 +3513,7 @@ struct my_option my_long_options[] =
(gptr*) &report_port, (gptr*) &report_port, 0, GET_UINT, REQUIRED_ARG,
MYSQL_PORT, 0, 0, 0, 0, 0},
{"rpl-recovery-rank", OPT_RPL_RECOVERY_RANK, "Undocumented",
- (gptr*) &rpl_recovery_rank, (gptr*) &rpl_recovery_rank, 0, GET_UINT,
+ (gptr*) &rpl_recovery_rank, (gptr*) &rpl_recovery_rank, 0, GET_ULONG,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"relay-log", OPT_RELAY_LOG, "Undocumented",
(gptr*) &opt_relay_logname, (gptr*) &opt_relay_logname, 0,
@@ -3223,8 +3528,7 @@ struct my_option my_long_options[] =
#ifndef TO_BE_DELETED
{"safe-show-database", OPT_SAFE_SHOW_DB,
"Deprecated option; One should use GRANT SHOW DATABASES instead...",
- (gptr*) &opt_safe_show_db, (gptr*) &opt_safe_show_db, 0, GET_BOOL, NO_ARG,
- 0, 0, 0, 0, 0, 0},
+ 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
#endif
{"safe-user-create", OPT_SAFE_USER_CREATE,
"Don't allow new user creation by the user who has no write privileges to the mysql.user table",
@@ -3237,6 +3541,11 @@ struct my_option my_long_options[] =
{"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},
+#ifdef HAVE_SMEM
+ {"shared_memory_base_name",OPT_SHARED_MEMORY_BASE_NAME,
+ "Base name of shared memory", (gptr*) &shared_memory_base_name, (gptr*) &shared_memory_base_name,
+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+#endif
{"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,
@@ -3774,6 +4083,7 @@ struct show_var_st status_vars[]= {
{"Qcache_queries_in_cache", (char*) &query_cache.queries_in_cache, SHOW_LONG_CONST},
{"Qcache_inserts", (char*) &query_cache.inserts, SHOW_LONG},
{"Qcache_hits", (char*) &query_cache.hits, SHOW_LONG},
+ {"Qcache_lowmem_prunes", (char*) &query_cache.lowmem_prunes, SHOW_LONG},
{"Qcache_not_cached", (char*) &query_cache.refused, SHOW_LONG},
{"Qcache_free_memory", (char*) &query_cache.free_memory,
SHOW_LONG_CONST},
@@ -3894,11 +4204,11 @@ static void set_options(void)
/* Set default values for some variables */
global_system_variables.table_type=DB_TYPE_MYISAM;
- global_system_variables.tx_isolation=ISO_READ_COMMITTED;
- global_system_variables.select_limit= (ulong) HA_POS_ERROR;
+ global_system_variables.tx_isolation=ISO_REPEATABLE_READ;
+ global_system_variables.select_limit= (ulonglong) HA_POS_ERROR;
max_system_variables.select_limit= (ulong) HA_POS_ERROR;
- global_system_variables.max_join_size= (ulong) HA_POS_ERROR;
- max_system_variables.max_join_size= (ulong) HA_POS_ERROR;
+ global_system_variables.max_join_size= (ulonglong) HA_POS_ERROR;
+ max_system_variables.max_join_size= (ulonglong) HA_POS_ERROR;
#ifdef __WIN__
/* Allow Win32 users to move MySQL anywhere */
@@ -3921,7 +4231,7 @@ static void set_options(void)
}
-static my_bool
+extern "C" my_bool
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
char *argument)
{
@@ -3934,8 +4244,8 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
break;
case 'a':
opt_sql_mode = (MODE_REAL_AS_FLOAT | MODE_PIPES_AS_CONCAT |
- MODE_ANSI_QUOTES | MODE_IGNORE_SPACE | MODE_SERIALIZABLE
- | MODE_ONLY_FULL_GROUP_BY);
+ MODE_ANSI_QUOTES | MODE_IGNORE_SPACE | MODE_SERIALIZABLE |
+ MODE_ONLY_FULL_GROUP_BY);
global_system_variables.tx_isolation= ISO_SERIALIZABLE;
break;
case 'b':
@@ -4366,7 +4676,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
}
global_system_variables.tx_isolation= ((opt_sql_mode & MODE_SERIALIZABLE) ?
ISO_SERIALIZABLE :
- ISO_READ_COMMITTED);
+ ISO_REPEATABLE_READ);
break;
}
case OPT_MASTER_PASSWORD:
@@ -4464,9 +4774,17 @@ fn_format_relative_to_data_home(my_string to, const char *name,
static void fix_paths(void)
{
- char buff[FN_REFLEN];
- (void) fn_format(mysql_home,mysql_home,"","",16); // Remove symlinks
+ char buff[FN_REFLEN],*pos;
convert_dirname(mysql_home,mysql_home,NullS);
+ /* Resolve symlinks to allow 'mysql_home' to be a relative symlink */
+ my_realpath(mysql_home,mysql_home,MYF(0));
+ /* Ensure that mysql_home ends in FN_LIBCHAR */
+ pos=strend(mysql_home);
+ if (pos[-1] != FN_LIBCHAR)
+ {
+ pos[0]= FN_LIBCHAR;
+ pos[1]= 0;
+ }
convert_dirname(mysql_real_data_home,mysql_real_data_home,NullS);
convert_dirname(language,language,NullS);
(void) my_load_path(mysql_home,mysql_home,""); // Resolve current dir
diff --git a/sql/nt_servc.cc b/sql/nt_servc.cc
index 2d0eae125d6..b917c91ce15 100644
--- a/sql/nt_servc.cc
+++ b/sql/nt_servc.cc
@@ -568,31 +568,3 @@ BOOL NTService::is_super_user()
FreeSid(psidAdministrators);
return ret_value;
}
-/* ------------------------------------------------------------------------
- -------------------------------------------------------------------------- */
-BOOL NTService::IsService(LPCSTR ServiceName)
-{
- BOOL ret_value=FALSE;
- SC_HANDLE service, scm;
-
- if (scm = OpenSCManager(0, 0,SC_MANAGER_ENUMERATE_SERVICE))
- {
- if ((service = OpenService(scm,ServiceName, SERVICE_ALL_ACCESS )))
- {
- ret_value=TRUE;
- CloseServiceHandle(service);
- }
- CloseServiceHandle(scm);
- }
- return ret_value;
-}
-/* ------------------------------------------------------------------------
- -------------------------------------------------------------------------- */
-BOOL NTService::got_service_option(char **argv, char *service_option)
-{
- char *option;
- for (option= argv[1]; *option; option++)
- if (!strcmp(option, service_option))
- return TRUE;
- return FALSE;
-}
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 9a644553f26..b6f81ab07eb 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -299,9 +299,6 @@ static SEL_TREE * get_mm_parts(PARAM *param,Field *field,
Item_result cmp_type);
static SEL_ARG *get_mm_leaf(PARAM *param,Field *field,KEY_PART *key_part,
Item_func::Functype type,Item *value);
-static bool like_range(const char *ptr,uint length,char wild_prefix,
- uint field_length, char *min_str,char *max_str,
- char max_sort_char,uint *min_length,uint *max_length);
static SEL_TREE *get_mm_tree(PARAM *param,COND *cond);
static ha_rows check_quick_select(PARAM *param,uint index,SEL_ARG *key_tree);
static ha_rows check_quick_keys(PARAM *param,uint index,SEL_ARG *key_tree,
@@ -970,27 +967,14 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part,
max_str=min_str+length;
if (maybe_null)
max_str[0]= min_str[0]=0;
- if (field->binary())
- like_error=like_range(res->ptr(),res->length(),wild_prefix,field_length,
- min_str+offset,max_str+offset,(char) 255,
- &min_length,&max_length);
- else
- {
- CHARSET_INFO *charset=field->charset();
-#ifdef USE_STRCOLL
- if (use_strnxfrm(charset))
- like_error= my_like_range(charset,
- res->ptr(),res->length(),wild_prefix,
- field_length, min_str+maybe_null,
- max_str+maybe_null,&min_length,&max_length);
- else
-#endif
- like_error=like_range(res->ptr(),res->length(),wild_prefix,
- field_length,
- min_str+offset,max_str+offset,
- charset->max_sort_char,
- &min_length,&max_length);
- }
+
+ like_error= my_like_range(field->charset(),
+ res->ptr(),res->length(),
+ wild_prefix,wild_one,wild_many,
+ field_length,
+ min_str+offset, max_str+offset,
+ &min_length,&max_length);
+
if (like_error) // Can't optimize with LIKE
DBUG_RETURN(0);
if (offset != maybe_null) // Blob
@@ -1119,69 +1103,6 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part,
}
-/*
-** Calculate min_str and max_str that ranges a LIKE string.
-** Arguments:
-** ptr Pointer to LIKE string.
-** ptr_length Length of LIKE string.
-** escape Escape character in LIKE. (Normally '\').
-** All escape characters should be removed from min_str and max_str
-** res_length Length of min_str and max_str.
-** min_str Smallest case sensitive string that ranges LIKE.
-** Should be space padded to res_length.
-** max_str Largest case sensitive string that ranges LIKE.
-** Normally padded with the biggest character sort value.
-**
-** The function should return 0 if ok and 1 if the LIKE string can't be
-** optimized !
-*/
-
-static bool like_range(const char *ptr,uint ptr_length,char escape,
- uint res_length, char *min_str,char *max_str,
- char max_sort_chr, uint *min_length, uint *max_length)
-{
- const char *end=ptr+ptr_length;
- char *min_org=min_str;
- char *min_end=min_str+res_length;
-
- for (; ptr != end && min_str != min_end ; ptr++)
- {
- if (*ptr == escape && ptr+1 != end)
- {
- ptr++; // Skip escape
- *min_str++= *max_str++ = *ptr;
- continue;
- }
- if (*ptr == wild_one) // '_' in SQL
- {
- *min_str++='\0'; // This should be min char
- *max_str++=max_sort_chr;
- continue;
- }
- if (*ptr == wild_many) // '%' in SQL
- {
- *min_length= (uint) (min_str - min_org);
- *max_length=res_length;
- do {
- *min_str++ = ' '; // Because if key compression
- *max_str++ = max_sort_chr;
- } while (min_str != min_end);
- return 0;
- }
- *min_str++= *max_str++ = *ptr;
- }
- *min_length= *max_length = (uint) (min_str - min_org);
-
- /* Temporary fix for handling wild_one at end of string (key compression) */
- for (char *tmp= min_str ; tmp > min_org && tmp[-1] == '\0';)
- *--tmp=' ';
-
- while (min_str != min_end)
- *min_str++ = *max_str++ = ' '; // Because if key compression
- return 0;
-}
-
-
/******************************************************************************
** Tree manipulation functions
** If tree is 0 it means that the condition can't be tested. It refers
@@ -2542,9 +2463,9 @@ int QUICK_SELECT::get_next()
if (range->flag & NO_MIN_RANGE) // Read first record
{
- int error;
- if ((error=file->index_first(record)))
- DBUG_RETURN(error); // Empty table
+ int local_error;
+ if ((local_error=file->index_first(record)))
+ DBUG_RETURN(local_error); // Empty table
if (cmp_next(range) == 0)
DBUG_RETURN(0);
range=0; // No matching records; go to next range
@@ -2578,13 +2499,13 @@ int QUICK_SELECT::get_next()
/* compare if found key is over max-value */
/* Returns 0 if key <= range->max_key */
-int QUICK_SELECT::cmp_next(QUICK_RANGE *range)
+int QUICK_SELECT::cmp_next(QUICK_RANGE *range_arg)
{
- if (range->flag & NO_MAX_RANGE)
- return (0); /* key can't be to large */
+ if (range_arg->flag & NO_MAX_RANGE)
+ return 0; /* key can't be to large */
KEY_PART *key_part=key_parts;
- for (char *key=range->max_key, *end=key+range->max_length;
+ for (char *key=range_arg->max_key, *end=key+range_arg->max_length;
key < end;
key+= key_part++->part_length)
{
@@ -2605,7 +2526,7 @@ int QUICK_SELECT::cmp_next(QUICK_RANGE *range)
if (cmp > 0)
return 1;
}
- return (range->flag & NEAR_MAX) ? 1 : 0; // Exact match
+ return (range_arg->flag & NEAR_MAX) ? 1 : 0; // Exact match
}
@@ -2689,9 +2610,9 @@ int QUICK_SELECT_DESC::get_next()
if (range->flag & NO_MAX_RANGE) // Read last record
{
- int error;
- if ((error=file->index_last(record)))
- DBUG_RETURN(error); // Empty table
+ int local_error;
+ if ((local_error=file->index_last(record)))
+ DBUG_RETURN(local_error); // Empty table
if (cmp_prev(range) == 0)
DBUG_RETURN(0);
range=0; // No matching records; go to next range
@@ -2745,16 +2666,18 @@ int QUICK_SELECT_DESC::get_next()
}
}
+
/*
- * Returns 0 if found key is inside range (found key >= range->min_key).
- */
-int QUICK_SELECT_DESC::cmp_prev(QUICK_RANGE *range)
+ Returns 0 if found key is inside range (found key >= range->min_key).
+*/
+
+int QUICK_SELECT_DESC::cmp_prev(QUICK_RANGE *range_arg)
{
- if (range->flag & NO_MIN_RANGE)
- return (0); /* key can't be to small */
+ if (range_arg->flag & NO_MIN_RANGE)
+ return 0; /* key can't be to small */
KEY_PART *key_part = key_parts;
- for (char *key = range->min_key, *end = key + range->min_length;
+ for (char *key = range_arg->min_key, *end = key + range_arg->min_length;
key < end;
key += key_part++->part_length)
{
@@ -2778,42 +2701,45 @@ int QUICK_SELECT_DESC::cmp_prev(QUICK_RANGE *range)
if (cmp < 0)
return 1;
}
- return (range->flag & NEAR_MIN) ? 1 : 0; // Exact match
+ return (range_arg->flag & NEAR_MIN) ? 1 : 0; // Exact match
}
+
/*
* True if this range will require using HA_READ_AFTER_KEY
See comment in get_next() about this
*/
-bool QUICK_SELECT_DESC::range_reads_after_key(QUICK_RANGE *range)
+bool QUICK_SELECT_DESC::range_reads_after_key(QUICK_RANGE *range_arg)
{
- return ((range->flag & (NO_MAX_RANGE | NEAR_MAX)) ||
- !(range->flag & EQ_RANGE) ||
- head->key_info[index].key_length != range->max_length) ? 1 : 0;
+ return ((range_arg->flag & (NO_MAX_RANGE | NEAR_MAX)) ||
+ !(range_arg->flag & EQ_RANGE) ||
+ head->key_info[index].key_length != range_arg->max_length) ? 1 : 0;
}
+
/* True if we are reading over a key that may have a NULL value */
-bool QUICK_SELECT_DESC::test_if_null_range(QUICK_RANGE *range,
+bool QUICK_SELECT_DESC::test_if_null_range(QUICK_RANGE *range_arg,
uint used_key_parts)
{
uint offset,end;
KEY_PART *key_part = key_parts,
*key_part_end= key_part+used_key_parts;
- for (offset= 0, end = min(range->min_length, range->max_length) ;
+ for (offset= 0, end = min(range_arg->min_length, range_arg->max_length) ;
offset < end && key_part != key_part_end ;
offset += key_part++->part_length)
{
uint null_length=test(key_part->null_bit);
- if (!memcmp((char*) range->min_key+offset, (char*) range->max_key+offset,
+ if (!memcmp((char*) range_arg->min_key+offset,
+ (char*) range_arg->max_key+offset,
key_part->part_length + null_length))
{
offset+=null_length;
continue;
}
- if (null_length && range->min_key[offset])
+ if (null_length && range_arg->min_key[offset])
return 1; // min_key is null and max_key isn't
// Range doesn't cover NULL. This is ok if there is no more null parts
break;
@@ -2826,7 +2752,7 @@ bool QUICK_SELECT_DESC::test_if_null_range(QUICK_RANGE *range,
*/
if (key_part != key_part_end && key_part->null_bit)
{
- if (offset >= range->min_length || range->min_key[offset])
+ if (offset >= range_arg->min_length || range_arg->min_key[offset])
return 1; // Could be null
key_part++;
}
diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc
index 38365dbb546..1477d46e756 100644
--- a/sql/opt_sum.cc
+++ b/sql/opt_sum.cc
@@ -37,6 +37,19 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
bool recalc_const_item=0;
table_map removed_tables=0;
Item *item;
+ COND *org_conds= conds;
+
+ /* Add all ON conditions to WHERE condition */
+ for (TABLE_LIST *tl=tables; tl ; tl= tl->next)
+ {
+ if (tl->on_expr)
+ conds= and_expressions(conds, tl->on_expr, &org_conds);
+ }
+
+ /*
+ Iterate through item is select part and replace COUNT(), MIN() and MAX()
+ with constants (if possible)
+ */
while ((item= it++))
{
diff --git a/sql/procedure.h b/sql/procedure.h
index 3434079a8fb..c3280b951d3 100644
--- a/sql/procedure.h
+++ b/sql/procedure.h
@@ -62,7 +62,7 @@ public:
{ value=atof(str); }
double val() { return value; }
longlong val_int() { return (longlong) value; }
- String *val_str(String *s) { s->set(value,decimals,my_thd_charset); return s; }
+ String *val_str(String *s) { s->set(value,decimals,thd_charset()); return s; }
unsigned int size_of() { return sizeof(*this);}
};
@@ -80,7 +80,7 @@ public:
{ value=strtoll(str,NULL,10); }
double val() { return (double) value; }
longlong val_int() { return value; }
- String *val_str(String *s) { s->set(value, my_thd_charset); return s; }
+ String *val_str(String *s) { s->set(value, thd_charset()); return s; }
unsigned int size_of() { return sizeof(*this);}
};
@@ -92,9 +92,9 @@ public:
{ this->max_length=length; }
enum Item_result result_type () const { return STRING_RESULT; }
enum_field_types field_type() const { return FIELD_TYPE_STRING; }
- void set(double nr) { str_value.set(nr, 2, my_thd_charset); }
- void set(longlong nr) { str_value.set(nr, my_thd_charset); }
- void set(const char *str, uint length) { str_value.copy(str,length, my_thd_charset); }
+ void set(double nr) { str_value.set(nr, 2, thd_charset()); }
+ void set(longlong nr) { str_value.set(nr, thd_charset()); }
+ void set(const char *str, uint length) { str_value.copy(str,length, thd_charset()); }
double val() { return atof(str_value.ptr()); }
longlong val_int() { return strtoll(str_value.ptr(),NULL,10); }
String *val_str(String*)
diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc
index 4295a16c547..785a253b1ac 100644
--- a/sql/repl_failsafe.cc
+++ b/sql/repl_failsafe.cc
@@ -188,14 +188,15 @@ err2:
return 1;
}
-static uint32* slave_list_key(SLAVE_INFO* si, uint* len,
- my_bool not_used __attribute__((unused)))
+extern "C" uint32
+*slave_list_key(SLAVE_INFO* si, uint* len,
+ my_bool not_used __attribute__((unused)))
{
*len = 4;
return &si->server_id;
}
-static void slave_info_free(void *s)
+extern "C" void slave_info_free(void *s)
{
my_free((gptr) s, MYF(MY_WME));
}
@@ -203,7 +204,7 @@ static void slave_info_free(void *s)
void init_slave_list()
{
hash_init(&slave_list, system_charset_info, SLAVE_LIST_CHUNK, 0, 0,
- (hash_get_key) slave_list_key, slave_info_free, 0);
+ (hash_get_key) slave_list_key, (hash_free_key) slave_info_free, 0);
pthread_mutex_init(&LOCK_slave_list, MY_MUTEX_INIT_FAST);
}
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 72579664a3e..599c4af06cc 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -154,11 +154,11 @@ sys_var_thd_ulong sys_max_error_count("max_error_count",
&SV::max_error_count);
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",
+sys_var_thd_ulonglong 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",
+sys_var_thd_ulonglong sys_sql_max_join_size("sql_max_join_size",
&SV::max_join_size,
fix_max_join_size);
#endif
@@ -202,8 +202,6 @@ sys_var_thd_enum sys_query_cache_type("query_cache_type",
&SV::query_cache_type,
&query_cache_type_typelib);
#endif /* HAVE_QUERY_CACHE */
-sys_var_bool_ptr sys_safe_show_db("safe_show_database",
- &opt_safe_show_db);
sys_var_long_ptr sys_server_id("server_id",&server_id);
sys_var_bool_ptr sys_slave_compressed_protocol("slave_compressed_protocol",
&opt_slave_compressed_protocol);
@@ -282,7 +280,7 @@ static sys_var_thd_bit sys_unique_checks("unique_checks",
/* Local state variables */
-static sys_var_thd_ulong sys_select_limit("sql_select_limit",
+static sys_var_thd_ulonglong 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");
@@ -299,6 +297,8 @@ static sys_var_readonly sys_warning_count("warning_count",
/* alias for last_insert_id() to be compatible with Sybase */
static sys_var_slave_skip_counter sys_slave_skip_counter("sql_slave_skip_counter");
+static sys_var_rand_seed1 sys_rand_seed1("rand_seed1");
+static sys_var_rand_seed2 sys_rand_seed2("rand_seed2");
/*
@@ -370,10 +370,11 @@ sys_var *sys_variables[]=
&sys_query_cache_type,
#endif /* HAVE_QUERY_CACHE */
&sys_quote_show_create,
+ &sys_rand_seed1,
+ &sys_rand_seed2,
&sys_read_buff_size,
&sys_read_rnd_buff_size,
&sys_rpl_recovery_rank,
- &sys_safe_show_db,
&sys_safe_updates,
&sys_select_limit,
&sys_server_id,
@@ -448,7 +449,7 @@ struct show_var_st init_vars[]= {
{"innodb_file_io_threads", (char*) &innobase_file_io_threads, SHOW_LONG },
{"innodb_force_recovery", (char*) &innobase_force_recovery, SHOW_LONG },
{"innodb_thread_concurrency", (char*) &innobase_thread_concurrency, SHOW_LONG },
- {"innodb_flush_log_at_trx_commit", (char*) &innobase_flush_log_at_trx_commit, SHOW_LONG},
+ {"innodb_flush_log_at_trx_commit", (char*) &innobase_flush_log_at_trx_commit, SHOW_INT},
{"innodb_fast_shutdown", (char*) &innobase_fast_shutdown, SHOW_MY_BOOL},
{"innodb_flush_method", (char*) &innobase_unix_file_flush_method, SHOW_CHAR_PTR},
{"innodb_lock_wait_timeout", (char*) &innobase_lock_wait_timeout, SHOW_LONG },
@@ -519,14 +520,19 @@ struct show_var_st init_vars[]= {
{sys_query_cache_size.name, (char*) &sys_query_cache_size, SHOW_SYS},
{sys_query_cache_type.name, (char*) &sys_query_cache_type, SHOW_SYS},
#endif /* HAVE_QUERY_CACHE */
- {sys_safe_show_db.name, (char*) &sys_safe_show_db, SHOW_SYS},
+#ifdef HAVE_SMEM
+ {"shared_memory", (char*) &opt_enable_shared_memory, SHOW_MY_BOOL},
+ {"shared_memory_base_name", (char*) &shared_memory_base_name, SHOW_CHAR_PTR},
+#endif
{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},
+#ifdef HAVE_SYS_UN_H
{"socket", (char*) &mysql_unix_port, SHOW_CHAR_PTR},
+#endif
{sys_sort_buffer.name, (char*) &sys_sort_buffer, SHOW_SYS},
{"sql_mode", (char*) &opt_sql_mode, SHOW_LONG},
{"table_cache", (char*) &table_cache_size, SHOW_LONG},
@@ -594,7 +600,7 @@ 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)
+ if (thd->variables.max_join_size == (ulonglong) HA_POS_ERROR)
thd->options|= OPTION_BIG_SELECTS;
else
thd->options&= ~OPTION_BIG_SELECTS;
@@ -769,7 +775,7 @@ bool sys_var_thd_ulonglong::update(THD *thd, set_var *var)
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;
+ global_system_variables.*offset= (ulonglong) option_limits->def_value;
else
thd->variables.*offset= global_system_variables.*offset;
}
@@ -1069,6 +1075,19 @@ bool sys_var_slave_skip_counter::update(THD *thd, set_var *var)
}
+bool sys_var_rand_seed1::update(THD *thd, set_var *var)
+{
+ thd->rand.seed1= (ulong) var->value->val_int();
+ return 0;
+}
+
+bool sys_var_rand_seed2::update(THD *thd, set_var *var)
+{
+ thd->rand.seed2= (ulong) var->value->val_int();
+ return 0;
+}
+
+
/*
Functions to update thd->options bits
*/
diff --git a/sql/set_var.h b/sql/set_var.h
index 31154d1e1d7..de1e27e0da8 100644
--- a/sql/set_var.h
+++ b/sql/set_var.h
@@ -203,6 +203,10 @@ public:
sys_var_thd_ulonglong(const char *name_arg, ulonglong SV::*offset_arg)
:sys_var_thd(name_arg), offset(offset_arg)
{}
+ sys_var_thd_ulonglong(const char *name_arg, ulonglong 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_LONGLONG; }
@@ -333,6 +337,23 @@ public:
};
+class sys_var_rand_seed1 :public sys_var
+{
+public:
+ sys_var_rand_seed1(const char *name_arg) :sys_var(name_arg) {}
+ bool update(THD *thd, set_var *var);
+ bool check_type(enum_var_type type) { return type == OPT_GLOBAL; }
+};
+
+class sys_var_rand_seed2 :public sys_var
+{
+public:
+ sys_var_rand_seed2(const char *name_arg) :sys_var(name_arg) {}
+ bool update(THD *thd, set_var *var);
+ bool check_type(enum_var_type type) { return type == OPT_GLOBAL; }
+};
+
+
class sys_var_thd_conv_charset :public sys_var_thd
{
public:
diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt
index c8ac594f00b..1b1f90abfb3 100644
--- a/sql/share/czech/errmsg.txt
+++ b/sql/share/czech/errmsg.txt
@@ -188,7 +188,7 @@
"Update tabulky bez WHERE s kl-Bíèem není v módu bezpeèných update dovoleno",
"Kl-Bíè '%-.64s' v tabulce '%-.64s' neexistuje",
"Nemohu otev-Bøít tabulku",
-"Handler tabulky nepodporuje check/repair",
+"Handler tabulky nepodporuje %s",
"Proveden-Bí tohoto pøíkazu není v transakci dovoleno",
"Chyba %d p-Bøi COMMIT",
"Chyba %d p-Bøi ROLLBACK",
@@ -252,4 +252,6 @@
"Subselect returns more than 1 field",
"Subselect returns more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
-"Help database is corrupt or does not exist", \ No newline at end of file
+"Help database is corrupt or does not exist",
+"Cyclic reference on subqueries",
+"Converting column '%s' from %s to %s"
diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt
index 5638260277e..65eb190b48b 100644
--- a/sql/share/danish/errmsg.txt
+++ b/sql/share/danish/errmsg.txt
@@ -182,7 +182,7 @@
"Du bruger sikker opdaterings modus ('safe update mode') og du forsøgte at opdatere en tabel uden en WHERE klausul, der gør brug af et KEY felt",
"Nøglen '%-.64s' eksisterer ikke i tabellen '%-.64s'",
"Kan ikke åbne tabellen",
-"Denne tabeltype understøtter ikke CHECK/REPAIR",
+"Denne tabeltype understøtter ikke %s",
"Du må ikke bruge denne kommando i en transaktion",
"Modtog fejl %d mens kommandoen COMMIT blev udført",
"Modtog fejl %d mens kommandoen ROLLBACK blev udført",
@@ -246,4 +246,6 @@
"Subselect returns more than 1 field",
"Subselect returns more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
-"Help database is corrupt or does not exist", \ No newline at end of file
+"Help database is corrupt or does not exist",
+"Cyclic reference on subqueries",
+"Converting column '%s' from %s to %s"
diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt
index acbda2829d0..965221dd83f 100644
--- a/sql/share/dutch/errmsg.txt
+++ b/sql/share/dutch/errmsg.txt
@@ -190,7 +190,7 @@
"U gebruikt 'safe update mode' en u probeerde een tabel te updaten zonder een WHERE met een KEY kolom",
"Zoeksleutel '%-.64s' bestaat niet in tabel '%-.64s'",
"Kan tabel niet openen",
-"De 'handler' voor de tabel ondersteund geen check/repair",
+"De 'handler' voor de tabel ondersteund geen %s",
"Het is u niet toegestaan dit commando uit te voeren binnen een transactie",
"Kreeg fout %d tijdens COMMIT",
"Kreeg fout %d tijdens ROLLBACK",
@@ -254,4 +254,6 @@
"Subselect returns more than 1 field",
"Subselect returns more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
-"Help database is corrupt or does not exist", \ No newline at end of file
+"Help database is corrupt or does not exist",
+"Cyclic reference on subqueries",
+"Converting column '%s' from %s to %s"
diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt
index 36d8831fd39..7472fe14365 100644
--- a/sql/share/english/errmsg.txt
+++ b/sql/share/english/errmsg.txt
@@ -179,7 +179,7 @@
"You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column",
"Key '%-.64s' doesn't exist in table '%-.64s'",
"Can't open table",
-"The handler for the table doesn't support check/repair",
+"The handler for the table doesn't support %s",
"You are not allowed to execute this command in a transaction",
"Got error %d during COMMIT",
"Got error %d during ROLLBACK",
@@ -243,4 +243,6 @@
"Subselect returns more than 1 field",
"Subselect returns more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
-"Help database is corrupt or does not exist", \ No newline at end of file
+"Help database is corrupt or does not exist",
+"Cyclic reference on subqueries",
+"Converting column '%s' from %s to %s"
diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt
index 96bd758cc6a..3f2745a8809 100644
--- a/sql/share/estonian/errmsg.txt
+++ b/sql/share/estonian/errmsg.txt
@@ -184,7 +184,7 @@
"Katse muuta tabelit turvalises rezhiimis ilma WHERE klauslita",
"Võti '%-.64s' ei eksisteeri tabelis '%-.64s'",
"Ei suuda avada tabelit",
-"Antud tabelitüüp ei toeta CHECK/REPAIR käske",
+"Antud tabelitüüp ei toeta %s käske",
"Seda käsku ei saa kasutada transaktsiooni sees",
"Viga %d käsu COMMIT täitmisel",
"Viga %d käsu ROLLBACK täitmisel",
@@ -248,4 +248,6 @@
"Subselect returns more than 1 field",
"Subselect returns more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
-"Help database is corrupt or does not exist", \ No newline at end of file
+"Help database is corrupt or does not exist",
+"Cyclic reference on subqueries",
+"Converting column '%s' from %s to %s"
diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt
index 932182a2c94..f1df0c0c2f2 100644
--- a/sql/share/french/errmsg.txt
+++ b/sql/share/french/errmsg.txt
@@ -179,7 +179,7 @@
"Vous êtes en mode 'safe update' et vous essayez de faire un UPDATE sans clause WHERE utilisant un index",
"L'index '%-.64s' n'existe pas sur la table '%-.64s'",
"Impossible d'ouvrir la table",
-"Ce type de table ne supporte pas les check/repair",
+"Ce type de table ne supporte pas les %s",
"Vous n'êtes pas autorisé à exécute cette commande dans une transaction",
"Erreur %d lors du COMMIT",
"Erreur %d lors du ROLLBACK",
@@ -243,4 +243,6 @@
"Subselect returns more than 1 field",
"Subselect returns more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
-"Help database is corrupt or does not exist", \ No newline at end of file
+"Help database is corrupt or does not exist",
+"Cyclic reference on subqueries",
+"Converting column '%s' from %s to %s"
diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt
index febd723df89..bd51de5a257 100644
--- a/sql/share/german/errmsg.txt
+++ b/sql/share/german/errmsg.txt
@@ -182,7 +182,7 @@
"Unter Verwendung des Sicheren Updatemodes wurde versucht eine Tabelle zu updaten ohne eine KEY-Spalte in der WHERE-Klausel",
"Schlüssel '%-.64s' existiert nicht in der Tabelle '%-.64s'",
"Kann Tabelle nicht öffnen",
-"Der Tabellen-Handler für diese Tabelle unterstützt kein check/repair",
+"Der Tabellen-Handler für diese Tabelle unterstützt kein %s",
"Keine Berechtigung dieses Kommando in einer Transaktion auszuführen",
"Fehler %d wärend COMMIT",
"Fehler %d wärend ROLLBACK",
@@ -246,4 +246,6 @@
"Subselect return more than 1 field",
"Subselect return more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
-"Help database is corrupt or does not exist", \ No newline at end of file
+"Help database is corrupt or does not exist",
+"Cyclic reference on subqueries",
+"Converting column '%s' from %s to %s"
diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt
index 9d9aa07af8d..915b4e9f64b 100644
--- a/sql/share/greek/errmsg.txt
+++ b/sql/share/greek/errmsg.txt
@@ -179,7 +179,7 @@
"You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column",
"Key '%-.64s' doesn't exist in table '%-.64s'",
"Can't open table",
-"The handler for the table doesn't support check/repair",
+"The handler for the table doesn't support %s",
"You are not allowed to execute this command in a transaction",
"Got error %d during COMMIT",
"Got error %d during ROLLBACK",
@@ -243,4 +243,6 @@
"Subselect returns more than 1 field",
"Subselect returns more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
-"Help database is corrupt or does not exist", \ No newline at end of file
+"Help database is corrupt or does not exist",
+"Cyclic reference on subqueries",
+"Converting column '%s' from %s to %s"
diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt
index d596c8f3433..aa8567dac87 100644
--- a/sql/share/hungarian/errmsg.txt
+++ b/sql/share/hungarian/errmsg.txt
@@ -181,7 +181,7 @@
"On a biztonsagos update modot hasznalja, es WHERE that uses a KEY column",
"A '%-.64s' kulcs nem letezik a '%-.64s' tablaban",
"Nem tudom megnyitni a tablat",
-"A tabla kezeloje (handler) nem tamogatja az ellenorzest/helyreallitast",
+"A tabla kezeloje (handler) nem tamogatja az %s",
"Az On szamara nem engedelyezett a parancs vegrehajtasa a tranzakcioban",
"%d hiba a COMMIT vegrehajtasa soran",
"%d hiba a ROLLBACK vegrehajtasa soran",
@@ -245,4 +245,6 @@
"Subselect returns more than 1 field",
"Subselect returns more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
-"Help database is corrupt or does not exist", \ No newline at end of file
+"Help database is corrupt or does not exist",
+"Cyclic reference on subqueries",
+"Converting column '%s' from %s to %s"
diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt
index d9ccf54d7ea..20430757590 100644
--- a/sql/share/italian/errmsg.txt
+++ b/sql/share/italian/errmsg.txt
@@ -179,7 +179,7 @@
"In modalita` 'safe update' si e` cercato di aggiornare una tabella senza clausola WHERE su una chiave",
"La chiave '%-.64s' non esiste nella tabella '%-.64s'",
"Impossibile aprire la tabella",
-"Il gestore per la tabella non supporta il controllo/riparazione",
+"Il gestore per la tabella non supporta il %s",
"Non puoi eseguire questo comando in una transazione",
"Rilevato l'errore %d durante il COMMIT",
"Rilevato l'errore %d durante il ROLLBACK",
@@ -243,4 +243,6 @@
"Subselect returns more than 1 field",
"Subselect returns more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
-"Help database is corrupt or does not exist", \ No newline at end of file
+"Help database is corrupt or does not exist",
+"Cyclic reference on subqueries",
+"Converting column '%s' from %s to %s"
diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt
index 22a53801efd..2f3c61c1fe1 100644
--- a/sql/share/japanese/errmsg.txt
+++ b/sql/share/japanese/errmsg.txt
@@ -181,7 +181,7 @@
"You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column",
"Key '%-.64s' doesn't exist in table '%-.64s'",
"Can't open table",
-"The handler for the table doesn't support check/repair",
+"The handler for the table doesn't support %s",
"You are not allowed to execute this command in a transaction",
"Got error %d during COMMIT",
"Got error %d during ROLLBACK",
@@ -245,4 +245,6 @@
"Subselect returns more than 1 field",
"Subselect returns more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
-"Help database is corrupt or does not exist", \ No newline at end of file
+"Help database is corrupt or does not exist",
+"Cyclic reference on subqueries",
+"Converting column '%s' from %s to %s"
diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt
index 27a8fdde027..277e53895c3 100644
--- a/sql/share/korean/errmsg.txt
+++ b/sql/share/korean/errmsg.txt
@@ -179,7 +179,7 @@
"You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column",
"Key '%-.64s' doesn't exist in table '%-.64s'",
"Can't open table",
-"The handler for the table doesn't support check/repair",
+"The handler for the table doesn't support %s",
"You are not allowed to execute this command in a transaction",
"Got error %d during COMMIT",
"Got error %d during ROLLBACK",
@@ -243,4 +243,6 @@
"Subselect returns more than 1 field",
"Subselect returns more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
-"Help database is corrupt or does not exist", \ No newline at end of file
+"Help database is corrupt or does not exist",
+"Cyclic reference on subqueries",
+"Converting column '%s' from %s to %s"
diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt
index 8e8b5aa7e61..4c3a12d6557 100644
--- a/sql/share/norwegian-ny/errmsg.txt
+++ b/sql/share/norwegian-ny/errmsg.txt
@@ -181,7 +181,7 @@
"You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column",
"Key '%-.64s' doesn't exist in table '%-.64s'",
"Can't open table",
-"The handler for the table doesn't support check/repair",
+"The handler for the table doesn't support %s",
"You are not allowed to execute this command in a transaction",
"Got error %d during COMMIT",
"Got error %d during ROLLBACK",
@@ -245,4 +245,6 @@
"Subselect returns more than 1 field",
"Subselect returns more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
-"Help database is corrupt or does not exist", \ No newline at end of file
+"Help database is corrupt or does not exist",
+"Cyclic reference on subqueries",
+"Converting column '%s' from %s to %s"
diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt
index 0f4650c186c..46bf84c409e 100644
--- a/sql/share/norwegian/errmsg.txt
+++ b/sql/share/norwegian/errmsg.txt
@@ -181,7 +181,7 @@
"You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column",
"Key '%-.64s' doesn't exist in table '%-.64s'",
"Can't open table",
-"The handler for the table doesn't support check/repair",
+"The handler for the table doesn't support %s",
"You are not allowed to execute this command in a transaction",
"Got error %d during COMMIT",
"Got error %d during ROLLBACK",
@@ -245,4 +245,6 @@
"Subselect returns more than 1 field",
"Subselect returns more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
-"Help database is corrupt or does not exist", \ No newline at end of file
+"Help database is corrupt or does not exist",
+"Cyclic reference on subqueries",
+"Converting column '%s' from %s to %s"
diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt
index 758e96e5ca3..e4d9832725d 100644
--- a/sql/share/polish/errmsg.txt
+++ b/sql/share/polish/errmsg.txt
@@ -183,7 +183,7 @@
"You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column",
"Key '%-.64s' doesn't exist in table '%-.64s'",
"Can't open table",
-"The handler for the table doesn't support check/repair",
+"The handler for the table doesn't support %s",
"You are not allowed to execute this command in a transaction",
"Got error %d during COMMIT",
"Got error %d during ROLLBACK",
@@ -247,4 +247,6 @@
"Subselect returns more than 1 field",
"Subselect returns more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
-"Help database is corrupt or does not exist", \ No newline at end of file
+"Help database is corrupt or does not exist",
+"Cyclic reference on subqueries",
+"Converting column '%s' from %s to %s"
diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt
index 21ebe5c39dc..1c5adc96560 100644
--- a/sql/share/portuguese/errmsg.txt
+++ b/sql/share/portuguese/errmsg.txt
@@ -179,7 +179,7 @@
"Você está usando modo de atualização seguro e tentou atualizar uma tabela sem uma cláusula WHERE que use uma coluna chave",
"Chave '%-.64s' não existe na tabela '%-.64s'",
"Não pode abrir a tabela",
-"O manipulador de tabela não suporta checagem/reparação (check/repair)",
+"O manipulador de tabela não suporta %s",
"Não lhe é permitido executar este comando em uma transação",
"Obteve erro %d durante COMMIT",
"Obteve erro %d durante ROLLBACK",
@@ -243,4 +243,6 @@
"Subselect returns more than 1 field",
"Subselect returns more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
-"Help database is corrupt or does not exist", \ No newline at end of file
+"Help database is corrupt or does not exist",
+"Cyclic reference on subqueries",
+"Converting column '%s' from %s to %s"
diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt
index c84049d6192..313af2e5f14 100644
--- a/sql/share/romanian/errmsg.txt
+++ b/sql/share/romanian/errmsg.txt
@@ -183,7 +183,7 @@
"You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column",
"Key '%-.64s' doesn't exist in table '%-.64s'",
"Can't open table",
-"The handler for the table doesn't support check/repair",
+"The handler for the table doesn't support %s",
"You are not allowed to execute this command in a transaction",
"Got error %d during COMMIT",
"Got error %d during ROLLBACK",
@@ -247,4 +247,6 @@
"Subselect returns more than 1 field",
"Subselect returns more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
-"Help database is corrupt or does not exist", \ No newline at end of file
+"Help database is corrupt or does not exist",
+"Cyclic reference on subqueries",
+"Converting column '%s' from %s to %s"
diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt
index 0ee79ce5811..3b636aacae7 100644
--- a/sql/share/russian/errmsg.txt
+++ b/sql/share/russian/errmsg.txt
@@ -182,7 +182,7 @@
"MySQL ÒÁÂÏÔÁÅÔ × ÒÅÖÉÍÅ ÚÁÝÉÔÙ ÏÔ ÄÕÒÁËÏ× (safe_mode) - ÎÅ ÍÏÇÕ UPDATE ÂÅÚ WHERE Ó ËÁËÉÍ-ÎÅÂÕÄØ KEY",
"éÎÄÅËÓ '%-.64s' ÎÅ ÎÁÊÄÅÎ × ÔÁÂÌÉÃÅ '%-.64s'",
"îÅ ÍÏÇÕ ÏÔËÒÙÔØ ÔÁÂÌÉÃÕ",
-"äÁÎÎÙÊ ÔÉÐ ÔÁÂÌÉà ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔ check/repair",
+"äÁÎÎÙÊ ÔÉÐ ÔÁÂÌÉà ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔ ËÏÍÁÎÄÕ %s",
"üÔÁ ËÏÍÁÎÄÁ ×ÎÕÔÒÉ ÔÒÁÎÚÁËÃÉÉ ÚÁÐÒÅÝÅÎÁ",
"ïÛÉÂËÁ %d ×Ï ×ÒÅÍÑ COMMIT",
"ïÛÉÂËÁ %d ×Ï ×ÒÅÍÑ ROLLBACK",
@@ -246,4 +246,6 @@
"ðÏÄÚÁÐÒÏÓ ×ÏÚ×ÒÁÝÁÅÔ ÂÏÌÅÅ ÏÄÎÏÇÏ ÐÏÌÑ",
"ðÏÄÚÁÐÒÏÓ ×ÏÚ×ÒÁÝÁÅÔ ÂÏÌÅÅ ÏÄÎÏÊ ÚÁÐÉÓÉ",
"Unknown prepared statement handler (%ld) given to %s",
-"Help database is corrupt or does not exist", \ No newline at end of file
+"Help database is corrupt or does not exist",
+"ãÉËÌÉÞÅÓËÁÑ ÓÓÙÌËÁ ÎÁ ÐÏÄÚÁÐÒÏÓ",
+"Converting column '%s' from %s to %s"
diff --git a/sql/share/serbian/errmsg.txt b/sql/share/serbian/errmsg.txt
index d120630b636..0ee69010aca 100644
--- a/sql/share/serbian/errmsg.txt
+++ b/sql/share/serbian/errmsg.txt
@@ -239,4 +239,6 @@
"Subselect returns more than 1 field",
"Subselect returns more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
-"Help database is corrupt or does not exist", \ No newline at end of file
+"Help database is corrupt or does not exist",
+"Cyclic reference on subqueries",
+"Converting column '%s' from %s to %s"
diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt
index eb9e2a240a0..9f610a84bd9 100644
--- a/sql/share/slovak/errmsg.txt
+++ b/sql/share/slovak/errmsg.txt
@@ -187,7 +187,7 @@
"You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column",
"Key '%-.64s' doesn't exist in table '%-.64s'",
"Can't open table",
-"The handler for the table doesn't support check/repair",
+"The handler for the table doesn't support %s",
"You are not allowed to execute this command in a transaction",
"Got error %d during COMMIT",
"Got error %d during ROLLBACK",
@@ -251,4 +251,6 @@
"Subselect returns more than 1 field",
"Subselect returns more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
-"Help database is corrupt or does not exist", \ No newline at end of file
+"Help database is corrupt or does not exist",
+"Cyclic reference on subqueries",
+"Converting column '%s' from %s to %s"
diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt
index 0b7de283481..ab4e3e93a25 100644
--- a/sql/share/spanish/errmsg.txt
+++ b/sql/share/spanish/errmsg.txt
@@ -180,7 +180,7 @@
"Tu estás usando modo de actualización segura y tentado actualizar una tabla sin un WHERE que usa una KEY columna",
"Clave '%-.64s' no existe en la tabla '%-.64s'",
"No puedo abrir tabla",
-"El manipulador de la tabla no permite soporte para check/repair",
+"El manipulador de la tabla no permite soporte para %s",
"No tienes el permiso para ejecutar este comando en una transición",
"Obtenido error %d durante COMMIT",
"Obtenido error %d durante ROLLBACK",
@@ -244,4 +244,6 @@
"Subselect returns more than 1 field",
"Subselect returns more than 1 record",
"Unknown prepared statement handler (%ld) given to %s",
-"Help database is corrupt or does not exist", \ No newline at end of file
+"Help database is corrupt or does not exist",
+"Cyclic reference on subqueries",
+"Converting column '%s' from %s to %s"
diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt
index 052cd1506d3..3d91522bf0f 100644
--- a/sql/share/swedish/errmsg.txt
+++ b/sql/share/swedish/errmsg.txt
@@ -179,7 +179,7 @@
"Du använder 'säker uppdaterings mod' och försökte uppdatera en table utan en WHERE sats som använder sig av en nyckel",
"Nyckel '%-.64s' finns inte in tabell '%-.64s'",
"Kan inte öppna tabellen",
-"Tabellhanteraren för denna tabell kan inte göra check/repair",
+"Tabellhanteraren för denna tabell kan inte göra %s",
"Du får inte utföra detta kommando i en transaktion",
"Fick fel %d vid COMMIT",
"Fick fel %d vid ROLLBACK",
@@ -229,18 +229,20 @@
"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 returns more than 1 field",
-"Subselect returns more than 1 record",
-"Unknown prepared statement handler (%ld) given to %s",
-"Help database is corrupt or does not exist", \ No newline at end of file
+"Variable '%-.64s' är en LOCAL variabel och kan inte ändrad med SET GLOBAL",
+"Variable '%-.64s' är en GLOBAL variabel och bör sättas med SET GLOBAL",
+"Variable '%-.64s' har inte ett DEFAULT värde",
+"Variable '%-.64s' kan inte be satt till '%-.64s'",
+"Fel typ av argument till variabel '%-.64s'",
+"Variabeln '%-.64s' kan endast sättas, inte läsas",
+"Fel använding/placering av '%s'",
+"Denna version av MySQL kan inte utföra '%s'",
+"Fick fatalt fel %d: '%-.128s' från master vid läsning av binär loggen",
+"Felaktig FOREIGN KEY definition för '%-.64s': %s",
+"Nyckel referensen och table referensen stämmer inte överens",
+"Subselect returnerade mer än 1 fält",
+"Subselect returnerade mer än 1 rad",
+"Okänd PREPARED STATEMENT id (%ld) var given till %s",
+"Hjälp databasen finns inte eller är skadad",
+"Syklisk referens i subselect",
+"Konvertar kolumn '%s' från %s till %s"
diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt
index 5cfad494a32..d16a8e678d1 100644
--- a/sql/share/ukrainian/errmsg.txt
+++ b/sql/share/ukrainian/errmsg.txt
@@ -184,7 +184,7 @@
"÷É Õ ÒÅÖÉͦ ÂÅÚÐÅÞÎÏÇÏ ÏÎÏ×ÌÅÎÎÑ ÔÁ ÎÁÍÁÇÁ¤ÔÅÓØ ÏÎÏ×ÉÔÉ ÔÁÂÌÉÃÀ ÂÅÚ ÏÐÅÒÁÔÏÒÁ WHERE, ÝÏ ×ÉËÏÒÉÓÔÏ×Õ¤ KEY ÓÔÏ×ÂÅÃØ",
"ëÌÀÞ '%-.64s' ÎÅ ¦ÓÎÕ¤ × ÔÁÂÌÉæ '%-.64s'",
"îÅ ÍÏÖÕ ×¦ÄËÒÉÔÉ ÔÁÂÌÉÃÀ",
-"÷ËÁÚ¦×ÎÉË ÔÁÂÌÉæ ΊЦÄÔÒÉÍÕÅ ÐÅÒÅצÒËÕ/צÄÎÏ×ÌÅÎÎÑ",
+"÷ËÁÚ¦×ÎÉË ÔÁÂÌÉæ ΊЦÄÔÒÉÍÕÅ %s",
"÷ÁÍ ÎÅ ÄÏÚ×ÏÌÅÎÏ ×ÉËÏÎÕ×ÁÔÉ ÃÀ ËÏÍÁÎÄÕ × ÔÒÁÎÚÁËæ§",
"ïÔÒÉÍÁÎÏ ÐÏÍÉÌËÕ %d Ð¦Ä ÞÁÓ COMMIT",
"ïÔÒÉÍÁÎÏ ÐÏÍÉÌËÕ %d Ð¦Ä ÞÁÓ ROLLBACK",
@@ -248,4 +248,6 @@
"ðiÄÚÁÐÉÔ ÐÏ×ÅÒÔÁ¤ ÂiÌØÛ ÎiÖ 1 ÓÔÏ×ÂÅÃØ",
"ðiÄÚÁÐÉÔ ÐÏ×ÅÒÔÁ¤ ÂiÌØÛ ÎiÖ 1 ÚÁÐÉÓ",
"Unknown prepared statement handler (%ld) given to %s",
-"Help database is corrupt or does not exist", \ No newline at end of file
+"Help database is corrupt or does not exist",
+"ãÉËÌiÞÎÅ ÐÏÓÉÌÁÎÎÑ ÎÁ ÐiÄÚÁÐÉÔ",
+"Converting column '%s' from %s to %s"
diff --git a/sql/slave.cc b/sql/slave.cc
index a07fd7ac7d1..f8acc592afa 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -608,7 +608,7 @@ void init_table_rule_hash(HASH* h, bool* h_inited)
{
hash_init(h, system_charset_info,TABLE_RULE_HASH_SIZE,0,0,
(hash_get_key) get_table_key,
- (void (*)(void*)) free_table_ent, 0);
+ (hash_free_key) free_table_ent, 0);
*h_inited = 1;
}
@@ -638,9 +638,10 @@ static TABLE_RULE_ENT* find_wild(DYNAMIC_ARRAY *a, const char* key, int len)
{
TABLE_RULE_ENT* e ;
get_dynamic(a, (gptr)&e, i);
- if (!wild_case_compare(system_charset_info, key, key_end,
+ if (!my_wildcmp(system_charset_info, key, key_end,
(const char*)e->db,
- (const char*)(e->db + e->key_len),'\\'))
+ (const char*)(e->db + e->key_len),
+ '\\',wild_one,wild_many))
return e;
}
@@ -1636,7 +1637,7 @@ bool flush_master_info(MASTER_INFO* mi)
DBUG_PRINT("enter",("master_pos: %ld", (long) mi->master_log_pos));
my_b_seek(file, 0L);
- my_b_printf(file, "%s\n%s\n%s\n%s\n%s\n%d\n%d\n%d\n",
+ my_b_printf(file, "%s\n%s\n%s\n%s\n%s\n%d\n%d\n",
mi->master_log_name, llstr(mi->master_log_pos, lbuf),
mi->host, mi->user,
mi->password, mi->port, mi->connect_retry
@@ -1944,7 +1945,7 @@ int check_expected_error(THD* thd, RELAY_LOG_INFO* rli, int expected_error)
"Slave: query '%s' partially completed on the master \
and was aborted. There is a chance that your master is inconsistent at this \
point. If you are sure that your master is ok, run this query manually on the\
- slave and then restart the slave with SET SQL_SLAVE_SKIP_COUNTER=1;\
+ slave and then restart the slave with SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1;\
SLAVE START;", thd->query);
rli->last_slave_errno = expected_error;
sql_print_error("%s",rli->last_slave_error);
@@ -2024,11 +2025,10 @@ This may also be a network problem, or just a bug in the master or slave code.\
}
/*****************************************************************************
-
Slave I/O Thread entry point
-
*****************************************************************************/
-pthread_handler_decl(handle_slave_io,arg)
+
+extern "C" pthread_handler_decl(handle_slave_io,arg)
{
THD *thd; // needs to be first for thread_stack
MYSQL *mysql;
@@ -2297,11 +2297,10 @@ err:
}
/*****************************************************************************
-
Slave SQL Thread entry point
-
*****************************************************************************/
-pthread_handler_decl(handle_slave_sql,arg)
+
+extern "C" pthread_handler_decl(handle_slave_sql,arg)
{
THD *thd; /* needs to be first for thread_stack */
char llbuff[22],llbuff1[22];
@@ -2477,7 +2476,7 @@ static int process_io_create_file(MASTER_INFO* mi, Create_file_log_event* cev)
in the loop
*/
{
- Append_block_log_event aev(thd,0,0);
+ Append_block_log_event aev(thd,0,0,0);
for (;;)
{
@@ -2490,7 +2489,7 @@ static int process_io_create_file(MASTER_INFO* mi, Create_file_log_event* cev)
if (unlikely(!num_bytes)) /* eof */
{
net_write_command(net, 0, "", 0, "", 0);/* 3.23 master wants it */
- Execute_load_log_event xev(thd);
+ Execute_load_log_event xev(thd,0);
xev.log_pos = mi->master_log_pos;
if (unlikely(mi->rli.relay_log.append(&xev)))
{
diff --git a/sql/slave.h b/sql/slave.h
index 74c89f9d755..2c750e415bc 100644
--- a/sql/slave.h
+++ b/sql/slave.h
@@ -436,8 +436,8 @@ int init_relay_log_pos(RELAY_LOG_INFO* rli,const char* log,ulonglong pos,
int purge_relay_logs(RELAY_LOG_INFO* rli, THD *thd, bool just_reset,
const char** errmsg);
-pthread_handler_decl(handle_slave_io,arg);
-pthread_handler_decl(handle_slave_sql,arg);
+extern "C" pthread_handler_decl(handle_slave_io,arg);
+extern "C" pthread_handler_decl(handle_slave_sql,arg);
extern bool volatile abort_loop;
extern MASTER_INFO main_mi, *active_mi; /* active_mi for multi-master */
extern volatile int active_mi_in_use;
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 55a364bdb2b..a5fb24b0796 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -121,6 +121,7 @@ static bool compare_hostname(const acl_host_and_ip *host, const char *hostname,
SYNOPSIS
acl_init()
+ thd Thread handler
dont_read_acl_tables Set to 1 if run with --skip-grant
RETURN VALUES
@@ -129,9 +130,9 @@ static bool compare_hostname(const acl_host_and_ip *host, const char *hostname,
*/
-my_bool acl_init(bool dont_read_acl_tables)
+my_bool acl_init(THD *org_thd, bool dont_read_acl_tables)
{
- THD *thd, *org_thd;
+ THD *thd;
TABLE_LIST tables[3];
TABLE *table;
READ_RECORD read_record_info;
@@ -142,7 +143,7 @@ my_bool acl_init(bool dont_read_acl_tables)
if (!acl_cache)
acl_cache=new hash_filo(ACL_CACHE_SIZE,0,0,
(hash_get_key) acl_entry_get_key,
- (void (*)(void*)) free);
+ (hash_free_key) free);
if (dont_read_acl_tables)
{
DBUG_RETURN(0); /* purecov: tested */
@@ -151,7 +152,6 @@ my_bool acl_init(bool dont_read_acl_tables)
/*
To be able to run this from boot, we allocate a temporary THD
*/
- org_thd=current_thd; // Save for restore
if (!(thd=new THD))
DBUG_RETURN(1); /* purecov: inspected */
thd->store_globals();
@@ -348,6 +348,11 @@ end:
delete thd;
if (org_thd)
org_thd->store_globals(); /* purecov: inspected */
+ else
+ {
+ /* Remember that we don't have a THD */
+ my_pthread_setspecific_ptr(THR_THD, 0);
+ }
DBUG_RETURN(return_val);
}
@@ -394,7 +399,7 @@ void acl_reload(THD *thd)
delete_dynamic(&acl_wild_hosts);
hash_free(&acl_check_hosts);
- if (acl_init(0))
+ if (acl_init(thd, 0))
{ // Error. Revert to old list
acl_free(); /* purecov: inspected */
acl_hosts=old_acl_hosts;
@@ -1157,7 +1162,7 @@ bool change_password(THD *thd, const char *host, const char *user,
acl_user->host.hostname ? acl_user->host.hostname : "",
new_password));
mysql_update_log.write(thd, buff, query_length);
- Query_log_event qinfo(thd, buff, query_length);
+ Query_log_event qinfo(thd, buff, query_length, 0);
mysql_bin_log.write(&qinfo);
DBUG_RETURN(0);
}
@@ -1420,8 +1425,13 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
strlen(thd->lex.x509_subject), system_charset_info);
break;
case SSL_TYPE_NOT_SPECIFIED:
- case SSL_TYPE_NONE: // Impossible
- break; // Nothing to do
+ break;
+ case SSL_TYPE_NONE:
+ table->field[24]->store("", 0, system_charset_info);
+ table->field[25]->store("", 0, system_charset_info);
+ table->field[26]->store("", 0, system_charset_info);
+ table->field[27]->store("", 0, system_charset_info);
+ break;
}
USER_RESOURCES mqh = thd->lex.mqh;
@@ -2342,9 +2352,9 @@ void grant_free(void)
/* Init grant array if possible */
-my_bool grant_init(void)
+my_bool grant_init(THD *org_thd)
{
- THD *thd, *org_thd;
+ THD *thd;
TABLE_LIST tables[2];
MYSQL_LOCK *lock;
my_bool return_val= 1;
@@ -2361,7 +2371,6 @@ my_bool grant_init(void)
if (!initialized)
DBUG_RETURN(0); /* purecov: tested */
- org_thd=current_thd;
if (!(thd=new THD))
DBUG_RETURN(1); /* purecov: deadcode */
thd->store_globals();
@@ -2419,13 +2428,18 @@ end:
delete thd;
if (org_thd)
org_thd->store_globals();
+ else
+ {
+ /* Remember that we don't have a THD */
+ my_pthread_setspecific_ptr(THR_THD, 0);
+ }
DBUG_RETURN(return_val);
}
/* Reload grant array if possible */
-void grant_reload(void)
+void grant_reload(THD *thd)
{
HASH old_hash_tables;bool old_grant_option;
MEM_ROOT old_mem;
@@ -2439,7 +2453,7 @@ void grant_reload(void)
old_grant_option = grant_option;
old_mem = memex;
- if (grant_init())
+ if (grant_init(thd))
{ // Error. Revert to old hash
grant_free(); /* purecov: deadcode */
hash_tables=old_hash_tables; /* purecov: deadcode */
diff --git a/sql/sql_acl.h b/sql/sql_acl.h
index a62026ef03c..66e7d0dad7c 100644
--- a/sql/sql_acl.h
+++ b/sql/sql_acl.h
@@ -81,7 +81,7 @@
/* prototypes */
-my_bool acl_init(bool dont_read_acl_tables);
+my_bool acl_init(THD *thd, bool dont_read_acl_tables);
void acl_reload(THD *thd);
void acl_free(bool end=0);
ulong acl_get(const char *host, const char *ip, const char *bin_ip,
@@ -98,9 +98,9 @@ int mysql_grant(THD *thd, const char *db, List <LEX_USER> &user_list,
int mysql_table_grant(THD *thd, TABLE_LIST *table, List <LEX_USER> &user_list,
List <LEX_COLUMN> &column_list, ulong rights,
bool revoke);
-my_bool grant_init(void);
+my_bool grant_init(THD *thd);
void grant_free(void);
-void grant_reload(void);
+void grant_reload(THD *thd);
bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
uint show_command=0, bool dont_print_error=0);
bool check_grant_column (THD *thd,TABLE *table, const char *name, uint length,
diff --git a/sql/sql_analyse.cc b/sql/sql_analyse.cc
index 5c735ab35d5..f98eb0e0b26 100644
--- a/sql/sql_analyse.cc
+++ b/sql/sql_analyse.cc
@@ -677,7 +677,7 @@ bool analyse::end_of_records()
case FIELD_TYPE_DECIMAL:
ans.append("DECIMAL", 7);
// if item is FIELD_ITEM, it _must_be_ Field_num in this case
- if (((Field_num*) (*f)->item)->zerofill)
+ if (((Field_num*) ((Item_field*) (*f)->item)->field)->zerofill)
ans.append(" ZEROFILL");
break;
default:
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 77253d49ed0..59310fb00de 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -39,8 +39,8 @@ static key_map get_key_map_from_key_list(TABLE *table,
List<String> *index_list);
-static byte *cache_key(const byte *record,uint *length,
- my_bool not_used __attribute__((unused)))
+extern "C" byte *table_cache_key(const byte *record,uint *length,
+ my_bool not_used __attribute__((unused)))
{
TABLE *entry=(TABLE*) record;
*length=entry->key_length;
@@ -50,8 +50,8 @@ static byte *cache_key(const byte *record,uint *length,
void table_cache_init(void)
{
VOID(hash_init(&open_cache,system_charset_info,
- table_cache_size+16,0,0,cache_key,
- (void (*)(void*)) free_cache_entry,0));
+ table_cache_size+16,0,0,table_cache_key,
+ (hash_free_key) free_cache_entry,0));
mysql_rm_tmp_tables();
}
@@ -536,14 +536,14 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh,
if (!found)
if_wait_for_refresh=0; // Nothing to wait for
}
+ if (!tables)
+ kill_delayed_threads();
if (if_wait_for_refresh)
{
/*
If there is any table that has a lower refresh_version, wait until
this is closed (or this thread is killed) before returning
*/
- if (!tables)
- kill_delayed_threads();
thd->mysys_var->current_mutex= &LOCK_open;
thd->mysys_var->current_cond= &COND_refresh;
thd->proc_info="Flushing tables";
@@ -699,26 +699,20 @@ void close_temporary_tables(THD *thd)
{
TABLE *table,*next;
char *query, *end;
- const uint init_query_buf_size = 11; // "drop table "
uint query_buf_size;
bool found_user_tables = 0;
+ if (!thd->temporary_tables)
+ return;
+
LINT_INIT(end);
- query_buf_size = init_query_buf_size;
+ query_buf_size= 50; // Enough for DROP ... TABLE
for (table=thd->temporary_tables ; table ; table=table->next)
- {
query_buf_size += table->key_length;
- }
-
- if (query_buf_size == init_query_buf_size)
- return; // no tables to close
if ((query = alloc_root(&thd->mem_root, query_buf_size)))
- {
- memcpy(query, "drop table ", init_query_buf_size);
- end = query + init_query_buf_size;
- }
+ end=strmov(query, "DROP /*!40005 TEMPORARY */ TABLE ");
for (table=thd->temporary_tables ; table ; table=next)
{
@@ -727,12 +721,14 @@ void close_temporary_tables(THD *thd)
// skip temporary tables not created directly by the user
if (table->real_name[0] != '#')
{
- end = strxmov(end,table->table_cache_key,".",
- table->real_name,",", NullS);
- // here we assume table_cache_key always starts
- // with \0 terminated db name
+ /*
+ Here we assume table_cache_key always starts
+ with \0 terminated db name
+ */
found_user_tables = 1;
}
+ end = strxmov(end,table->table_cache_key,".",
+ table->real_name,",", NullS);
}
next=table->next;
close_temporary(table);
@@ -740,7 +736,7 @@ void close_temporary_tables(THD *thd)
if (query && found_user_tables && mysql_bin_log.is_open())
{
/* The -1 is to remove last ',' */
- Query_log_event qinfo(thd, query, (ulong)(end-query)-1);
+ Query_log_event qinfo(thd, query, (ulong)(end-query)-1, 0);
qinfo.error_code=0;
mysql_bin_log.write(&qinfo);
}
@@ -1435,7 +1431,7 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db,
int error;
DBUG_ENTER("open_unireg_entry");
- (void) sprintf(path,"%s/%s/%s",mysql_data_home,db,name);
+ strxmov(path, mysql_data_home, "/", db, "/", name, NullS);
if (openfrm(path,alias,
(uint) (HA_OPEN_KEYFILE | HA_OPEN_RNDFILE | HA_GET_INDEX |
HA_TRY_READ_ONLY),
@@ -1564,6 +1560,61 @@ int open_tables(THD *thd,TABLE_LIST *start)
}
+/*
+ Check that lock is ok for tables; Call start stmt if ok
+
+ SYNOPSIS
+ check_lock_and_start_stmt()
+ thd Thread handle
+ table_list Table to check
+ lock_type Lock used for table
+
+ RETURN VALUES
+ 0 ok
+ 1 error
+*/
+
+static bool check_lock_and_start_stmt(THD *thd, TABLE *table,
+ thr_lock_type lock_type)
+{
+ int error;
+ DBUG_ENTER("check_lock_and_start_stmt");
+
+ if ((int) lock_type >= (int) TL_WRITE_ALLOW_READ &&
+ (int) table->reginfo.lock_type < (int) TL_WRITE_ALLOW_READ)
+ {
+ my_printf_error(ER_TABLE_NOT_LOCKED_FOR_WRITE,
+ ER(ER_TABLE_NOT_LOCKED_FOR_WRITE),
+ MYF(0),table->table_name);
+ DBUG_RETURN(1);
+ }
+ if ((error=table->file->start_stmt(thd)))
+ {
+ table->file->print_error(error,MYF(0));
+ DBUG_RETURN(1);
+ }
+ DBUG_RETURN(0);
+}
+
+
+/*
+ Open and lock one table
+
+ SYNOPSIS
+ open_ltable()
+ thd Thread handler
+ table_list Table to open is first table in this list
+ lock_type Lock to use for open
+
+ RETURN VALUES
+ table Opened table
+ 0 Error
+
+ If ok, the following are also set:
+ table_list->lock_type lock_type
+ table_list->table table
+*/
+
TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type)
{
TABLE *table;
@@ -1576,8 +1627,6 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type)
&refresh)) && refresh) ;
if (table)
{
- int error;
-
#if defined( __WIN__) || defined(OS2)
/* Win32 can't drop a file that is open */
if (lock_type == TL_WRITE_ALLOW_READ)
@@ -1585,39 +1634,29 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type)
lock_type= TL_WRITE;
}
#endif /* __WIN__ || OS2 */
-
- table_list->table=table;
+ table_list->lock_type= lock_type;
+ table_list->table= table;
table->grant= table_list->grant;
if (thd->locked_tables)
{
- thd->proc_info=0;
- if ((int) lock_type >= (int) TL_WRITE_ALLOW_READ &&
- (int) table->reginfo.lock_type < (int) TL_WRITE_ALLOW_READ)
- {
- my_printf_error(ER_TABLE_NOT_LOCKED_FOR_WRITE,
- ER(ER_TABLE_NOT_LOCKED_FOR_WRITE),
- MYF(0),table_list->alias);
- table=0;
- }
- else if ((error=table->file->start_stmt(thd)))
- {
- table->file->print_error(error,MYF(0));
- table=0;
- }
- thd->proc_info=0;
- DBUG_RETURN(table);
+ if (check_lock_and_start_stmt(thd, table, lock_type))
+ table= 0;
+ }
+ else
+ {
+ if ((table->reginfo.lock_type= lock_type) != TL_UNLOCK)
+ if (!(thd->lock=mysql_lock_tables(thd,&table_list->table,1)))
+ table= 0;
}
- if ((table->reginfo.lock_type=lock_type) != TL_UNLOCK)
- if (!(thd->lock=mysql_lock_tables(thd,&table_list->table,1)))
- DBUG_RETURN(0);
}
thd->proc_info=0;
DBUG_RETURN(table);
}
+
/*
-** Open all tables in list and locks them for read.
-** The lock will automaticly be freed by the close_thread_tables
+ Open all tables in list and locks them for read.
+ The lock will automaticly be freed by close_thread_tables()
*/
int open_and_lock_tables(THD *thd,TABLE_LIST *tables)
@@ -1627,10 +1666,27 @@ int open_and_lock_tables(THD *thd,TABLE_LIST *tables)
return 0;
}
+
+/*
+ Lock all tables in list
+
+ SYNOPSIS
+ lock_tables()
+ thd Thread handler
+ tables Tables to lock
+
+ RETURN VALUES
+ 0 ok
+ -1 Error
+*/
+
int lock_tables(THD *thd,TABLE_LIST *tables)
{
TABLE_LIST *table;
- if (tables && !thd->locked_tables)
+ if (!tables)
+ return 0;
+
+ if (!thd->locked_tables)
{
uint count=0;
for (table = tables ; table ; table=table->next)
@@ -1647,10 +1703,9 @@ int lock_tables(THD *thd,TABLE_LIST *tables)
{
for (table = tables ; table ; table=table->next)
{
- int error;
- if ((error=table->table->file->start_stmt(thd)))
+ if (check_lock_and_start_stmt(thd, table->table, table->lock_type))
{
- table->table->file->print_error(error,MYF(0));
+ ha_rollback_stmt(thd);
return -1;
}
}
@@ -1658,10 +1713,11 @@ int lock_tables(THD *thd,TABLE_LIST *tables)
return 0;
}
+
/*
-** Open a single table without table caching and don't set it in open_list
-** Used by alter_table to open a temporary table and when creating
-** a temporary table with CREATE TEMPORARY ...
+ Open a single table without table caching and don't set it in open_list
+ Used by alter_table to open a temporary table and when creating
+ a temporary table with CREATE TEMPORARY ...
*/
TABLE *open_temporary_table(THD *thd, const char *path, const char *db,
@@ -1670,11 +1726,13 @@ TABLE *open_temporary_table(THD *thd, const char *path, const char *db,
TABLE *tmp_table;
DBUG_ENTER("open_temporary_table");
- // the extra size in my_malloc() is for table_cache_key
- // 4 bytes for master thread id if we are in the slave
- // 1 byte to terminate db
- // 1 byte to terminate table_name
- // total of 6 extra bytes in my_malloc in addition to table/db stuff
+ /*
+ The extra size in my_malloc() is for table_cache_key
+ 4 bytes for master thread id if we are in the slave
+ 1 byte to terminate db
+ 1 byte to terminate table_name
+ total of 6 extra bytes in my_malloc in addition to table/db stuff
+ */
if (!(tmp_table=(TABLE*) my_malloc(sizeof(*tmp_table)+(uint) strlen(db)+
(uint) strlen(table_name)+6,
MYF(MY_WME))))
@@ -1748,7 +1806,9 @@ Field *find_field_in_table(THD *thd,TABLE *table,const char *name,uint length,
}
else
{
- Field **ptr=table->field;
+ Field **ptr;
+ if (!(ptr=table->field))
+ return (Field *)0;
while ((field = *ptr++))
{
if (!my_strcasecmp(system_charset_info, field->field_name, name))
@@ -2069,6 +2129,7 @@ bool setup_tables(TABLE_LIST *tables)
DBUG_RETURN(1);
table->keys_in_use_for_query &= ~map;
}
+ table->used_keys &= table->keys_in_use_for_query;
if (table_list->shared)
{
/* Clear query_id that may have been set by previous select */
@@ -2200,6 +2261,7 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
Item_cond_and *cond_and=new Item_cond_and();
if (!cond_and) // If not out of memory
DBUG_RETURN(1);
+ cond_and->top_level_item();
uint i,j;
for (i=0 ; i < t1->fields ; i++)
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index 2f236da2aa3..ef584f4364e 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -473,33 +473,6 @@ byte *query_cache_table_get_key(const byte *record, uint *length,
Query_cache_query methods
*****************************************************************************/
-void Query_cache_query::init_n_lock()
-{
- DBUG_ENTER("Query_cache_query::init_n_lock");
- res=0; wri = 0; len = 0;
- my_rwlock_init(&lock, NULL);
- lock_writing();
- DBUG_PRINT("qcache", ("inited & locked query for block 0x%lx",
- ((byte*) this)-ALIGN_SIZE(sizeof(Query_cache_block))));
- DBUG_VOID_RETURN;
-}
-
-
-void Query_cache_query::unlock_n_destroy()
-{
- DBUG_ENTER("Query_cache_query::unlock_n_destroy");
- DBUG_PRINT("qcache", ("destroyed & unlocked query for block 0x%lx",
- ((byte*)this)-ALIGN_SIZE(sizeof(Query_cache_block))));
- /*
- The following call is not needed on system where one can destroy an
- active semaphore
- */
- this->unlock_writing();
- rwlock_destroy(&lock);
- DBUG_VOID_RETURN;
-}
-
-
/*
Following methods work for block read/write locking only in this
particular case and in interaction with structure_guard_mutex.
@@ -551,6 +524,34 @@ inline void Query_cache_query::unlock_reading()
RW_UNLOCK(&lock);
}
+
+void Query_cache_query::init_n_lock()
+{
+ DBUG_ENTER("Query_cache_query::init_n_lock");
+ res=0; wri = 0; len = 0;
+ my_rwlock_init(&lock, NULL);
+ lock_writing();
+ DBUG_PRINT("qcache", ("inited & locked query for block 0x%lx",
+ ((byte*) this)-ALIGN_SIZE(sizeof(Query_cache_block))));
+ DBUG_VOID_RETURN;
+}
+
+
+void Query_cache_query::unlock_n_destroy()
+{
+ DBUG_ENTER("Query_cache_query::unlock_n_destroy");
+ DBUG_PRINT("qcache", ("destroyed & unlocked query for block 0x%lx",
+ ((byte*)this)-ALIGN_SIZE(sizeof(Query_cache_block))));
+ /*
+ The following call is not needed on system where one can destroy an
+ active semaphore
+ */
+ this->unlock_writing();
+ rwlock_destroy(&lock);
+ DBUG_VOID_RETURN;
+}
+
+
extern "C"
{
byte *query_cache_query_get_key(const byte *record, uint *length,
@@ -714,19 +715,19 @@ void query_cache_invalidate_by_MyISAM_filename(const char *filename)
Query_cache methods
*****************************************************************************/
-Query_cache::Query_cache(ulong query_cache_limit,
- ulong min_allocation_unit,
- ulong min_result_data_size,
- uint def_query_hash_size ,
- uint def_table_hash_size)
+Query_cache::Query_cache(ulong query_cache_limit_arg,
+ ulong min_allocation_unit_arg,
+ ulong min_result_data_size_arg,
+ uint def_query_hash_size_arg,
+ uint def_table_hash_size_arg)
:query_cache_size(0),
- query_cache_limit(query_cache_limit),
+ query_cache_limit(query_cache_limit_arg),
queries_in_cache(0), hits(0), inserts(0), refused(0),
- total_blocks(0),
- min_allocation_unit(ALIGN_SIZE(min_allocation_unit)),
- min_result_data_size(ALIGN_SIZE(min_result_data_size)),
- def_query_hash_size(ALIGN_SIZE(def_query_hash_size)),
- def_table_hash_size(ALIGN_SIZE(def_table_hash_size)),
+ total_blocks(0), lowmem_prunes(0),
+ min_allocation_unit(ALIGN_SIZE(min_allocation_unit_arg)),
+ min_result_data_size(ALIGN_SIZE(min_result_data_size_arg)),
+ def_query_hash_size(ALIGN_SIZE(def_query_hash_size_arg)),
+ def_table_hash_size(ALIGN_SIZE(def_table_hash_size_arg)),
initialized(0)
{
ulong min_needed= (ALIGN_SIZE(sizeof(Query_cache_block)) +
@@ -751,13 +752,13 @@ ulong Query_cache::resize(ulong query_cache_size_arg)
void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used)
{
- TABLE_COUNTER_TYPE tables;
+ TABLE_COUNTER_TYPE local_tables;
ulong tot_length;
DBUG_ENTER("Query_cache::store_query");
if (query_cache_size == 0)
DBUG_VOID_RETURN;
- if ((tables = is_cacheable(thd, thd->query_length,
+ if ((local_tables = is_cacheable(thd, thd->query_length,
thd->query, &thd->lex, tables_used)))
{
NET *net = &thd->net;
@@ -803,7 +804,7 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used)
Query_cache_block *query_block;
query_block= write_block_data(tot_length, (gptr) thd->query,
ALIGN_SIZE(sizeof(Query_cache_query)),
- Query_cache_block::QUERY, tables, 1);
+ Query_cache_block::QUERY, local_tables, 1);
if (query_block != 0)
{
DBUG_PRINT("qcache", ("query block 0x%lx allocated, %lu",
@@ -820,7 +821,7 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used)
STRUCT_UNLOCK(&structure_guard_mutex);
goto end;
}
- if (!register_all_tables(query_block, tables_used, tables))
+ if (!register_all_tables(query_block, tables_used, local_tables))
{
refused++;
DBUG_PRINT("warning", ("tables list including failed"));
@@ -1527,6 +1528,7 @@ my_bool Query_cache::free_old_query()
if (query_block != 0)
{
free_query(query_block);
+ lowmem_prunes++;
DBUG_RETURN(0);
}
}
@@ -1796,7 +1798,7 @@ inline ulong Query_cache::get_min_append_result_data_size()
my_bool Query_cache::allocate_data_chain(Query_cache_block **result_block,
ulong data_len,
Query_cache_block *query_block,
- my_bool first_block)
+ my_bool first_block_arg)
{
ulong all_headers_len = (ALIGN_SIZE(sizeof(Query_cache_block)) +
ALIGN_SIZE(sizeof(Query_cache_result)));
@@ -1806,7 +1808,7 @@ my_bool Query_cache::allocate_data_chain(Query_cache_block **result_block,
DBUG_PRINT("qcache", ("data_len %lu, all_headers_len %lu",
data_len, all_headers_len));
- ulong min_size = (first_block ?
+ ulong min_size = (first_block_arg ?
get_min_first_result_data_size():
get_min_append_result_data_size());
*result_block = allocate_block(max(min_size, align_len),
@@ -1833,7 +1835,7 @@ my_bool Query_cache::allocate_data_chain(Query_cache_block **result_block,
Query_cache_block *next_block;
if ((success = allocate_data_chain(&next_block,
len - new_block->length,
- query_block, first_block)))
+ query_block, first_block_arg)))
double_linked_list_join(new_block, next_block);
}
if (success)
@@ -1902,14 +1904,23 @@ void Query_cache::invalidate_table(Query_cache_block *table_block)
}
}
+/*
+ Store all used tables
+
+ SYNOPSIS
+ register_all_tables()
+ block Store tables in this block
+ tables_used List if used tables
+ tables_arg Not used ?
+*/
my_bool Query_cache::register_all_tables(Query_cache_block *block,
TABLE_LIST *tables_used,
- TABLE_COUNTER_TYPE tables)
+ TABLE_COUNTER_TYPE tables_arg)
{
TABLE_COUNTER_TYPE n;
DBUG_PRINT("qcache", ("register tables block 0x%lx, n %d, header %x",
- (ulong) block, (int) tables,
+ (ulong) block, (int) tables_arg,
(int) ALIGN_SIZE(sizeof(Query_cache_block))));
Query_cache_block_table *block_table = block->table(0);
@@ -2201,28 +2212,28 @@ void Query_cache::split_block(Query_cache_block *block, ulong len)
Query_cache_block *
-Query_cache::join_free_blocks(Query_cache_block *first_block,
+Query_cache::join_free_blocks(Query_cache_block *first_block_arg,
Query_cache_block *block_in_list)
{
Query_cache_block *second_block;
DBUG_ENTER("Query_cache::join_free_blocks");
DBUG_PRINT("qcache",
("join first 0x%lx, pnext 0x%lx, in list 0x%lx",
- (ulong) first_block, (ulong) first_block->pnext,
+ (ulong) first_block_arg, (ulong) first_block_arg->pnext,
(ulong) block_in_list));
exclude_from_free_memory_list(block_in_list);
- second_block = first_block->pnext;
+ second_block = first_block_arg->pnext;
// May be was not free block
second_block->used=0;
second_block->destroy();
total_blocks--;
- first_block->length += second_block->length;
- first_block->pnext = second_block->pnext;
- second_block->pnext->pprev = first_block;
+ first_block_arg->length += second_block->length;
+ first_block_arg->pnext = second_block->pnext;
+ second_block->pnext->pprev = first_block_arg;
- DBUG_RETURN(first_block);
+ DBUG_RETURN(first_block_arg);
}
@@ -2439,7 +2450,7 @@ TABLE_COUNTER_TYPE Query_cache::is_cacheable(THD *thd, uint32 query_len,
char *query,
LEX *lex, TABLE_LIST *tables_used)
{
- TABLE_COUNTER_TYPE tables = 0;
+ TABLE_COUNTER_TYPE table_count = 0;
DBUG_ENTER("Query_cache::is_cacheable");
if (lex->sql_command == SQLCOM_SELECT &&
@@ -2456,7 +2467,7 @@ TABLE_COUNTER_TYPE Query_cache::is_cacheable(THD *thd, uint32 query_len,
for (; tables_used; tables_used= tables_used->next)
{
- tables++;
+ table_count++;
DBUG_PRINT("qcache", ("table %s, db %s, type %u",
tables_used->real_name,
tables_used->db, tables_used->table->db_type));
@@ -2480,7 +2491,7 @@ TABLE_COUNTER_TYPE Query_cache::is_cacheable(THD *thd, uint32 query_len,
{
ha_myisammrg *handler = (ha_myisammrg *)tables_used->table->file;
MYRG_INFO *file = handler->myrg_info();
- tables+= (file->end_table - file->open_tables);
+ table_count+= (file->end_table - file->open_tables);
}
}
@@ -2490,8 +2501,8 @@ TABLE_COUNTER_TYPE Query_cache::is_cacheable(THD *thd, uint32 query_len,
DBUG_PRINT("qcache", ("not in autocommin mode"));
DBUG_RETURN(0);
}
- DBUG_PRINT("qcache", ("select is using %d tables", tables));
- DBUG_RETURN(tables);
+ DBUG_PRINT("qcache", ("select is using %d tables", table_count));
+ DBUG_RETURN(table_count);
}
DBUG_PRINT("qcache",
diff --git a/sql/sql_cache.h b/sql/sql_cache.h
index f19e6630da5..b15df28f54b 100644
--- a/sql/sql_cache.h
+++ b/sql/sql_cache.h
@@ -178,7 +178,7 @@ extern "C"
my_bool not_used);
}
void query_cache_insert(NET *thd, const char *packet, ulong length);
-void query_cache_invalidate_by_MyISAM_filename(const char* filename);
+extern "C" void query_cache_invalidate_by_MyISAM_filename(const char* filename);
struct Query_cache_memory_bin
@@ -219,7 +219,7 @@ public:
ulong query_cache_size, query_cache_limit;
/* statistics */
ulong free_memory, queries_in_cache, hits, inserts, refused,
- free_memory_blocks, total_blocks;
+ free_memory_blocks, total_blocks, lowmem_prunes;
protected:
/*
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 887ee262777..4141211ad92 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -59,14 +59,14 @@ template class List_iterator<Alter_column>;
** User variables
****************************************************************************/
-static byte* get_var_key(user_var_entry *entry, uint *length,
- my_bool not_used __attribute__((unused)))
+extern "C" byte *get_var_key(user_var_entry *entry, uint *length,
+ my_bool not_used __attribute__((unused)))
{
*length=(uint) entry->name.length;
return (byte*) entry->name.str;
}
-static void free_var(user_var_entry *entry)
+extern "C" void free_user_var(user_var_entry *entry)
{
char *pos= (char*) entry+ALIGN_SIZE(sizeof(*entry));
if (entry->value && entry->value != pos)
@@ -88,9 +88,6 @@ THD::THD():user_time(0), fatal_error(0),
host_or_ip="unknown ip";
locked=killed=count_cuted_fields=some_tables_deleted=no_errors=password=
query_start_used=safe_to_cache_query=prepare_command=0;
- pthread_mutex_lock(&LOCK_global_system_variables);
- variables= global_system_variables;
- pthread_mutex_unlock(&LOCK_global_system_variables);
db_length=query_length=col_access=0;
query_error=0;
next_insert_id=last_insert_id=0;
@@ -107,6 +104,7 @@ THD::THD():user_time(0), fatal_error(0),
slave_proxy_id = 0;
file_id = 0;
cond_count=0;
+ warn_id= 0;
db_charset=default_charset_info;
thd_charset=default_charset_info;
mysys_var=0;
@@ -132,19 +130,12 @@ THD::THD():user_time(0), fatal_error(0),
server_id = ::server_id;
slave_net = 0;
log_pos = 0;
- server_status= SERVER_STATUS_AUTOCOMMIT;
- update_lock_default= (variables.low_priority_updates ?
- TL_WRITE_LOW_PRIORITY :
- TL_WRITE);
- options= thd_startup_options;
- sql_mode=(uint) opt_sql_mode;
- open_options=ha_open_options;
- session_tx_isolation= (enum_tx_isolation) variables.tx_isolation;
command=COM_CONNECT;
set_query_id=1;
db_access=NO_ACCESS;
version=refresh_version; // For boot
+ init();
/* Initialize sub structures */
bzero((char*) &mem_root,sizeof(mem_root));
bzero((char*) &transaction.mem_root,sizeof(transaction.mem_root));
@@ -156,7 +147,7 @@ THD::THD():user_time(0), fatal_error(0),
user_connect=(USER_CONN *)0;
hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0,
(hash_get_key) get_var_key,
- (void (*)(void*)) free_var,0);
+ (hash_free_key) free_user_var,0);
/* Prepared statements */
last_prepared_stmt= 0;
@@ -189,6 +180,48 @@ THD::THD():user_time(0), fatal_error(0),
}
}
+
+/*
+ Init common variables that has to be reset on start and on change_user
+*/
+
+void THD::init(void)
+{
+ server_status= SERVER_STATUS_AUTOCOMMIT;
+ update_lock_default= (variables.low_priority_updates ?
+ TL_WRITE_LOW_PRIORITY :
+ TL_WRITE);
+ options= thd_startup_options;
+ sql_mode=(uint) opt_sql_mode;
+ open_options=ha_open_options;
+ pthread_mutex_lock(&LOCK_global_system_variables);
+ variables= global_system_variables;
+ pthread_mutex_unlock(&LOCK_global_system_variables);
+ session_tx_isolation= (enum_tx_isolation) variables.tx_isolation;
+}
+
+/*
+ Do what's needed when one invokes change user
+
+ SYNOPSIS
+ change_user()
+
+ IMPLEMENTATION
+ Reset all resources that are connection specific
+*/
+
+
+void THD::change_user(void)
+{
+ cleanup();
+ cleanup_done= 0;
+ init();
+ hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0,
+ (hash_get_key) get_var_key,
+ (hash_free_key) free_user_var, 0);
+}
+
+
/* Do operations that may take a long time */
void THD::cleanup(void)
@@ -206,17 +239,21 @@ void THD::cleanup(void)
close_thread_tables(this);
}
close_temporary_tables(this);
-#ifdef USING_TRANSACTIONS
- if (opt_using_transactions)
+ hash_free(&user_vars);
+ if (global_read_lock)
+ unlock_global_read_lock(this);
+ if (ull)
{
- close_cached_file(&transaction.trans_log);
- ha_close_connection(this);
+ pthread_mutex_lock(&LOCK_user_locks);
+ item_user_lock_release(ull);
+ pthread_mutex_unlock(&LOCK_user_locks);
+ ull= 0;
}
-#endif
cleanup_done=1;
DBUG_VOID_RETURN;
}
+
THD::~THD()
{
THD_CHECK_SENTRY(this);
@@ -233,15 +270,13 @@ THD::~THD()
}
if (!cleanup_done)
cleanup();
- if (global_read_lock)
- unlock_global_read_lock(this);
- if (ull)
+#ifdef USING_TRANSACTIONS
+ if (opt_using_transactions)
{
- pthread_mutex_lock(&LOCK_user_locks);
- item_user_lock_release(ull);
- pthread_mutex_unlock(&LOCK_user_locks);
+ close_cached_file(&transaction.trans_log);
+ ha_close_connection(this);
}
- hash_free(&user_vars);
+#endif
DBUG_PRINT("info", ("freeing host"));
if (host != localhost) // If not pointer to constant
@@ -337,20 +372,21 @@ void THD::add_changed_table(TABLE *table)
DBUG_VOID_RETURN;
}
+
void THD::add_changed_table(const char *key, long key_length)
{
DBUG_ENTER("THD::add_changed_table(key)");
- CHANGED_TABLE_LIST** prev = &transaction.changed_tables;
- CHANGED_TABLE_LIST* curr = transaction.changed_tables;
+ CHANGED_TABLE_LIST **prev_changed = &transaction.changed_tables;
+ CHANGED_TABLE_LIST *curr = transaction.changed_tables;
- for (; curr; prev = &(curr->next), curr = curr->next)
+ for (; curr; prev_changed = &(curr->next), curr = curr->next)
{
int cmp = (long)curr->key_length - (long)key_length;
if (cmp < 0)
{
- list_include(prev, curr, changed_table_dup(key, key_length));
+ list_include(prev_changed, curr, changed_table_dup(key, key_length));
DBUG_PRINT("info",
- ("key_length %u %u", key_length, (*prev)->key_length));
+ ("key_length %u %u", key_length, (*prev_changed)->key_length));
DBUG_VOID_RETURN;
}
else if (cmp == 0)
@@ -358,10 +394,10 @@ void THD::add_changed_table(const char *key, long key_length)
cmp = memcmp(curr->key, key, curr->key_length);
if (cmp < 0)
{
- list_include(prev, curr, changed_table_dup(key, key_length));
+ list_include(prev_changed, curr, changed_table_dup(key, key_length));
DBUG_PRINT("info",
("key_length %u %u", key_length,
- (*prev)->key_length));
+ (*prev_changed)->key_length));
DBUG_VOID_RETURN;
}
else if (cmp == 0)
@@ -371,9 +407,9 @@ void THD::add_changed_table(const char *key, long key_length)
}
}
}
- *prev = changed_table_dup(key, key_length);
+ *prev_changed = changed_table_dup(key, key_length);
DBUG_PRINT("info", ("key_length %u %u", key_length,
- (*prev)->key_length));
+ (*prev_changed)->key_length));
DBUG_VOID_RETURN;
}
@@ -434,6 +470,15 @@ void THD::close_active_vio()
}
#endif
+void THD::add_possible_loop (Item *item)
+{
+ if (!possible_loops)
+ {
+ possible_loops= new List<Item>;
+ }
+ possible_loops->push_back(item);
+}
+
/*****************************************************************************
** Functions to provide a interface to select results
*****************************************************************************/
@@ -872,9 +917,9 @@ bool select_singleval_subselect::send_data(List<Item> &items)
{
DBUG_ENTER("select_singleval_subselect::send_data");
Item_singleval_subselect *it= (Item_singleval_subselect *)item;
- if (it->assigned()){
- thd->fatal_error= 1;
- my_message(ER_SUBSELECT_NO_1_ROW, ER(ER_SUBSELECT_NO_1_ROW), MYF(0));
+ if (it->assigned())
+ {
+ my_message(ER_SUBSELECT_NO_1_ROW, ER(ER_SUBSELECT_NO_1_ROW), MYF(0));
DBUG_RETURN(1);
}
if (unit->offset_limit_cnt)
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 1d9c395c623..0b2ecbb08e0 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -341,13 +341,14 @@ struct system_variables
{
ulonglong myisam_max_extra_sort_file_size;
ulonglong myisam_max_sort_file_size;
+ ulonglong select_limit;
+ ulonglong max_join_size;
ulong bulk_insert_buff_size;
ulong join_buff_size;
ulong long_query_time;
ulong max_allowed_packet;
ulong max_error_count;
ulong max_heap_table_size;
- ulong max_join_size;
ulong max_prep_stmt_count;
ulong max_sort_length;
ulong max_tmp_tables;
@@ -361,7 +362,6 @@ struct system_variables
ulong query_cache_type;
ulong read_buff_size;
ulong read_rnd_buff_size;
- ulong select_limit;
ulong sortbuff_size;
ulong table_type;
ulong tmp_table_size;
@@ -482,11 +482,13 @@ public:
USER_CONN *user_connect;
CHARSET_INFO *db_charset;
CHARSET_INFO *thd_charset;
+ List<Item> *possible_loops; // Items that may cause loops in subselects
List <MYSQL_ERROR> warn_list;
uint warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_END];
uint total_warn_count, old_total_warn_count;
- ulong query_id, version, options, thread_id, col_access;
+ ulong query_id, warn_id, version, options, thread_id, col_access;
ulong current_stmt_id;
+ ulong rand_saved_seed1, rand_saved_seed2;
long dbug_thread_id;
pthread_t real_id;
uint current_tablenr,tmp_table,cond_count;
@@ -494,6 +496,7 @@ public:
uint32 query_length;
uint32 db_length;
uint select_number; //number of select (used for EXPLAIN)
+ uint check_loops_counter; //last id used to check loops
/* variables.transaction_isolation is reset to this after each commit */
enum_tx_isolation session_tx_isolation;
char scramble[21]; // extend scramble to handle new auth
@@ -502,7 +505,6 @@ public:
bool set_query_id,locked,count_cuted_fields,some_tables_deleted;
bool no_errors, allow_sum_func, password, fatal_error;
bool query_start_used,last_insert_id_used,insert_id_used,rand_used;
- ulonglong rand_saved_seed1, rand_saved_seed2;
bool system_thread,in_lock_tables,global_read_lock;
bool query_error, bootstrap, cleanup_done;
bool safe_to_cache_query;
@@ -532,6 +534,8 @@ public:
THD();
~THD();
+ void init(void);
+ void change_user(void);
void cleanup(void);
bool store_globals();
#ifdef SIGNAL_WITH_VIO_CLOSE
@@ -631,6 +635,7 @@ public:
net.last_errno= 0;
net.report_error= 0;
}
+ void add_possible_loop(Item *);
};
/*
@@ -929,11 +934,9 @@ public:
ha_rows deleted;
uint num_of_tables;
int error;
- thr_lock_type lock_option;
- bool do_delete, not_trans_safe;
+ bool do_delete, transactional_tables, log_delayed, normal_tables;
public:
- multi_delete(THD *thd, TABLE_LIST *dt, thr_lock_type lock_option_arg,
- uint num_of_tables);
+ multi_delete(THD *thd, TABLE_LIST *dt, uint num_of_tables);
~multi_delete();
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
bool send_fields(List<Item> &list,
@@ -953,7 +956,6 @@ public:
ha_rows updated, found;
List<Item> fields;
List <Item> **fields_by_tables;
- thr_lock_type lock_option;
enum enum_duplicates dupl;
uint num_of_tables, num_fields, num_updated, *save_time_stamps, *field_sequence;
int error;
@@ -961,7 +963,7 @@ public:
public:
multi_update(THD *thd_arg, TABLE_LIST *ut, List<Item> &fs,
enum enum_duplicates handle_duplicates,
- thr_lock_type lock_option_arg, uint num);
+ uint num);
~multi_update();
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
bool send_fields(List<Item> &list,
diff --git a/sql/sql_db.cc b/sql/sql_db.cc
index b80e25c9f40..c3e183de0ac 100644
--- a/sql/sql_db.cc
+++ b/sql/sql_db.cc
@@ -220,7 +220,7 @@ int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info,
if (!thd->query) // Only in replication
{
query= path;
- query_length= (uint) (strxmov(path,"create database ", db, NullS) -
+ query_length= (uint) (strxmov(path,"create database `", db, "`", NullS) -
path);
}
else
@@ -231,7 +231,7 @@ int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info,
mysql_update_log.write(thd, query, query_length);
if (mysql_bin_log.is_open())
{
- Query_log_event qinfo(thd, query, query_length);
+ Query_log_event qinfo(thd, query, query_length, 0);
mysql_bin_log.write(&qinfo);
}
send_ok(thd, result);
@@ -282,7 +282,7 @@ int mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info)
mysql_update_log.write(thd,thd->query, thd->query_length);
if (mysql_bin_log.is_open())
{
- Query_log_event qinfo(thd, thd->query, thd->query_length);
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
mysql_bin_log.write(&qinfo);
}
send_ok(thd, result);
@@ -346,22 +346,25 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
query_cache_invalidate1(db);
if (!silent)
{
+ const char *query;
+ ulong query_length;
if (!thd->query)
{
- thd->query = path;
- thd->query_length = (uint) (strxmov(path,"drop database ", db, NullS)-
- path);
+ /* The client used the old obsolete mysql_drop_db() call */
+ query= path;
+ query_length = (uint) (strxmov(path,"drop database `", db, "`",
+ NullS)- path);
}
- mysql_update_log.write(thd, thd->query, thd->query_length);
- if (mysql_bin_log.is_open())
+ else
{
- Query_log_event qinfo(thd, thd->query, thd->query_length);
- mysql_bin_log.write(&qinfo);
+ query=thd->query;
+ query_length=thd->query_length;
}
- if (thd->query == path)
+ mysql_update_log.write(thd, query, query_length);
+ if (mysql_bin_log.is_open())
{
- thd->query = 0; // just in case
- thd->query_length = 0;
+ Query_log_event qinfo(thd, query, query_length, 0);
+ mysql_bin_log.write(&qinfo);
}
send_ok(thd,(ulong) deleted);
}
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index 64945fa2d4d..c9e10b5b0b5 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -28,26 +28,18 @@
#include "sql_select.h"
int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order,
- ha_rows limit, thr_lock_type lock_type, ulong options)
+ ha_rows limit, ulong options)
{
int error;
TABLE *table;
SQL_SELECT *select=0;
READ_RECORD info;
bool using_limit=limit != HA_POS_ERROR;
- bool using_transactions;
+ bool transactional_table, log_delayed, safe_update, const_cond;
ha_rows deleted;
DBUG_ENTER("mysql_delete");
- if (!table_list->db)
- table_list->db=thd->db;
- if ((thd->options & OPTION_SAFE_UPDATES) && !conds)
- {
- send_error(thd,ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE);
- DBUG_RETURN(1);
- }
-
- if (!(table = open_ltable(thd,table_list, lock_type)))
+ if (!(table = open_ltable(thd, table_list, table_list->lock_type)))
DBUG_RETURN(-1);
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
thd->proc_info="init";
@@ -56,8 +48,16 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order,
setup_ftfuncs(&thd->lex.select_lex))
DBUG_RETURN(-1);
+ const_cond= (!conds || conds->const_item());
+ safe_update=test(thd->options & OPTION_SAFE_UPDATES);
+ if (safe_update && const_cond)
+ {
+ send_error(thd,ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE);
+ DBUG_RETURN(1);
+ }
+
/* Test if the user wants to delete all rows */
- if (!using_limit && (!conds || conds->const_item()) &&
+ if (!using_limit && const_cond &&
!(specialflag & (SPECIAL_NO_NEW_FUNC | SPECIAL_SAFE_MODE)))
{
deleted= table->file->records;
@@ -79,9 +79,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 & OPTION_SAFE_UPDATES),
- limit)) ||
- !limit)
+ if ((select && select->check_quick(safe_update, limit)) || !limit)
{
delete select;
send_ok(thd,0L);
@@ -92,7 +90,7 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order,
if (!table->quick_keys)
{
thd->lex.select_lex.options|=QUERY_NO_INDEX_USED;
- if ((thd->options & OPTION_SAFE_UPDATES) && limit == HA_POS_ERROR)
+ if (safe_update && !using_limit)
{
delete select;
send_error(thd,ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE);
@@ -162,23 +160,34 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order,
(void) table->file->extra(HA_EXTRA_NORMAL);
cleanup:
- using_transactions=table->file->has_transactions();
- if (deleted && (error <= 0 || !using_transactions))
+ transactional_table= table->file->has_transactions();
+ log_delayed= (transactional_table || table->tmp_table);
+ if (deleted && (error <= 0 || !transactional_table))
{
mysql_update_log.write(thd,thd->query, thd->query_length);
if (mysql_bin_log.is_open())
{
Query_log_event qinfo(thd, thd->query, thd->query_length,
- using_transactions);
- if (mysql_bin_log.write(&qinfo) && using_transactions)
+ log_delayed);
+ if (mysql_bin_log.write(&qinfo) && transactional_table)
error=1;
}
- if (!using_transactions)
+ if (!log_delayed)
thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
}
- if (using_transactions && ha_autocommit_or_rollback(thd,error >= 0))
- error=1;
- if (deleted)
+ if (transactional_table)
+ {
+ if (ha_autocommit_or_rollback(thd,error >= 0))
+ error=1;
+ }
+ /*
+ Only invalidate the query cache if something changed or if we
+ didn't commit the transacion (query cache is automaticly
+ invalidated on commit)
+ */
+ if (deleted &&
+ (!transactional_table ||
+ thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))
{
query_cache_invalidate3(thd, table_list, 1);
}
@@ -205,19 +214,17 @@ cleanup:
#define MEM_STRIP_BUF_SIZE current_thd->variables.sortbuff_size
-int refposcmp2(void* arg, const void *a,const void *b)
+extern "C" int refposcmp2(void* arg, const void *a,const void *b)
{
return memcmp(a,b, *(int*) arg);
}
multi_delete::multi_delete(THD *thd_arg, TABLE_LIST *dt,
- thr_lock_type lock_option_arg,
uint num_of_tables_arg)
: delete_tables (dt), thd(thd_arg), deleted(0),
- num_of_tables(num_of_tables_arg), error(0), lock_option(lock_option_arg),
- do_delete(false)
+ num_of_tables(num_of_tables_arg), error(0),
+ do_delete(0), transactional_tables(0), log_delayed(0), normal_tables(0)
{
- not_trans_safe=false;
tempfiles = (Unique **) sql_calloc(sizeof(Unique *) * (num_of_tables-1));
}
@@ -268,8 +275,12 @@ multi_delete::initialize_tables(JOIN *join)
/* Don't use KEYREAD optimization on this table */
tbl->no_keyread=1;
walk=walk->next;
- if (!not_trans_safe && !tbl->file->has_transactions())
- not_trans_safe=true;
+ if (tbl->file->has_transactions())
+ log_delayed= transactional_tables= 1;
+ else if (tbl->tmp_table != NO_TMP_TABLE)
+ log_delayed= 1;
+ else
+ normal_tables= 1;
}
}
walk= delete_tables;
@@ -375,7 +386,7 @@ void multi_delete::send_error(uint errcode,const char *err)
In all other cases do attempt deletes ...
*/
if ((table_being_deleted->table->file->has_transactions() &&
- table_being_deleted == delete_tables) || !not_trans_safe)
+ table_being_deleted == delete_tables) || !normal_tables)
ha_rollback_stmt(thd);
else if (do_delete)
{
@@ -394,7 +405,7 @@ void multi_delete::send_error(uint errcode,const char *err)
int multi_delete::do_deletes(bool from_send_error)
{
- int error = 0, counter = 0;
+ int local_error= 0, counter= 0;
if (from_send_error)
{
@@ -415,27 +426,26 @@ int multi_delete::do_deletes(bool from_send_error)
TABLE *table = table_being_deleted->table;
if (tempfiles[counter]->get(table))
{
- error=1;
+ local_error=1;
break;
}
READ_RECORD info;
init_read_record(&info,thd,table,NULL,0,0);
- while (!(error=info.read_record(&info)) &&
- (!thd->killed || from_send_error || not_trans_safe))
+ while (!(local_error=info.read_record(&info)) && !thd->killed)
{
- if ((error=table->file->delete_row(table->record[0])))
+ if ((local_error=table->file->delete_row(table->record[0])))
{
- table->file->print_error(error,MYF(0));
+ table->file->print_error(local_error,MYF(0));
break;
}
deleted++;
}
end_read_record(&info);
- if (error == -1) // End of file
- error = 0;
+ if (local_error == -1) // End of file
+ local_error = 0;
}
- return error;
+ return local_error;
}
@@ -451,15 +461,11 @@ bool multi_delete::send_eof()
thd->proc_info="deleting from reference tables";
/* Does deletes for the last n - 1 tables, returns 0 if ok */
- int error = do_deletes(0); // returns 0 if success
+ int local_error= do_deletes(0); // returns 0 if success
/* reset used flags */
thd->proc_info="end";
- if (error)
- {
- ::send_error(thd);
- return 1;
- }
+
/*
Write the SQL statement to the binlog if we deleted
@@ -467,24 +473,25 @@ bool multi_delete::send_eof()
was a non-transaction-safe table involved, since
modifications in it cannot be rolled back.
*/
- if (deleted || not_trans_safe)
+ if (deleted)
{
mysql_update_log.write(thd,thd->query,thd->query_length);
if (mysql_bin_log.is_open())
{
- Query_log_event qinfo(thd, thd->query, thd->query_length);
- if (mysql_bin_log.write(&qinfo) &&
- !not_trans_safe)
- error=1; // Log write failed: roll back the SQL statement
+ Query_log_event qinfo(thd, thd->query, thd->query_length,
+ log_delayed);
+ if (mysql_bin_log.write(&qinfo) && !normal_tables)
+ local_error=1; // Log write failed: roll back the SQL statement
}
/* Commit or rollback the current SQL statement */
- VOID(ha_autocommit_or_rollback(thd,error > 0));
- }
- if (deleted)
- {
+ VOID(ha_autocommit_or_rollback(thd,local_error > 0));
+
query_cache_invalidate3(thd, delete_tables, 1);
}
- ::send_ok(thd,deleted);
+ if (local_error)
+ ::send_error(thd);
+ else
+ ::send_ok(thd, deleted);
return 0;
}
@@ -557,8 +564,9 @@ int mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok)
if (!ha_supports_generate(table_type))
{
/* Probably InnoDB table */
- DBUG_RETURN(mysql_delete(thd,table_list, (COND*) 0, (ORDER*) 0,
- HA_POS_ERROR, TL_WRITE, 0));
+ table_list->lock_type= TL_WRITE;
+ DBUG_RETURN(mysql_delete(thd, table_list, (COND*) 0, (ORDER*) 0,
+ HA_POS_ERROR, 0));
}
if (lock_and_wait_for_table_name(thd, table_list))
DBUG_RETURN(-1);
@@ -570,6 +578,7 @@ int mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok)
*fn_ext(path)=0; // Remove the .frm extension
error= ha_create_table(path,&create_info,1) ? -1 : 0;
query_cache_invalidate3(thd, table_list, 0);
+
end:
if (!dont_send_ok)
{
@@ -578,7 +587,8 @@ end:
mysql_update_log.write(thd,thd->query,thd->query_length);
if (mysql_bin_log.is_open())
{
- Query_log_event qinfo(thd, thd->query, thd->query_length);
+ Query_log_event qinfo(thd, thd->query, thd->query_length,
+ thd->tmp_table);
mysql_bin_log.write(&qinfo);
}
send_ok(thd); // This should return record count
diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc
index 1335618b90d..b3d2b1602d0 100644
--- a/sql/sql_derived.cc
+++ b/sql/sql_derived.cc
@@ -28,8 +28,7 @@
static const char *any_db="*any*"; // Special symbol for check_access
-int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t,
- bool tables_is_opened)
+int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
{
/*
TODO: make derived tables with union inside (now only 1 SELECT may be
@@ -58,7 +57,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t,
if (cursor->derived)
{
res= mysql_derived(thd, lex, (SELECT_LEX_UNIT *)cursor->derived,
- cursor, 0);
+ cursor);
if (res) DBUG_RETURN(res);
}
}
@@ -68,7 +67,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t,
while ((item= it++))
item_list.push_back(item);
- if (tables_is_opened || !(res=open_and_lock_tables(thd,tables)))
+ if (!(res=open_and_lock_tables(thd,tables)))
{
if (setup_fields(thd,tables,item_list,0,0,1))
{
@@ -89,19 +88,24 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t,
if ((derived_result=new select_union(table)))
{
+ derived_result->tmp_table_param=&tmp_table_param;
unit->offset_limit_cnt= sl->offset_limit;
unit->select_limit_cnt= sl->select_limit+sl->offset_limit;
if (unit->select_limit_cnt < sl->select_limit)
unit->select_limit_cnt= HA_POS_ERROR;
if (unit->select_limit_cnt == HA_POS_ERROR)
sl->options&= ~OPTION_FOUND_ROWS;
-
+
+ SELECT_LEX_NODE *save_current_select= lex->current_select;
+ lex->current_select= sl;
res= mysql_select(thd, tables, sl->item_list,
sl->where, (ORDER *) sl->order_list.first,
(ORDER*) sl->group_list.first,
sl->having, (ORDER*) NULL,
sl->options | thd->options | SELECT_NO_UNLOCK,
derived_result, unit, sl, 0);
+ lex->current_select= save_current_select;
+
if (!res)
{
// Here we entirely fix both TABLE_LIST and list of SELECT's as there were no derived tables
@@ -112,8 +116,10 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t,
t->real_name=table->real_name;
t->table=table;
table->derived_select_number= sl->select_number;
- sl->exclude();
- t->db= (tables && tables->db && tables->db[0]) ? t->db : thd->db;
+ table->tmp_table=TMP_TABLE;
+ if (!lex->describe)
+ sl->exclude();
+ t->db=(char *)"";
t->derived=(SELECT_LEX *)0; // just in case ...
}
}
@@ -123,8 +129,6 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t,
free_tmp_table(thd,table);
exit:
close_thread_tables(thd);
- if (res > 0)
- send_error(thd, ER_UNKNOWN_COM_ERROR); // temporary only ...
}
DBUG_RETURN(res);
}
diff --git a/sql/sql_error.cc b/sql/sql_error.cc
index 3d6a0fa24aa..0740dc428f0 100644
--- a/sql/sql_error.cc
+++ b/sql/sql_error.cc
@@ -51,13 +51,22 @@ This file contains the implementation of error and warnings related
SYNOPSIS
mysql_reset_errors()
thd Thread handle
+
+ IMPLEMENTATION
+ Don't reset warnings if this has already been called for this query.
+ This may happen if one gets a warning during the parsing stage,
+ in which case push_warnings() has already called this function.
*/
void mysql_reset_errors(THD *thd)
{
- free_root(&thd->warn_root,MYF(0));
- bzero((char*) thd->warn_count, sizeof(thd->warn_count));
- thd->warn_list.empty();
+ if (thd->query_id != thd->warn_id)
+ {
+ thd->warn_id= thd->query_id;
+ free_root(&thd->warn_root,MYF(0));
+ bzero((char*) thd->warn_count, sizeof(thd->warn_count));
+ thd->warn_list.empty();
+ }
}
@@ -75,6 +84,9 @@ void mysql_reset_errors(THD *thd)
void push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level, uint code,
const char *msg)
{
+ if (thd->query_id != thd->warn_id)
+ mysql_reset_errors(thd);
+
if (thd->warn_list.elements < thd->variables.max_error_count)
{
/*
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 0a1b4435fff..6cb146afb33 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -25,7 +25,7 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list);
static int write_delayed(THD *thd,TABLE *table, enum_duplicates dup,
char *query, uint query_length, bool log_on);
static void end_delayed_insert(THD *thd);
-static pthread_handler_decl(handle_delayed_insert,arg);
+extern "C" pthread_handler_decl(handle_delayed_insert,arg);
static void unlink_blobs(register TABLE *table);
/* Define to force use of my_malloc() if the allocated memory block is big */
@@ -98,13 +98,12 @@ check_insert_fields(THD *thd,TABLE *table,List<Item> &fields,
int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
- List<List_item> &values_list,enum_duplicates duplic,
- thr_lock_type lock_type)
+ List<List_item> &values_list,enum_duplicates duplic)
{
int error;
bool log_on= ((thd->options & OPTION_UPDATE_LOG) ||
!(thd->master_access & SUPER_ACL));
- bool using_transactions, bulk_insert=0;
+ bool transactional_table, log_delayed, bulk_insert=0;
uint value_count;
uint save_time_stamp;
ulong counter = 1;
@@ -114,6 +113,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
List_iterator_fast<List_item> its(values_list);
List_item *values;
char *query=thd->query;
+ thr_lock_type lock_type = table_list->lock_type;
DBUG_ENTER("mysql_insert");
/*
@@ -194,14 +194,19 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
thd->proc_info="update";
if (duplic == DUP_IGNORE || duplic == DUP_REPLACE)
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
- if ((bulk_insert= (values_list.elements > 1 &&
+ if ((bulk_insert= (values_list.elements >= MIN_ROWS_TO_USE_BULK_INSERT &&
lock_type != TL_WRITE_DELAYED &&
!(specialflag & SPECIAL_SAFE_MODE))))
{
table->file->extra_opt(HA_EXTRA_WRITE_CACHE,
- thd->variables.read_buff_size);
- table->file->extra_opt(HA_EXTRA_BULK_INSERT_BEGIN,
- thd->variables.bulk_insert_buff_size);
+ min(thd->variables.read_buff_size,
+ table->avg_row_length*values_list.elements));
+ if (thd->variables.bulk_insert_buff_size)
+ table->file->extra_opt(HA_EXTRA_BULK_INSERT_BEGIN,
+ min(thd->variables.bulk_insert_buff_size,
+ (table->total_key_length +
+ table->keys * TREE_ELEMENT_EXTRA_SIZE)*
+ values_list.elements));
table->bulk_insert= 1;
}
@@ -266,10 +271,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
info.copied=values_list.elements;
end_delayed_insert(thd);
}
- if (info.copied || info.deleted)
- {
- query_cache_invalidate3(thd, table_list, 1);
- }
+ query_cache_invalidate3(thd, table_list, 1);
}
else
{
@@ -297,23 +299,33 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
thd->insert_id(id); // For update log
else if (table->next_number_field)
id=table->next_number_field->val_int(); // Return auto_increment value
- using_transactions=table->file->has_transactions();
- if ((info.copied || info.deleted) && (error <= 0 || !using_transactions))
+
+ transactional_table= table->file->has_transactions();
+ log_delayed= (transactional_table || table->tmp_table);
+ if ((info.copied || info.deleted) && (error <= 0 || !transactional_table))
{
mysql_update_log.write(thd, thd->query, thd->query_length);
if (mysql_bin_log.is_open())
{
Query_log_event qinfo(thd, thd->query, thd->query_length,
- using_transactions);
- if (mysql_bin_log.write(&qinfo) && using_transactions)
+ log_delayed);
+ if (mysql_bin_log.write(&qinfo) && transactional_table)
error=1;
}
- if (!using_transactions)
+ if (!log_delayed)
thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
}
- if (using_transactions)
+ if (transactional_table)
error=ha_autocommit_or_rollback(thd,error);
- if (info.copied || info.deleted)
+
+ /*
+ Only invalidate the query cache if something changed or if we
+ didn't commit the transacion (query cache is automaticly
+ invalidated on commit)
+ */
+ if ((info.copied || info.deleted) &&
+ (!transactional_table ||
+ thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))
{
query_cache_invalidate3(thd, table_list, 1);
}
@@ -913,7 +925,7 @@ void kill_delayed_threads(void)
* Create a new delayed insert thread
*/
-static pthread_handler_decl(handle_delayed_insert,arg)
+extern "C" pthread_handler_decl(handle_delayed_insert,arg)
{
delayed_insert *di=(delayed_insert*) arg;
THD *thd= &di->thd;
@@ -1197,7 +1209,7 @@ bool delayed_insert::handle_inserts(void)
mysql_update_log.write(&thd,row->query, row->query_length);
if (using_bin_log)
{
- Query_log_event qinfo(&thd, row->query, row->query_length);
+ Query_log_event qinfo(&thd, row->query, row->query_length,0);
mysql_bin_log.write(&qinfo);
}
}
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 5327801bf9c..9ed66aede6f 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -855,9 +855,8 @@ int yylex(void *arg)
case STATE_END:
lex->next_state=STATE_END;
return(0); // We found end of input last time
-
- // Actually real shouldn't start
- // with . but allow them anyhow
+
+ /* Actually real shouldn't start with . but allow them anyhow */
case STATE_REAL_OR_POINT:
if (my_isdigit(system_charset_info,yyPeek()))
state = STATE_REAL; // Real
@@ -959,6 +958,7 @@ void st_select_lex::init_query()
table_list.next= (byte**) &table_list.first;
item_list.empty();
join= 0;
+ olap= UNSPECIFIED_OLAP_TYPE;
}
void st_select_lex::init_select()
@@ -1180,7 +1180,6 @@ bool st_select_lex_unit::create_total_list_n_last_return(THD *thd, st_lex *lex,
if (!cursor)
{
/* Add not used table to the total table list */
- aux->lock_type= lex->lock_option;
if (!(cursor= (TABLE_LIST *) thd->memdup((char*) aux,
sizeof(*aux))))
{
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index ea944ef34c8..dd41af4b250 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -239,7 +239,7 @@ public:
thr_lock_type flags= TL_UNLOCK,
List<String> *use_index= 0,
List<String> *ignore_index= 0);
-
+ virtual void set_lock_for_tables(thr_lock_type lock_type) {}
void mark_as_dependent(st_select_lex *last);
private:
void fast_exclude();
@@ -336,7 +336,7 @@ public:
}
st_select_lex* outer_select();
st_select_lex* next_select() { return (st_select_lex*) next; }
- st_select_lex* next_select_in_list()
+ st_select_lex* next_select_in_list()
{
return (st_select_lex*) link_next;
}
@@ -364,6 +364,7 @@ public:
thr_lock_type flags= TL_UNLOCK,
List<String> *use_index= 0,
List<String> *ignore_index= 0);
+ void set_lock_for_tables(thr_lock_type lock_type);
inline void init_order()
{
order_list.elements= 0;
@@ -436,9 +437,9 @@ typedef struct st_lex
uint grant, grant_tot_col, which_columns;
uint fk_delete_opt, fk_update_opt, fk_match_option;
uint param_count;
- bool drop_primary, drop_if_exists, local_file, olap;
+ bool drop_primary, drop_if_exists, drop_temporary, local_file;
bool in_comment, ignore_space, verbose, simple_alter;
- bool derived_tables, describe;
+ bool derived_tables, describe, olap;
uint slave_thd_opt;
CHARSET_INFO *charset;
char *help_arg;
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index 52d1f3adf48..00450a3b86c 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -90,7 +90,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
bool is_fifo=0;
LOAD_FILE_INFO lf_info;
char * db = table_list->db ? table_list->db : thd->db;
- bool using_transactions;
+ bool transactional_table, log_delayed;
DBUG_ENTER("mysql_load");
#ifdef EMBEDDED_LIBRARY
@@ -105,6 +105,9 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
}
if (!(table = open_ltable(thd,table_list,lock_type)))
DBUG_RETURN(-1);
+ transactional_table= table->file->has_transactions();
+ log_delayed= (transactional_table || table->tmp_table);
+
if (!fields.elements)
{
Field **field;
@@ -224,6 +227,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
lf_info.handle_dup = handle_duplicates;
lf_info.wrote_create_file = 0;
lf_info.last_pos_in_file = HA_POS_ERROR;
+ lf_info.log_delayed= log_delayed;
read_info.set_io_cache_arg((void*) &lf_info);
}
restore_record(table,2);
@@ -275,16 +279,16 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
free_blobs(table); /* if pack_blob was used */
table->copy_blobs=0;
thd->count_cuted_fields=0; /* Don`t calc cuted fields */
- using_transactions = table->file->has_transactions();
+
if (error)
{
- if (using_transactions)
+ if (transactional_table)
ha_autocommit_or_rollback(thd,error);
if (!opt_old_rpl_compat && mysql_bin_log.is_open())
{
if (lf_info.wrote_create_file)
{
- Delete_file_log_event d(thd);
+ Delete_file_log_event d(thd, log_delayed);
mysql_bin_log.write(&d);
}
}
@@ -297,27 +301,30 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
if (!thd->slave_thread)
mysql_update_log.write(thd,thd->query,thd->query_length);
- if (!using_transactions)
+ if (!log_delayed)
thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
if (mysql_bin_log.is_open())
{
- if (opt_old_rpl_compat && !read_file_from_client)
+ if (opt_old_rpl_compat)
{
- Load_log_event qinfo(thd, ex, db, table->table_name, fields,
- handle_duplicates);
- mysql_bin_log.write(&qinfo);
+ if (!read_file_from_client)
+ {
+ Load_log_event qinfo(thd, ex, db, table->table_name, fields,
+ handle_duplicates, log_delayed);
+ mysql_bin_log.write(&qinfo);
+ }
}
- if (!opt_old_rpl_compat)
+ else
{
read_info.end_io_cache(); // make sure last block gets logged
if (lf_info.wrote_create_file)
{
- Execute_load_log_event e(thd);
+ Execute_load_log_event e(thd, log_delayed);
mysql_bin_log.write(&e);
}
}
}
- if (using_transactions)
+ if (transactional_table)
error=ha_autocommit_or_rollback(thd,error);
DBUG_RETURN(error);
}
diff --git a/sql/sql_manager.cc b/sql/sql_manager.cc
index 13cac83fc3f..0af6a80d4c2 100644
--- a/sql/sql_manager.cc
+++ b/sql/sql_manager.cc
@@ -32,7 +32,7 @@ pthread_t manager_thread;
pthread_mutex_t LOCK_manager;
pthread_cond_t COND_manager;
-pthread_handler_decl(handle_manager,arg __attribute__((unused)))
+extern "C" pthread_handler_decl(handle_manager,arg __attribute__((unused)))
{
int error = 0;
ulong status;
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 365f7d2d110..7d828dbbefa 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -100,7 +100,17 @@ static void init_signals(void)
}
#endif
-inline bool end_active_trans(THD *thd)
+static void unlock_locked_tables(THD *thd)
+{
+ if (thd->locked_tables)
+ {
+ thd->lock=thd->locked_tables;
+ thd->locked_tables=0; // Will be automaticly closed
+ close_thread_tables(thd); // Free tables
+ }
+}
+
+static bool end_active_trans(THD *thd)
{
int error=0;
if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN |
@@ -270,14 +280,14 @@ static bool check_user(THD *thd,enum_server_command command, const char *user,
started with corresponding variable that is greater then 0.
*/
-static byte* get_key_conn(user_conn *buff, uint *length,
- my_bool not_used __attribute__((unused)))
+extern "C" byte *get_key_conn(user_conn *buff, uint *length,
+ my_bool not_used __attribute__((unused)))
{
*length=buff->len;
return (byte*) buff->user;
}
-static void free_user(struct user_conn *uc)
+extern "C" void free_user(struct user_conn *uc)
{
my_free((char*) uc,MYF(0));
}
@@ -286,7 +296,7 @@ void init_max_user_conn(void)
{
(void) hash_init(&hash_user_connections,system_charset_info,max_connections,
0,0,
- (hash_get_key) get_key_conn, (void (*)(void*)) free_user,
+ (hash_get_key) get_key_conn, (hash_free_key) free_user,
0);
}
@@ -569,7 +579,13 @@ check_connections(THD *thd)
{
/* Do the SSL layering. */
DBUG_PRINT("info", ("IO layer change in progress..."));
- sslaccept(ssl_acceptor_fd, net->vio, thd->variables.net_wait_timeout);
+ if (sslaccept(ssl_acceptor_fd, net->vio, thd->variables.net_wait_timeout))
+ {
+ DBUG_PRINT("error", ("Failed to read user information (pkt_len= %lu)",
+ pkt_len));
+ inc_host_errors(&thd->remote.sin_addr);
+ return(ER_HANDSHAKE_ERROR);
+ }
DBUG_PRINT("info", ("Reading user information over SSL layer"));
if ((pkt_len=my_net_read(net)) == packet_error ||
pkt_len < NORMAL_HANDSHAKE_SIZE)
@@ -740,7 +756,7 @@ pthread_handler_decl(handle_one_connection,arg)
goto end_thread;
}
- if ((ulong) thd->variables.max_join_size == (ulong) HA_POS_ERROR)
+ if ((ulong) thd->variables.max_join_size == (ulonglong) HA_POS_ERROR)
thd->options |= OPTION_BIG_SELECTS;
if (thd->client_capabilities & CLIENT_COMPRESS)
net->compress=1; // Use compression
@@ -770,7 +786,7 @@ pthread_handler_decl(handle_one_connection,arg)
(net->last_errno ? ER(net->last_errno) :
ER(ER_UNKNOWN_ERROR)));
send_error(thd,net->last_errno,NullS);
- thread_safe_increment(aborted_threads,&LOCK_status);
+ statistic_increment(aborted_threads,&LOCK_status);
}
end_thread:
@@ -791,7 +807,7 @@ end_thread:
Used when creating the initial grant tables
*/
-pthread_handler_decl(handle_bootstrap,arg)
+extern "C" pthread_handler_decl(handle_bootstrap,arg)
{
THD *thd=(THD*) arg;
FILE *file=bootstrap_file;
@@ -816,7 +832,7 @@ pthread_handler_decl(handle_bootstrap,arg)
#endif
- if ((ulong) thd->variables.max_join_size == (ulong) HA_POS_ERROR)
+ if ((ulong) thd->variables.max_join_size == (ulonglong) HA_POS_ERROR)
thd->options |= OPTION_BIG_SELECTS;
thd->proc_info=0;
@@ -983,7 +999,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
thd->lex.select_lex.options=0; // We store status here
switch (command) {
case COM_INIT_DB:
- thread_safe_increment(com_stat[SQLCOM_CHANGE_DB],&LOCK_status);
+ statistic_increment(com_stat[SQLCOM_CHANGE_DB],&LOCK_status);
if (!mysql_change_db(thd,packet))
mysql_log.write(thd,command,"%s",thd->db);
break;
@@ -995,7 +1011,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
}
case COM_TABLE_DUMP:
{
- thread_safe_increment(com_other, &LOCK_status);
+ statistic_increment(com_other, &LOCK_status);
slow_command = TRUE;
uint db_len = *(uchar*)packet;
uint tbl_len = *(uchar*)(packet + db_len + 1);
@@ -1012,7 +1028,10 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
}
case COM_CHANGE_USER:
{
- thread_safe_increment(com_other,&LOCK_status);
+ thd->change_user();
+ clear_error_message(thd); // If errors from rollback
+
+ statistic_increment(com_other,&LOCK_status);
char *user= (char*) packet;
char *passwd= strend(user)+1;
char *db= strend(passwd)+1;
@@ -1088,7 +1107,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
{
char *fields;
TABLE_LIST table_list;
- thread_safe_increment(com_stat[SQLCOM_SHOW_FIELDS],&LOCK_status);
+ statistic_increment(com_stat[SQLCOM_SHOW_FIELDS],&LOCK_status);
bzero((char*) &table_list,sizeof(table_list));
if (!(table_list.db=thd->db))
{
@@ -1123,7 +1142,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
case COM_CREATE_DB: // QQ: To be removed
{
- thread_safe_increment(com_stat[SQLCOM_CREATE_DB],&LOCK_status);
+ statistic_increment(com_stat[SQLCOM_CREATE_DB],&LOCK_status);
char *db=thd->strdup(packet);
// null test to handle EOM
if (!db || !strip_sp(db) || check_db_name(db))
@@ -1141,7 +1160,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
}
case COM_DROP_DB: // QQ: To be removed
{
- thread_safe_increment(com_stat[SQLCOM_DROP_DB],&LOCK_status);
+ statistic_increment(com_stat[SQLCOM_DROP_DB],&LOCK_status);
char *db=thd->strdup(packet);
// null test to handle EOM
if (!db || !strip_sp(db) || check_db_name(db))
@@ -1162,7 +1181,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
}
case COM_BINLOG_DUMP:
{
- thread_safe_increment(com_other,&LOCK_status);
+ statistic_increment(com_other,&LOCK_status);
slow_command = TRUE;
if (check_global_access(thd, REPL_SLAVE_ACL))
break;
@@ -1186,7 +1205,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
}
case COM_REFRESH:
{
- thread_safe_increment(com_stat[SQLCOM_FLUSH],&LOCK_status);
+ statistic_increment(com_stat[SQLCOM_FLUSH],&LOCK_status);
ulong options= (ulong) (uchar) packet[0];
if (check_global_access(thd,RELOAD_ACL))
break;
@@ -1198,7 +1217,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
break;
}
case COM_SHUTDOWN:
- thread_safe_increment(com_other,&LOCK_status);
+ statistic_increment(com_other,&LOCK_status);
if (check_global_access(thd,SHUTDOWN_ACL))
break; /* purecov: inspected */
DBUG_PRINT("quit",("Got shutdown command"));
@@ -1221,7 +1240,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
case COM_STATISTICS:
{
mysql_log.write(thd,command,NullS);
- thread_safe_increment(com_stat[SQLCOM_SHOW_STATUS],&LOCK_status);
+ statistic_increment(com_stat[SQLCOM_SHOW_STATUS],&LOCK_status);
char buff[200];
ulong uptime = (ulong) (thd->start_time - start_time);
sprintf((char*) buff,
@@ -1240,11 +1259,11 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
break;
}
case COM_PING:
- thread_safe_increment(com_other,&LOCK_status);
+ statistic_increment(com_other,&LOCK_status);
send_ok(thd); // Tell client we are alive
break;
case COM_PROCESS_INFO:
- thread_safe_increment(com_stat[SQLCOM_SHOW_PROCESSLIST],&LOCK_status);
+ statistic_increment(com_stat[SQLCOM_SHOW_PROCESSLIST],&LOCK_status);
if (!thd->priv_user[0] && check_global_access(thd,PROCESS_ACL))
break;
mysql_log.write(thd,command,NullS);
@@ -1253,13 +1272,13 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
break;
case COM_PROCESS_KILL:
{
- thread_safe_increment(com_stat[SQLCOM_KILL],&LOCK_status);
+ statistic_increment(com_stat[SQLCOM_KILL],&LOCK_status);
ulong id=(ulong) uint4korr(packet);
kill_one_thread(thd,id);
break;
}
case COM_DEBUG:
- thread_safe_increment(com_other,&LOCK_status);
+ statistic_increment(com_other,&LOCK_status);
if (check_global_access(thd, SUPER_ACL))
break; /* purecov: inspected */
mysql_print_status(thd);
@@ -1380,7 +1399,7 @@ mysql_execute_command(THD *thd)
that is not a SHOW command or a select that only access local
variables, but for now this is probably good enough.
*/
- if (tables)
+ if (tables || lex->select_lex.next_select_in_list())
mysql_reset_errors(thd);
/*
Save old warning count to be able to send to client how many warnings we
@@ -1411,81 +1430,34 @@ mysql_execute_command(THD *thd)
#endif
}
- select_result *explain_result= 0;
/*
TODO: make derived tables processing 'inside' SELECT processing.
TODO: solve problem with depended derived tables in subselects
*/
- if (lex->sql_command == SQLCOM_SELECT &&
- lex->describe && lex->derived_tables)
- {
- if (!(explain_result= new select_send()))
- {
- send_error(thd, ER_OUT_OF_RESOURCES);
- DBUG_VOID_RETURN;
- }
- //check rights
- for (cursor= tables;
- cursor;
- cursor= cursor->next)
- if (cursor->derived)
- {
- TABLE_LIST *tables=
- (TABLE_LIST *)((SELECT_LEX_UNIT *)
- cursor->derived)->first_select()->table_list.first;
- int res;
- if (tables)
- res= check_table_access(thd,SELECT_ACL, tables);
- else
- res= check_access(thd, SELECT_ACL, any_db);
- if (res)
- DBUG_VOID_RETURN;
- }
- thd->send_explain_fields(explain_result);
- // EXPLAIN derived tables
- for (cursor= tables;
- cursor;
- cursor= cursor->next)
- if (cursor->derived)
- {
- SELECT_LEX *select_lex= ((SELECT_LEX_UNIT *)
- cursor->derived)->first_select();
- if (!open_and_lock_tables(thd,
- (TABLE_LIST*) select_lex->table_list.first))
- {
- mysql_explain_select(thd, select_lex,
- "DERIVED", explain_result);
- // execute derived table SELECT to provide table for other SELECTs
- if (mysql_derived(thd, lex, (SELECT_LEX_UNIT *)cursor->derived,
- cursor, 1))
+ if (lex->derived_tables)
+ {
+ for (SELECT_LEX *sl= &lex->select_lex; sl; sl= sl->next_select_in_list())
+ if (sl->linkage != DERIVED_TABLE_TYPE)
+ for (TABLE_LIST *cursor= sl->get_table_list();
+ cursor;
+ cursor= cursor->next)
+ if (cursor->derived && (res=mysql_derived(thd, lex,
+ (SELECT_LEX_UNIT *)
+ cursor->derived,
+ cursor)))
+ {
+ if (res < 0 || thd->net.report_error)
+ send_error(thd,thd->killed ? ER_SERVER_SHUTDOWN : 0);
DBUG_VOID_RETURN;
- }
- else
- DBUG_VOID_RETURN;
- }
-
- }
- else if (lex->derived_tables)
- {
- for (TABLE_LIST *cursor= tables;
- cursor;
- cursor= cursor->next)
- if (cursor->derived && (res=mysql_derived(thd, lex,
- (SELECT_LEX_UNIT *)cursor->derived,
- cursor, 0)))
- {
- if (res < 0)
- send_error(thd,thd->killed ? ER_SERVER_SHUTDOWN : 0);
- DBUG_VOID_RETURN;
- }
- }
+ }
+ }
if ((lex->select_lex.next_select_in_list() &&
lex->unit.create_total_list(thd, lex, &tables)) ||
(table_rules_on && tables && thd->slave_thread &&
!tables_ok(thd,tables)))
DBUG_VOID_RETURN;
- thread_safe_increment(com_stat[lex->sql_command],&LOCK_status);
+ statistic_increment(com_stat[lex->sql_command],&LOCK_status);
switch (lex->sql_command) {
case SQLCOM_SELECT:
{
@@ -1506,10 +1478,11 @@ mysql_execute_command(THD *thd)
break; // Error message is given
}
- unit->offset_limit_cnt= unit->global_parameters->offset_limit;
- unit->select_limit_cnt= unit->global_parameters->select_limit+
- unit->global_parameters->offset_limit;
- if (unit->select_limit_cnt < unit->global_parameters->select_limit)
+ unit->offset_limit_cnt= (ha_rows) unit->global_parameters->offset_limit;
+ unit->select_limit_cnt= (ha_rows) (unit->global_parameters->select_limit+
+ unit->global_parameters->offset_limit);
+ if (unit->select_limit_cnt <
+ (ha_rows) unit->global_parameters->select_limit)
unit->select_limit_cnt= HA_POS_ERROR; // no limit
if (unit->select_limit_cnt == HA_POS_ERROR)
select_lex->options&= ~OPTION_FOUND_ROWS;
@@ -1518,19 +1491,18 @@ mysql_execute_command(THD *thd)
{
if (lex->describe)
{
- if (!explain_result)
- if (!(explain_result= new select_send()))
- {
- send_error(thd, ER_OUT_OF_RESOURCES);
- DBUG_VOID_RETURN;
- }
- else
- thd->send_explain_fields(explain_result);
+ if (!(result= new select_send()))
+ {
+ send_error(thd, ER_OUT_OF_RESOURCES);
+ DBUG_VOID_RETURN;
+ }
+ else
+ thd->send_explain_fields(result);
fix_tables_pointers(select_lex);
- res= mysql_explain_union(thd, &thd->lex.unit, explain_result);
+ res= mysql_explain_union(thd, &thd->lex.unit, result);
MYSQL_LOCK *save_lock= thd->lock;
thd->lock= (MYSQL_LOCK *)0;
- explain_result->send_eof();
+ result->send_eof();
thd->lock= save_lock;
}
else
@@ -1543,6 +1515,8 @@ mysql_execute_command(THD *thd)
Normal select:
Change lock if we are using SELECT HIGH PRIORITY,
FOR UPDATE or IN SHARE MODE
+
+ TODO: Delete the following loop when locks is set by sql_yacc
*/
TABLE_LIST *table;
for (table = tables ; table ; table=table->next)
@@ -1772,6 +1746,7 @@ mysql_execute_command(THD *thd)
TABLE_LIST *table;
if (check_table_access(thd, SELECT_ACL, tables->next))
goto error; // Error message is given
+ /* TODO: Delete the following loop when locks is set by sql_yacc */
for (table = tables->next ; table ; table=table->next)
table->lock_type= lex->lock_option;
}
@@ -1841,7 +1816,7 @@ mysql_execute_command(THD *thd)
#else
{
ulong priv=0;
- if (lex->name && strlen(lex->name) > NAME_LEN)
+ if (lex->name && (!lex->name[0] || strlen(lex->name) > NAME_LEN))
{
net_printf(thd,ER_WRONG_TABLE_NAME,lex->name);
res=0;
@@ -2015,18 +1990,13 @@ mysql_execute_command(THD *thd)
}
if (select_lex->table_list.elements == 1)
{
- res = mysql_update(thd,tables,
- select_lex->item_list,
- lex->value_list,
- select_lex->where,
- (ORDER *) select_lex->order_list.first,
- select_lex->select_limit,
- lex->duplicates,
- lex->lock_option);
-
-#ifdef DELETE_ITEMS
- delete select_lex->where;
-#endif
+ res= mysql_update(thd,tables,
+ select_lex->item_list,
+ lex->value_list,
+ select_lex->where,
+ (ORDER *) select_lex->order_list.first,
+ select_lex->select_limit,
+ lex->duplicates);
}
else
{
@@ -2036,11 +2006,8 @@ mysql_execute_command(THD *thd)
const char *msg=0;
lex->sql_command=SQLCOM_MULTI_UPDATE;
- for (auxi=(TABLE_LIST*) tables, table_count=0 ; auxi ; auxi=auxi->next)
- {
+ for (auxi= (TABLE_LIST*) tables, table_count=0 ; auxi ; auxi=auxi->next)
table_count++;
- auxi->lock_type=TL_WRITE;
- }
if (select_lex->order_list.elements)
msg="ORDER BY";
@@ -2062,8 +2029,7 @@ mysql_execute_command(THD *thd)
!setup_fields(thd,tables,lex->value_list,0,0,0) &&
!thd->fatal_error &&
(result=new multi_update(thd,tables,select_lex->item_list,
- lex->duplicates, lex->lock_option,
- table_count)))
+ lex->duplicates, table_count)))
{
List <Item> total_list;
List_iterator <Item> field_list(select_lex->item_list);
@@ -2094,8 +2060,7 @@ mysql_execute_command(THD *thd)
if (grant_option && check_grant(thd,INSERT_ACL,tables))
goto error;
res = mysql_insert(thd,tables,lex->field_list,lex->many_values,
- lex->duplicates,
- lex->lock_option);
+ lex->duplicates);
break;
case SQLCOM_REPLACE:
if (check_access(thd,INSERT_ACL | DELETE_ACL,
@@ -2106,8 +2071,7 @@ mysql_execute_command(THD *thd)
goto error;
res = mysql_insert(thd,tables,lex->field_list,lex->many_values,
- DUP_REPLACE,
- lex->lock_option);
+ DUP_REPLACE);
break;
case SQLCOM_REPLACE_SELECT:
case SQLCOM_INSERT_SELECT:
@@ -2142,8 +2106,8 @@ mysql_execute_command(THD *thd)
net_printf(thd,ER_INSERT_TABLE_USED,tables->real_name);
DBUG_VOID_RETURN;
}
- tables->lock_type=TL_WRITE; // update first table
{
+ /* TODO: Delete the following loop when locks is set by sql_yacc */
TABLE_LIST *table;
for (table = tables->next ; table ; table=table->next)
table->lock_type= lex->lock_option;
@@ -2186,8 +2150,7 @@ mysql_execute_command(THD *thd)
tables->grant.want_privilege=(SELECT_ACL & ~tables->grant.privilege);
res = mysql_delete(thd,tables, select_lex->where,
(ORDER*) select_lex->order_list.first,
- select_lex->select_limit, lex->lock_option,
- select_lex->options);
+ select_lex->select_limit, select_lex->options);
break;
}
case SQLCOM_DELETE_MULTI:
@@ -2223,7 +2186,7 @@ mysql_execute_command(THD *thd)
net_printf(thd,ER_NONUNIQ_TABLE,auxi->real_name);
goto error;
}
- auxi->lock_type=walk->lock_type=TL_WRITE;
+ walk->lock_type= auxi->lock_type;
auxi->table_list= walk; // Remember corresponding table
}
if (add_item_to_list(new Item_null()))
@@ -2238,7 +2201,6 @@ mysql_execute_command(THD *thd)
for (auxi=(TABLE_LIST*) aux_tables ; auxi ; auxi=auxi->next)
auxi->table= auxi->table_list->table;
if (!thd->fatal_error && (result= new multi_delete(thd,aux_tables,
- lex->lock_option,
table_count)))
{
res= mysql_select(thd,tables,select_lex->item_list,
@@ -2444,11 +2406,7 @@ mysql_execute_command(THD *thd)
send_ok(thd);
break;
case SQLCOM_UNLOCK_TABLES:
- if (thd->locked_tables)
- {
- thd->lock=thd->locked_tables;
- thd->locked_tables=0; // Will be automaticly closed
- }
+ unlock_locked_tables(thd);
if (thd->options & OPTION_TABLE_LOCK)
{
end_active_trans(thd);
@@ -2459,12 +2417,7 @@ mysql_execute_command(THD *thd)
send_ok(thd);
break;
case SQLCOM_LOCK_TABLES:
- if (thd->locked_tables)
- {
- thd->lock=thd->locked_tables;
- thd->locked_tables=0; // Will be automaticly closed
- close_thread_tables(thd);
- }
+ unlock_locked_tables(thd);
if (check_db_used(thd,tables) || end_active_trans(thd))
goto error;
if (check_table_access(thd, LOCK_TABLES_ACL | SELECT_ACL, tables))
@@ -2614,7 +2567,7 @@ mysql_execute_command(THD *thd)
mysql_update_log.write(thd, thd->query, thd->query_length);
if (mysql_bin_log.is_open())
{
- Query_log_event qinfo(thd, thd->query, thd->query_length);
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
mysql_bin_log.write(&qinfo);
}
}
@@ -2634,7 +2587,7 @@ mysql_execute_command(THD *thd)
mysql_update_log.write(thd, thd->query, thd->query_length);
if (mysql_bin_log.is_open())
{
- Query_log_event qinfo(thd, thd->query, thd->query_length);
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
mysql_bin_log.write(&qinfo);
}
if (mqh_used && lex->sql_command == SQLCOM_GRANT)
@@ -2851,6 +2804,8 @@ check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables,
TABLE_LIST *org_tables=tables;
for (; tables ; tables=tables->next)
{
+ if (tables->derived || (tables->table && (int)tables->table->tmp_table))
+ continue;
if ((thd->master_access & want_access) == (want_access & ~EXTRA_ACL) &&
thd->db)
tables->grant.privilege= want_access;
@@ -2867,7 +2822,7 @@ check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables,
found=1;
}
}
- else if (tables->db && check_access(thd,want_access,tables->db,&tables->grant.privilege,
+ else if (check_access(thd,want_access,tables->db,&tables->grant.privilege,
0, no_errors))
return TRUE;
}
@@ -2984,26 +2939,27 @@ void
mysql_init_query(THD *thd)
{
DBUG_ENTER("mysql_init_query");
- thd->lex.unit.init_query();
- thd->lex.unit.init_select();
- thd->lex.select_lex.init_query();
- thd->lex.unit.slave= &thd->lex.select_lex;
- thd->lex.unit.global_parameters= &thd->lex.select_lex; //Global limit & order
- thd->lex.select_lex.master= &thd->lex.unit;
- thd->lex.select_lex.prev= &thd->lex.unit.slave;
- thd->select_number= thd->lex.select_lex.select_number= 1;
- thd->lex.value_list.empty();
+ LEX *lex=&thd->lex;
+ lex->unit.init_query();
+ lex->unit.init_select();
+ lex->select_lex.init_query();
+ lex->value_list.empty();
+ lex->param_list.empty();
+ lex->unit.global_parameters= lex->unit.slave= lex->current_select=
+ &lex->select_lex;
+ lex->select_lex.master= &lex->unit;
+ lex->select_lex.prev= &lex->unit.slave;
+ lex->olap=lex->describe=0;
+ lex->derived_tables= false;
+ thd->check_loops_counter= thd->select_number=
+ lex->select_lex.select_number= 1;
thd->free_list= 0;
- thd->lex.current_select= &thd->lex.select_lex;
- thd->lex.olap=thd->lex.describe=0;
- thd->lex.select_lex.olap= UNSPECIFIED_OLAP_TYPE;
- thd->fatal_error= 0; // Safety
thd->total_warn_count=0; // Warnings for this query
thd->last_insert_id_used= thd->query_start_used= thd->insert_id_used=0;
thd->sent_row_count= thd->examined_row_count= 0;
- thd->rand_used=0;
+ thd->fatal_error= thd->rand_used= 0;
thd->safe_to_cache_query= 1;
- thd->lex.param_list.empty();
+ thd->possible_loops= 0;
DBUG_VOID_RETURN;
}
@@ -3015,7 +2971,6 @@ mysql_init_select(LEX *lex)
select_lex->init_select();
select_lex->master_unit()->select_limit= select_lex->select_limit=
lex->thd->variables.select_limit;
- select_lex->olap= UNSPECIFIED_OLAP_TYPE;
lex->exchange= 0;
lex->result= 0;
lex->proc_list.first= 0;
@@ -3099,14 +3054,13 @@ mysql_parse(THD *thd, char *inBuf, uint length)
mysql_init_query(thd);
thd->query_length = length;
- thd->lex.derived_tables= false;
if (query_cache_send_result_to_client(thd, inBuf, length) <= 0)
{
LEX *lex=lex_start(thd, (uchar*) inBuf, length);
if (!yyparse() && ! thd->fatal_error)
{
if (mqh_used && thd->user_connect &&
- check_mqh(thd, thd->lex.sql_command))
+ check_mqh(thd, lex->sql_command))
{
thd->net.error = 0;
}
@@ -3155,6 +3109,7 @@ bool add_field_to_list(char *field_name, enum_field_types type,
THD *thd=current_thd;
LEX *lex= &thd->lex;
uint allowed_type_modifier=0;
+ char warn_buff[MYSQL_ERRMSG_SIZE];
DBUG_ENTER("add_field_to_list");
if (strlen(field_name) > NAME_LEN)
@@ -3246,8 +3201,6 @@ bool add_field_to_list(char *field_name, enum_field_types type,
if (!length) new_field->length=20;
allowed_type_modifier= AUTO_INCREMENT_FLAG;
break;
- case FIELD_TYPE_STRING:
- case FIELD_TYPE_VAR_STRING:
case FIELD_TYPE_NULL:
case FIELD_TYPE_GEOMETRY:
break;
@@ -3258,10 +3211,35 @@ bool add_field_to_list(char *field_name, enum_field_types type,
if (new_field->decimals)
new_field->length++;
break;
+ case FIELD_TYPE_STRING:
+ case FIELD_TYPE_VAR_STRING:
+ if (new_field->length < MAX_FIELD_WIDTH || default_value)
+ break;
+ /* Convert long CHAR() and VARCHAR columns to TEXT or BLOB */
+ new_field->sql_type= FIELD_TYPE_BLOB;
+ sprintf(warn_buff, ER(ER_AUTO_CONVERT), field_name, "CHAR",
+ (cs == my_charset_bin) ? "BLOB" : "TEXT");
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_AUTO_CONVERT,
+ warn_buff);
+ /* fall through */
case FIELD_TYPE_BLOB:
case FIELD_TYPE_TINY_BLOB:
case FIELD_TYPE_LONG_BLOB:
case FIELD_TYPE_MEDIUM_BLOB:
+ if (new_field->length)
+ {
+ /* The user has given a length to the blob column */
+ if (new_field->length < 256)
+ type= FIELD_TYPE_TINY_BLOB;
+ if (new_field->length < 65536)
+ type= FIELD_TYPE_BLOB;
+ else if (new_field->length < 256L*256L*256L)
+ type= FIELD_TYPE_MEDIUM_BLOB;
+ else
+ type= FIELD_TYPE_LONG_BLOB;
+ new_field->length= 0;
+ }
+ new_field->sql_type= type;
if (default_value) // Allow empty as default value
{
String str,*res;
@@ -3514,7 +3492,8 @@ TABLE_LIST *st_select_lex::add_table_to_list(Table_ident *table,
DBUG_RETURN(0); // End of memory
alias_str= alias ? alias->str : table->table.str;
if (table->table.length > NAME_LEN ||
- (table->table.length && check_table_name(table->table.str,table->table.length)) ||
+ (table->table.length &&
+ check_table_name(table->table.str,table->table.length)) ||
table->db.str && check_db_name(table->db.str))
{
net_printf(thd,ER_WRONG_TABLE_NAME,table->table.str);
@@ -3581,14 +3560,49 @@ TABLE_LIST *st_select_lex::add_table_to_list(Table_ident *table,
}
+/*
+ Set lock for all tables in current select level
+
+ SYNOPSIS:
+ set_lock_for_tables()
+ lock_type Lock to set for tables
+
+ NOTE:
+ If lock is a write lock, then tables->updating is set 1
+ This is to get tables_ok to know that the table is updated by the
+ query
+*/
+
+void st_select_lex::set_lock_for_tables(thr_lock_type lock_type)
+{
+ bool for_update= lock_type >= TL_READ_NO_INSERT;
+ DBUG_ENTER("set_lock_for_tables");
+ DBUG_PRINT("enter", ("lock_type: %d for_update: %d", lock_type,
+ for_update));
+
+ for (TABLE_LIST *tables= (TABLE_LIST*) table_list.first ;
+ tables ;
+ tables=tables->next)
+ {
+ tables->lock_type= lock_type;
+ tables->updating= for_update;
+ }
+ DBUG_VOID_RETURN;
+}
+
+
void add_join_on(TABLE_LIST *b,Item *expr)
{
- if (!b->on_expr)
- b->on_expr=expr;
- else
+ if (expr)
{
- // This only happens if you have both a right and left join
- b->on_expr=new Item_cond_and(b->on_expr,expr);
+ if (!b->on_expr)
+ b->on_expr=expr;
+ else
+ {
+ // This only happens if you have both a right and left join
+ b->on_expr=new Item_cond_and(b->on_expr,expr);
+ }
+ b->on_expr->top_level_item();
}
}
@@ -3616,7 +3630,7 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables)
if (options & REFRESH_GRANT)
{
acl_reload(thd);
- grant_reload();
+ grant_reload(thd);
if (mqh_used)
reset_mqh(thd,(LEX_USER *) NULL,true);
}
diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc
index a9ab1776e19..5b0ec2ec843 100644
--- a/sql/sql_rename.cc
+++ b/sql/sql_rename.cc
@@ -94,7 +94,7 @@ end:
mysql_update_log.write(thd,thd->query,thd->query_length);
if (mysql_bin_log.is_open())
{
- Query_log_event qinfo(thd, thd->query, thd->query_length);
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
mysql_bin_log.write(&qinfo);
}
send_ok(thd);
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index 93545d10268..23951cec29f 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -941,7 +941,7 @@ int show_binlog_events(THD* thd)
if (mysql_bin_log.is_open())
{
LEX_MASTER_INFO *lex_mi = &thd->lex.mi;
- uint event_count, limit_start, limit_end;
+ ha_rows event_count, limit_start, limit_end;
my_off_t pos = lex_mi->pos;
char search_file_name[FN_REFLEN], *name;
const char *log_file_name = lex_mi->log_file_name;
@@ -1133,7 +1133,8 @@ int log_loaded_block(IO_CACHE* file)
lf_info->last_pos_in_file = file->pos_in_file;
if (lf_info->wrote_create_file)
{
- Append_block_log_event a(lf_info->thd, buffer, block_len);
+ Append_block_log_event a(lf_info->thd, buffer, block_len,
+ lf_info->log_delayed);
mysql_bin_log.write(&a);
}
else
@@ -1141,7 +1142,7 @@ int log_loaded_block(IO_CACHE* file)
Create_file_log_event c(lf_info->thd,lf_info->ex,lf_info->db,
lf_info->table_name, *lf_info->fields,
lf_info->handle_dup, buffer,
- block_len);
+ block_len, lf_info->log_delayed);
mysql_bin_log.write(&c);
lf_info->wrote_create_file = 1;
DBUG_SYNC_POINT("debug_lock.created_file_event",10);
diff --git a/sql/sql_repl.h b/sql/sql_repl.h
index 197fd03ec7c..15435382b08 100644
--- a/sql/sql_repl.h
+++ b/sql/sql_repl.h
@@ -43,13 +43,13 @@ int check_binlog_magic(IO_CACHE* log, const char** errmsg);
typedef struct st_load_file_info
{
THD* thd;
+ my_off_t last_pos_in_file;
sql_exchange* ex;
List <Item> *fields;
enum enum_duplicates handle_dup;
char* db;
char* table_name;
- bool wrote_create_file;
- my_off_t last_pos_in_file;
+ bool wrote_create_file, log_delayed;
} LOAD_FILE_INFO;
int log_loaded_block(IO_CACHE* file);
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index b9162daadaa..20b000392df 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -324,6 +324,7 @@ JOIN::prepare(TABLE_LIST *tables_init,
this->group= group_list != 0;
row_limit= ((select_distinct || order || group_list) ? HA_POS_ERROR :
unit->select_limit_cnt);
+ do_send_rows = (unit->select_limit_cnt) ? 1 : 0;
this->unit= unit;
#ifdef RESTRICTED_GROUP
@@ -366,19 +367,24 @@ JOIN::optimize()
{
conds->fix_fields(thd, tables_list, &conds);
conds->change_ref_to_fields(thd, tables_list);
+ conds->top_level_item();
having= 0;
}
}
#endif
- conds=optimize_cond(conds,&cond_value);
- if (thd->fatal_error || thd->net.report_error)
+ conds= optimize_cond(conds,&cond_value);
+ if (thd->fatal_error)
{
+ // quick abort
delete procedure;
- error = 0;
+ error= 0;
DBUG_RETURN(1);
- }
- if (cond_value == Item::COND_FALSE || !unit->select_limit_cnt)
+ } else if (thd->net.report_error)
+ // normal error processing & cleanup
+ DBUG_RETURN(-1);
+
+ if (cond_value == Item::COND_FALSE || (!unit->select_limit_cnt && !(select_options & OPTION_FOUND_ROWS)))
{ /* Impossible cond */
zero_result_cause= "Impossible WHERE";
DBUG_RETURN(0);
@@ -395,13 +401,7 @@ JOIN::optimize()
zero_result_cause= "No matching min/max row";
DBUG_RETURN(0);
}
- if (select_options & SELECT_DESCRIBE)
- {
- select_describe(this, false, false, false,
- "Select tables optimized away");
- delete procedure;
- DBUG_RETURN(1);
- }
+ zero_result_cause= "Select tables optimized away";
tables_list= 0; // All tables resolved
}
}
@@ -663,7 +663,8 @@ JOIN::exec()
{ // Only test of functions
error=0;
if (select_options & SELECT_DESCRIBE)
- select_describe(this, false, false, false, "No tables used");
+ select_describe(this, false, false, false,
+ (zero_result_cause?zero_result_cause:"No tables used"));
else
{
result->send_fields(fields_list,1);
@@ -672,7 +673,10 @@ JOIN::exec()
if (do_send_rows && result->send_data(fields_list))
error= 1;
else
+ {
error= (int) result->send_eof();
+ send_records=1;
+ }
}
else
error=(int) result->send_eof();
@@ -957,6 +961,7 @@ JOIN::exec()
sort_table_cond)))
DBUG_VOID_RETURN;
table->select_cond=table->select->cond;
+ table->select_cond->top_level_item();
DBUG_EXECUTE("where",print_where(table->select->cond,
"select and having"););
having_list= make_cond_for_table(having_list, ~ (table_map) 0,
@@ -994,7 +999,8 @@ JOIN::exec()
}
having=having_list; // Actually a parameter
thd->proc_info="Sending data";
- error=do_select(this, &fields_list, NULL, procedure);
+ error= thd->net.report_error ||
+ do_select(this, &fields_list, NULL, procedure);
DBUG_VOID_RETURN;
}
@@ -1034,6 +1040,24 @@ JOIN::cleanup(THD *thd)
DBUG_RETURN(error);
}
+bool JOIN::check_loop(uint id)
+{
+ DBUG_ENTER("JOIN::check_loop");
+ Item *item;
+ List_iterator<Item> it(all_fields);
+ DBUG_PRINT("info", ("all_fields:"));
+ while ((item= it++))
+ if (item->check_loop(id))
+ DBUG_RETURN(1);
+ DBUG_PRINT("info", ("where:"));
+ if (select_lex->where && select_lex->where->check_loop(id))
+ DBUG_RETURN(1);
+ DBUG_PRINT("info", ("having:"));
+ if (select_lex->having && select_lex->having->check_loop(id))
+ DBUG_RETURN(1);
+ DBUG_RETURN(0);
+}
+
int
mysql_select(THD *thd, TABLE_LIST *tables, List<Item> &fields, COND *conds,
ORDER *order, ORDER *group,Item *having, ORDER *proc_param,
@@ -1068,6 +1092,23 @@ mysql_select(THD *thd, TABLE_LIST *tables, List<Item> &fields, COND *conds,
{
DBUG_RETURN(-1);
}
+ if (thd->possible_loops)
+ {
+ Item *item;
+ while(thd->possible_loops->elements)
+ {
+ item= thd->possible_loops->pop();
+ if (item->check_loop(thd->check_loops_counter++))
+ {
+ delete thd->possible_loops;
+ thd->possible_loops= 0;
+ my_message(ER_CYCLIC_REFERENCE, ER(ER_CYCLIC_REFERENCE), MYF(0));
+ return 1;
+ }
+ }
+ delete thd->possible_loops;
+ thd->possible_loops= 0;
+ }
}
switch (join->optimize())
@@ -1078,7 +1119,7 @@ mysql_select(THD *thd, TABLE_LIST *tables, List<Item> &fields, COND *conds,
goto err;
}
- if (free_join && join->global_optimize())
+ if (thd->net.report_error || (free_join && join->global_optimize()))
goto err;
join->exec();
@@ -1393,7 +1434,7 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
select->quick=0;
if (records != HA_POS_ERROR)
{
- s->found_records=records;
+ s->records=s->found_records=records;
s->read_time= (ha_rows) (s->quick ? s->quick->read_time : 0.0);
}
}
@@ -1926,7 +1967,7 @@ static void
find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
double read_time)
{
- ulong rec;
+ ha_rows rec;
double tmp;
THD *thd= join->thd;
@@ -2119,7 +2160,7 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
records
This gives the formula:
records= (x * (b-a) + a*c-b)/(c-1)
-
+
b = records matched by whole key
a = records matched by first key part (10% of all records?)
c = number of key parts in key
@@ -2188,7 +2229,7 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
{ // Check full join
if (s->on_expr)
{
- tmp=s->found_records; // Can't use read cache
+ tmp=rows2double(s->found_records); // Can't use read cache
}
else
{
@@ -2207,11 +2248,11 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
will ensure that this will be used
*/
best=tmp;
- records=s->found_records;
+ records= rows2double(s->found_records);
best_key=0;
}
}
- join->positions[idx].records_read=(double) records;
+ join->positions[idx].records_read= records;
join->positions[idx].key=best_key;
join->positions[idx].table= s;
if (!best_key && idx == join->const_tables &&
@@ -2548,7 +2589,7 @@ bool
store_val_in_field(Field *field,Item *item)
{
THD *thd=current_thd;
- ulong cuted_fields=thd->cuted_fields;
+ ha_rows cuted_fields=thd->cuted_fields;
thd->count_cuted_fields=1;
(void) item->save_in_field(field);
thd->count_cuted_fields=0;
@@ -2577,8 +2618,8 @@ make_simple_join(JOIN *join,TABLE *tmp_table)
join->sum_funcs=0;
join->send_records=(ha_rows) 0;
join->group=0;
- join->do_send_rows = 1;
join->row_limit=join->unit->select_limit_cnt;
+ join->do_send_rows = (join->row_limit) ? 1 : 0;
join_tab->cache.buff=0; /* No cacheing */
join_tab->table=tmp_table;
@@ -2636,7 +2677,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
use_quick_range=1;
tab->use_quick=1;
tab->ref.key_parts=0; // Don't use ref key.
- join->best_positions[i].records_read=tab->quick->records;
+ join->best_positions[i].records_read= rows2double(tab->quick->records);
}
COND *tmp=make_cond_for_table(cond,used_tables,current_map);
@@ -2911,27 +2952,43 @@ join_free(JOIN *join)
*/
if (join->tables > join->const_tables) // Test for not-const tables
free_io_cache(join->table[join->const_tables]);
- for (tab=join->join_tab,end=tab+join->tables ; tab != end ; tab++)
+ if (join->select_lex->dependent)
+ for (tab=join->join_tab,end=tab+join->tables ; tab != end ; tab++)
+ {
+ if (tab->table)
+ {
+ if (tab->table->key_read)
+ {
+ tab->table->key_read= 0;
+ tab->table->file->extra(HA_EXTRA_NO_KEYREAD);
+ }
+ /* Don't free index if we are using read_record */
+ if (!tab->read_record.table)
+ tab->table->file->index_end();
+ }
+ }
+ else
{
- delete tab->select;
- delete tab->quick;
- x_free(tab->cache.buff);
- if (tab->table)
+ for (tab=join->join_tab,end=tab+join->tables ; tab != end ; tab++)
{
- if (tab->table->key_read)
+ delete tab->select;
+ delete tab->quick;
+ x_free(tab->cache.buff);
+ if (tab->table)
{
- tab->table->key_read=0;
- tab->table->file->extra(HA_EXTRA_NO_KEYREAD);
+ if (tab->table->key_read)
+ {
+ tab->table->key_read= 0;
+ tab->table->file->extra(HA_EXTRA_NO_KEYREAD);
+ }
+ /* Don't free index if we are using read_record */
+ if (!tab->read_record.table)
+ tab->table->file->index_end();
}
- /* Don't free index if we are using read_record */
- if (!tab->read_record.table)
- tab->table->file->index_end();
+ end_read_record(&tab->read_record);
}
- end_read_record(&tab->read_record);
+ join->table= 0;
}
- //TODO: is enough join_free at the end of mysql_select?
- if (!join->select_lex->dependent)
- join->table=0;
}
/*
We are not using tables anymore
@@ -3893,7 +3950,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
*blob_field= 0; // End marker
/* If result table is small; use a heap */
- if (blob_count || using_unique_constraint || group_null_items ||
+ if (blob_count || using_unique_constraint ||
(select_options & (OPTION_BIG_TABLES | SELECT_SMALL_RESULT)) ==
OPTION_BIG_TABLES)
{
@@ -4512,7 +4569,7 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
if (error == -1)
table->file->print_error(my_errno,MYF(0));
}
- DBUG_RETURN(error);
+ DBUG_RETURN(error || join->thd->net.report_error);
}
@@ -5492,6 +5549,8 @@ end_write_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
}
else
{
+ if (end_of_records)
+ DBUG_RETURN(0);
join->first_record=1;
VOID(test_if_group_changed(join->group_fields));
}
@@ -5561,6 +5620,7 @@ make_cond_for_table(COND *cond,table_map tables,table_map used_table)
{
if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
{
+ /* Create new top level AND item */
Item_cond_and *new_cond=new Item_cond_and;
if (!new_cond)
return (COND*) 0; // OOM /* purecov: inspected */
@@ -5598,6 +5658,7 @@ make_cond_for_table(COND *cond,table_map tables,table_map used_table)
new_cond->argument_list()->push_back(fix);
}
new_cond->used_tables_cache=((Item_cond_or*) cond)->used_tables_cache;
+ new_cond->top_level_item();
return new_cond;
}
}
@@ -5949,6 +6010,7 @@ static bool fix_having(JOIN *join, Item **having)
sort_table_cond)))
return 1;
table->select_cond=table->select->cond;
+ table->select_cond->top_level_item();
DBUG_EXECUTE("where",print_where(table->select_cond,
"select and having"););
*having=make_cond_for_table(*having,~ (table_map) 0,~used_tables);
@@ -7377,56 +7439,32 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
{
if (tab->use_quick == 2)
{
- sprintf(buff_ptr,"range checked for each record (index map: %u)",
+ sprintf(buff_ptr,"; Range checked for each record (index map: %u)",
tab->keys);
buff_ptr=strend(buff_ptr);
}
else
- buff_ptr=strmov(buff_ptr,"where used");
+ buff_ptr=strmov(buff_ptr,"; Using where");
}
if (key_read)
- {
- if (buff != buff_ptr)
- {
- buff_ptr[0]=';' ; buff_ptr[1]=' '; buff_ptr+=2;
- }
- buff_ptr=strmov(buff_ptr,"Using index");
- }
+ buff_ptr= strmov(buff_ptr,"; Using index");
if (table->reginfo.not_exists_optimize)
- {
- if (buff != buff_ptr)
- {
- buff_ptr[0]=';' ; buff_ptr[1]=' '; buff_ptr+=2;
- }
- buff_ptr=strmov(buff_ptr,"Not exists");
- }
+ buff_ptr= strmov(buff_ptr,"; Not exists");
if (need_tmp_table)
{
need_tmp_table=0;
- if (buff != buff_ptr)
- {
- buff_ptr[0]=';' ; buff_ptr[1]=' '; buff_ptr+=2;
- }
- buff_ptr=strmov(buff_ptr,"Using temporary");
+ buff_ptr= strmov(buff_ptr,"; Using temporary");
}
if (need_order)
{
need_order=0;
- if (buff != buff_ptr)
- {
- buff_ptr[0]=';' ; buff_ptr[1]=' '; buff_ptr+=2;
- }
- buff_ptr=strmov(buff_ptr,"Using filesort");
+ buff_ptr= strmov(buff_ptr,"; Using filesort");
}
if (distinct & test_all_bits(used_tables,thd->used_tables))
- {
- if (buff != buff_ptr)
- {
- buff_ptr[0]=';' ; buff_ptr[1]=' '; buff_ptr+=2;
- }
- buff_ptr=strmov(buff_ptr,"Distinct");
- }
- item_list.push_back(new Item_string(buff,(uint) (buff_ptr - buff),
+ buff_ptr= strmov(buff_ptr,"; Distinct");
+ if (buff_ptr == buff)
+ buff_ptr+= 2; // Skip inital "; "
+ item_list.push_back(new Item_string(buff+2,(uint) (buff_ptr - buff)-2,
default_charset_info));
// For next iteration
used_tables|=table->map;
@@ -7458,8 +7496,10 @@ int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result)
((sl->next_select_in_list())?"PRIMARY":
"SIMPLE"):
((sl == first)?
+ ((sl->linkage == DERIVED_TABLE_TYPE) ?
+ "DERIVED":
((sl->dependent)?"DEPENDENT SUBSELECT":
- "SUBSELECT"):
+ "SUBSELECT")):
((sl->dependent)?"DEPENDENT UNION":
"UNION"))),
result);
@@ -7467,8 +7507,8 @@ int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result)
break;
}
- if (res > 0)
- res= -res; // mysql_explain_select do not report error
+ if (res > 0 || thd->net.report_error)
+ res= -1; // mysql_explain_select do not report error
DBUG_RETURN(res);
}
diff --git a/sql/sql_select.h b/sql/sql_select.h
index c5b5357be50..3b89c1ce0d3 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -244,7 +244,8 @@ class JOIN :public Sql_alloc
int global_optimize();
int reinit();
void exec();
- int cleanup(THD *thd);
+ int cleanup(THD *thd);
+ bool check_loop(uint id);
};
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index d6fe2f3772a..ebf5b210d6c 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -889,7 +889,7 @@ mysqld_show_keys(THD *thd, TABLE_LIST *table_list)
field_list.push_back(new Item_empty_string("Column_name",NAME_LEN));
field_list.push_back(item=new Item_empty_string("Collation",1));
item->maybe_null=1;
- field_list.push_back(item=new Item_int("Cardinality",0,11));
+ field_list.push_back(item=new Item_int("Cardinality",0,21));
item->maybe_null=1;
field_list.push_back(item=new Item_int("Sub_part",0,3));
item->maybe_null=1;
@@ -930,8 +930,8 @@ mysqld_show_keys(THD *thd, TABLE_LIST *table_list)
KEY *key=table->key_info+i;
if (key->rec_per_key[j])
{
- ulong records=(table->file->records / key->rec_per_key[j]);
- end=int10_to_str((long) records, buff, 10);
+ ha_rows records=(table->file->records / key->rec_per_key[j]);
+ end=longlong10_to_str((longlong) records, buff, 10);
net_store_data(packet,convert,buff,(uint) (end-buff));
}
else
@@ -1140,6 +1140,10 @@ store_create_info(THD *thd, TABLE *table, String *packet)
if (!found_primary)
append_identifier(thd,packet,key_info->name);
+ if (table->db_type == DB_TYPE_HEAP &&
+ key_info->algorithm == HA_KEY_ALG_BTREE)
+ packet->append(" USING BTREE", 12);
+
// +BAR: send USING only in non-default case: non-spatial rtree
if((key_info->algorithm == HA_KEY_ALG_RTREE) &&
!(key_info->flags & HA_SPATIAL))
@@ -1424,7 +1428,7 @@ int mysqld_show_charsets(THD *thd, const char *wild)
net_store_data(&packet2,convert,cs[0]->name);
net_store_data(&packet2,(uint32) cs[0]->number);
net_store_data(&packet2,(uint32) cs[0]->strxfrm_multiply);
- net_store_data(&packet2,(uint32) (cs[0]->mbmaxlen ? cs[0]->mbmaxlen : 1));
+ net_store_data(&packet2,(uint32) (cs[0]->mbmaxlen));
if (my_net_write(&thd->net, (char*) packet2.ptr(),packet2.length()))
goto err;
diff --git a/sql/sql_string.cc b/sql/sql_string.cc
index f0f31004544..5083fb13105 100644
--- a/sql/sql_string.cc
+++ b/sql/sql_string.cc
@@ -93,18 +93,36 @@ bool String::realloc(uint32 alloc_length)
bool String::set(longlong num, CHARSET_INFO *cs)
{
- if (alloc(21))
+ uint l=20*cs->mbmaxlen+1;
+
+ if (alloc(l))
return TRUE;
- str_length=(uint32) (longlong10_to_str(num,Ptr,-10)-Ptr);
+ if (cs->snprintf == my_snprintf_8bit)
+ {
+ str_length=(uint32) (longlong10_to_str(num,Ptr,-10)-Ptr);
+ }
+ else
+ {
+ str_length=cs->snprintf(cs,Ptr,l,"%d",num);
+ }
str_charset=cs;
return FALSE;
}
bool String::set(ulonglong num, CHARSET_INFO *cs)
{
- if (alloc(21))
+ uint l=20*cs->mbmaxlen+1;
+
+ if (alloc(l))
return TRUE;
- str_length=(uint32) (longlong10_to_str(num,Ptr,10)-Ptr);
+ if (cs->snprintf == my_snprintf_8bit)
+ {
+ str_length=(uint32) (longlong10_to_str(num,Ptr,10)-Ptr);
+ }
+ else
+ {
+ str_length=cs->snprintf(cs,Ptr,l,"%d",num);
+ }
str_charset=cs;
return FALSE;
}
@@ -117,14 +135,14 @@ bool String::set(double num,uint decimals, CHARSET_INFO *cs)
if (decimals >= NOT_FIXED_DEC)
{
sprintf(buff,"%.14g",num); // Enough for a DATETIME
- return copy(buff, (uint32) strlen(buff), my_charset_latin1);
+ return copy(buff, (uint32) strlen(buff), my_charset_latin1, cs);
}
#ifdef HAVE_FCONVERT
int decpt,sign;
char *pos,*to;
VOID(fconvert(num,(int) decimals,&decpt,&sign,buff+1));
- if (!my_isdigit(system_charset_info, buff[1]))
+ if (!my_isdigit(my_charset_latin1, buff[1]))
{ // Nan or Inf
pos=buff+1;
if (sign)
@@ -132,7 +150,7 @@ bool String::set(double num,uint decimals, CHARSET_INFO *cs)
buff[0]='-';
pos=buff;
}
- return copy(pos,(uint32) strlen(pos));
+ return copy(pos,(uint32) strlen(pos), my_charset_latin1, cs);
}
if (alloc((uint32) ((uint32) decpt+3+decimals)))
return TRUE;
@@ -182,7 +200,7 @@ end:
#else
sprintf(buff,"%.*f",(int) decimals,num);
#endif
- return copy(buff,(uint32) strlen(buff), my_charset_latin1);
+ return copy(buff,(uint32) strlen(buff), my_charset_latin1, cs);
#endif
}
@@ -219,6 +237,55 @@ bool String::copy(const char *str,uint32 arg_length, CHARSET_INFO *cs)
return FALSE;
}
+/* Copy with charset convertion */
+bool String::copy(const char *str,uint32 arg_length, CHARSET_INFO *from, CHARSET_INFO *to)
+{
+ uint32 new_length=to->mbmaxlen*arg_length;
+ int cnvres;
+ my_wc_t wc;
+ const uchar *s=(const uchar *)str;
+ const uchar *se=s+arg_length;
+ uchar *d, *de;
+
+ if (alloc(new_length))
+ return TRUE;
+
+ d=(uchar *)Ptr;
+ de=d+new_length;
+
+ for (str_length=new_length ; s < se && d < de ; )
+ {
+ if ((cnvres=from->mb_wc(from,&wc,s,se)) > 0 )
+ {
+ s+=cnvres;
+ }
+ else if (cnvres==MY_CS_ILSEQ)
+ {
+ s++;
+ wc='?';
+ }
+ else
+ break;
+
+outp:
+ if((cnvres=to->wc_mb(to,wc,d,de)) >0 )
+ {
+ d+=cnvres;
+ }
+ else if (cnvres==MY_CS_ILUNI && wc!='?')
+ {
+ wc='?';
+ goto outp;
+ }
+ else
+ break;
+ }
+ Ptr[new_length]=0;
+ length((uint32) (d-(uchar *)Ptr));
+ str_charset=to;
+ return FALSE;
+}
+
/* This is used by mysql.cc */
bool String::fill(uint32 max_length,char fill_char)
@@ -604,261 +671,5 @@ String *copy_if_not_alloced(String *to,String *from,uint32 from_length)
return to;
}
-/* Make it easier to handle different charactersets */
-
-#ifdef USE_MB
-#define INC_PTR(cs,A,B) A+=((use_mb_flag && \
- my_ismbchar(cs,A,B)) ? my_ismbchar(cs,A,B) : 1)
-#else
-#define INC_PTR(cs,A,B) A++
-#endif
-
-/*
-** Compare string against string with wildcard
-** 0 if matched
-** -1 if not matched with wildcard
-** 1 if matched with wildcard
-*/
-
-#ifdef LIKE_CMP_TOUPPER
-#define likeconv(s,A) (uchar) my_toupper(s,A)
-#else
-#define likeconv(s,A) (uchar) (s)->sort_order[(uchar) (A)]
-#endif
-
-int wild_case_compare(CHARSET_INFO *cs, const char *str,const char *str_end,
- const char *wildstr,const char *wildend,
- char escape)
-{
- int result= -1; // Not found, using wildcards
-#ifdef USE_MB
- bool use_mb_flag=use_mb(cs);
-#endif
- while (wildstr != wildend)
- {
- while (*wildstr != wild_many && *wildstr != wild_one)
- {
- if (*wildstr == escape && wildstr+1 != wildend)
- wildstr++;
-#ifdef USE_MB
- int l;
- if (use_mb_flag &&
- (l = my_ismbchar(cs, wildstr, wildend)))
- {
- if (str+l > str_end || memcmp(str, wildstr, l) != 0)
- return 1;
- str += l;
- wildstr += l;
- }
- else
-#endif
- if (str == str_end || likeconv(cs,*wildstr++) != likeconv(cs,*str++))
- return(1); // No match
- if (wildstr == wildend)
- return (str != str_end); // Match if both are at end
- result=1; // Found an anchor char
- }
- if (*wildstr == wild_one)
- {
- do
- {
- if (str == str_end) // Skip one char if possible
- return (result);
- INC_PTR(cs,str,str_end);
- } while (++wildstr < wildend && *wildstr == wild_one);
- if (wildstr == wildend)
- break;
- }
- if (*wildstr == wild_many)
- { // Found wild_many
- wildstr++;
- /* Remove any '%' and '_' from the wild search string */
- for (; wildstr != wildend ; wildstr++)
- {
- if (*wildstr == wild_many)
- continue;
- if (*wildstr == wild_one)
- {
- if (str == str_end)
- return (-1);
- INC_PTR(cs,str,str_end);
- continue;
- }
- break; // Not a wild character
- }
- if (wildstr == wildend)
- return(0); // Ok if wild_many is last
- if (str == str_end)
- return -1;
-
- uchar cmp;
- if ((cmp= *wildstr) == escape && wildstr+1 != wildend)
- cmp= *++wildstr;
-#ifdef USE_MB
- const char* mb = wildstr;
- int mblen;
- LINT_INIT(mblen);
- if (use_mb_flag)
- mblen = my_ismbchar(cs, wildstr, wildend);
-#endif
- INC_PTR(cs,wildstr,wildend); // This is compared trough cmp
- cmp=likeconv(cs,cmp);
- do
- {
-#ifdef USE_MB
- if (use_mb_flag)
- {
- for (;;)
- {
- if (str >= str_end)
- return -1;
- if (mblen)
- {
- if (str+mblen <= str_end && memcmp(str, mb, mblen) == 0)
- {
- str += mblen;
- break;
- }
- }
- else if (!my_ismbchar(cs, str, str_end) &&
- likeconv(cs,*str) == cmp)
- {
- str++;
- break;
- }
- INC_PTR(cs,str, str_end);
- }
- }
- else
- {
-#endif /* USE_MB */
- while (str != str_end && likeconv(cs,*str) != cmp)
- str++;
- if (str++ == str_end) return (-1);
-#ifdef USE_MB
- }
-#endif
- {
- int tmp=wild_case_compare(cs,str,str_end,wildstr,wildend,escape);
- if (tmp <= 0)
- return (tmp);
- }
- } while (str != str_end && wildstr[0] != wild_many);
- return(-1);
- }
- }
- return (str != str_end ? 1 : 0);
-}
-
-
-int wild_case_compare(String &match,String &wild, char escape)
-{
- DBUG_ENTER("wild_case_compare");
- DBUG_PRINT("enter",("match='%s', wild='%s', escape='%c'"
- ,match.ptr(),wild.ptr(),escape));
- DBUG_RETURN(wild_case_compare(match.str_charset,match.ptr(),match.ptr()+match.length(),
- wild.ptr(), wild.ptr()+wild.length(),escape));
-}
-
-/*
-** The following is used when using LIKE on binary strings
-*/
-
-int wild_compare(const char *str,const char *str_end,
- const char *wildstr,const char *wildend,char escape)
-{
- DBUG_ENTER("wild_compare");
- DBUG_PRINT("enter",("str='%s', str_end='%s', wildstr='%s', wildend='%s', escape='%c'"
- ,str,str_end,wildstr,wildend,escape));
- int result= -1; // Not found, using wildcards
- while (wildstr != wildend)
- {
- while (*wildstr != wild_many && *wildstr != wild_one)
- {
- if (*wildstr == escape && wildstr+1 != wildend)
- wildstr++;
- if (str == str_end || *wildstr++ != *str++)
- {
- DBUG_RETURN(1);
- }
- if (wildstr == wildend)
- {
- DBUG_RETURN(str != str_end); // Match if both are at end
- }
- result=1; // Found an anchor char
- }
- if (*wildstr == wild_one)
- {
- do
- {
- if (str == str_end) // Skip one char if possible
- DBUG_RETURN(result);
- str++;
- } while (*++wildstr == wild_one && wildstr != wildend);
- if (wildstr == wildend)
- break;
- }
- if (*wildstr == wild_many)
- { // Found wild_many
- wildstr++;
- /* Remove any '%' and '_' from the wild search string */
- for (; wildstr != wildend ; wildstr++)
- {
- if (*wildstr == wild_many)
- continue;
- if (*wildstr == wild_one)
- {
- if (str == str_end)
- {
- DBUG_RETURN(-1);
- }
- str++;
- continue;
- }
- break; // Not a wild character
- }
- if (wildstr == wildend)
- {
- DBUG_RETURN(0); // Ok if wild_many is last
- }
- if (str == str_end)
- {
- DBUG_RETURN(-1);
- }
- char cmp;
- if ((cmp= *wildstr) == escape && wildstr+1 != wildend)
- cmp= *++wildstr;
- wildstr++; // This is compared trough cmp
- do
- {
- while (str != str_end && *str != cmp)
- str++;
- if (str++ == str_end)
- {
- DBUG_RETURN(-1);
- }
- {
- int tmp=wild_compare(str,str_end,wildstr,wildend,escape);
- if (tmp <= 0)
- {
- DBUG_RETURN(tmp);
- }
- }
- } while (str != str_end && wildstr[0] != wild_many);
- DBUG_RETURN(-1);
- }
- }
- DBUG_RETURN(str != str_end ? 1 : 0);
-}
-
-
-int wild_compare(String &match,String &wild, char escape)
-{
- DBUG_ENTER("wild_compare");
- DBUG_PRINT("enter",("match='%s', wild='%s', escape='%c'"
- ,match.ptr(),wild.ptr(),escape));
- DBUG_RETURN(wild_compare(match.ptr(),match.ptr()+match.length(),
- wild.ptr(), wild.ptr()+wild.length(),escape));
-}
diff --git a/sql/sql_string.h b/sql/sql_string.h
index 4ac4308f113..42f9e446981 100644
--- a/sql/sql_string.h
+++ b/sql/sql_string.h
@@ -28,8 +28,6 @@ class String;
int sortcmp(const String *a,const String *b);
int stringcmp(const String *a,const String *b);
String *copy_if_not_alloced(String *a,String *b,uint32 arg_length);
-int wild_case_compare(String &match,String &wild,char escape);
-int wild_compare(String &match,String &wild,char escape);
class String
{
@@ -179,6 +177,7 @@ public:
bool copy(); // Alloc string if not alloced
bool copy(const String &s); // Allocate new string
bool copy(const char *s,uint32 arg_length, CHARSET_INFO *cs); // Allocate new string
+ bool copy(const char*s,uint32 arg_length, CHARSET_INFO *csfrom, CHARSET_INFO *csto);
bool append(const String &s);
bool append(const char *s,uint32 arg_length=0);
bool append(IO_CACHE* file, uint32 arg_length);
@@ -207,8 +206,6 @@ public:
friend int sortcmp(const String *a,const String *b);
friend int stringcmp(const String *a,const String *b);
friend String *copy_if_not_alloced(String *a,String *b,uint32 arg_length);
- friend int wild_case_compare(String &match,String &wild,char escape);
- friend int wild_compare(String &match,String &wild,char escape);
uint32 numchars();
int charpos(int i,uint32 offset=0);
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 5187351258e..00077bda39f 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -110,6 +110,17 @@ int mysql_rm_table_part2_with_lock(THD *thd,
return error;
}
+/*
+ TODO:
+ When logging to the binary log, we should log
+ tmp_tables and transactional tables as separate statements if we
+ are in a transaction; This is needed to get these tables into the
+ cached binary log that is only written on COMMIT.
+
+ The current code only writes DROP statements that only uses temporary
+ tables to the cache binary log. This should be ok on most cases, but
+ not all.
+*/
int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
bool dont_log_query)
@@ -119,7 +130,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
String wrong_tables;
db_type table_type;
int error;
- bool some_tables_deleted=0;
+ bool some_tables_deleted=0, tmp_table_deleted=0;
DBUG_ENTER("mysql_rm_table_part2");
for (table=tables ; table ; table=table->next)
@@ -127,7 +138,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
char *db=table->db ? table->db : thd->db;
if (!close_temporary_table(thd, db, table->real_name))
{
- some_tables_deleted=1; // Log query
+ tmp_table_deleted=1;
continue; // removed temporary table
}
@@ -143,8 +154,8 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
DBUG_RETURN(-1);
/* remove form file and isam files */
- (void) sprintf(path,"%s/%s/%s%s",mysql_data_home,db,table->real_name,
- reg_ext);
+ strxmov(path, mysql_data_home, "/", db, "/", table->real_name, reg_ext,
+ NullS);
(void) unpack_filename(path,path);
error=0;
@@ -177,7 +188,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
wrong_tables.append(String(table->real_name,default_charset_info));
}
}
- if (some_tables_deleted)
+ if (some_tables_deleted || tmp_table_deleted)
{
query_cache_invalidate3(thd, tables, 0);
if (!dont_log_query)
@@ -185,7 +196,8 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
mysql_update_log.write(thd, thd->query,thd->query_length);
if (mysql_bin_log.is_open())
{
- Query_log_event qinfo(thd, thd->query, thd->query_length);
+ Query_log_event qinfo(thd, thd->query, thd->query_length,
+ tmp_table_deleted && !some_tables_deleted);
mysql_bin_log.write(&qinfo);
}
}
@@ -271,7 +283,8 @@ static int sort_keys(KEY *a, KEY *b)
create_info Create information (like MAX_ROWS)
fields List of fields to create
keys List of keys to create
- tmp_table Set to 1 if this is a temporary table
+ tmp_table Set to 1 if this is an internal temporary table
+ (From ALTER TABLE)
no_log Don't log the query to binary log.
DESCRIPTION
@@ -523,19 +536,19 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
key_iterator.rewind();
key_number=0;
- for (; (key=key_iterator++) ; key_info++, key_number++)
+ for (; (key=key_iterator++) ; key_number++)
{
uint key_length=0;
key_part_spec *column;
switch(key->type){
- case Key::MULTIPLE:
+ case Key::MULTIPLE:
key_info->flags = 0;
break;
- case Key::FULLTEXT:
+ case Key::FULLTEXT:
key_info->flags = HA_FULLTEXT;
break;
- case Key::SPATIAL:
+ case Key::SPATIAL:
key_info->flags = HA_SPATIAL;
break;
case Key::FOREIGN_KEY:
@@ -734,6 +747,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
my_error(ER_TOO_LONG_KEY,MYF(0),max_key_length);
DBUG_RETURN(-1);
}
+ key_info++;
}
if (!unique_key && !primary_key &&
(file->table_flags() & HA_REQUIRE_PRIMARY_KEY))
@@ -783,7 +797,6 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
thd->proc_info="creating table";
- create_info->create_statement = thd->query;
create_info->table_options=db_options;
if (rea_create_table(thd, path, create_info, fields, key_count,
key_info_buffer))
@@ -791,16 +804,6 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
/* my_error(ER_CANT_CREATE_TABLE,MYF(0),table_name,my_errno); */
goto end;
}
- if (!tmp_table && !no_log)
- {
- // Must be written before unlock
- mysql_update_log.write(thd,thd->query, thd->query_length);
- if (mysql_bin_log.is_open())
- {
- Query_log_event qinfo(thd, thd->query, thd->query_length);
- mysql_bin_log.write(&qinfo);
- }
- }
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
{
/* Open table and put in temporary table list */
@@ -810,6 +813,18 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
goto end;
}
}
+ if (!tmp_table && !no_log)
+ {
+ // Must be written before unlock
+ mysql_update_log.write(thd,thd->query, thd->query_length);
+ if (mysql_bin_log.is_open())
+ {
+ Query_log_event qinfo(thd, thd->query, thd->query_length,
+ test(create_info->options &
+ HA_LEX_CREATE_TMP_TABLE));
+ mysql_bin_log.write(&qinfo);
+ }
+ }
error=0;
end:
VOID(pthread_mutex_unlock(&LOCK_open));
@@ -1254,8 +1269,13 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
switch (result_code) {
case HA_ADMIN_NOT_IMPLEMENTED:
- net_store_data(packet, "error");
- net_store_data(packet, ER(ER_CHECK_NOT_IMPLEMENTED));
+ {
+ char buf[ERRMSGSIZE+20];
+ my_snprintf(buf, ERRMSGSIZE,
+ ER(ER_CHECK_NOT_IMPLEMENTED), operator_name);
+ net_store_data(packet, "error");
+ net_store_data(packet, buf);
+ }
break;
case HA_ADMIN_OK:
@@ -1510,7 +1530,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
mysql_update_log.write(thd, thd->query, thd->query_length);
if (mysql_bin_log.is_open())
{
- Query_log_event qinfo(thd, thd->query, thd->query_length);
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
mysql_bin_log.write(&qinfo);
}
send_ok(thd);
@@ -1886,7 +1906,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
mysql_update_log.write(thd, thd->query,thd->query_length);
if (mysql_bin_log.is_open())
{
- Query_log_event qinfo(thd, thd->query, thd->query_length);
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
mysql_bin_log.write(&qinfo);
}
goto end_temporary;
@@ -2015,7 +2035,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
mysql_update_log.write(thd, thd->query,thd->query_length);
if (mysql_bin_log.is_open())
{
- Query_log_event qinfo(thd, thd->query, thd->query_length);
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
mysql_bin_log.write(&qinfo);
}
VOID(pthread_cond_broadcast(&COND_refresh));
diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc
index f45eca0b65f..35e33caf572 100644
--- a/sql/sql_udf.cc
+++ b/sql/sql_udf.cc
@@ -98,8 +98,8 @@ static void init_syms(udf_func *tmp)
}
}
-static byte* get_hash_key(const byte *buff,uint *length,
- my_bool not_used __attribute__((unused)))
+extern "C" byte* get_hash_key(const byte *buff,uint *length,
+ my_bool not_used __attribute__((unused)))
{
udf_func *udf=(udf_func*) buff;
*length=(uint) udf->name_length;
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index 53f89747ce7..0e6de306c0d 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -78,7 +78,13 @@ bool select_union::send_data(List<Item> &values)
fill_record(table->field,values);
if ((write_record(table,&info)))
{
- if (create_myisam_from_heap(table, tmp_table_param, info.last_errno, 0))
+ if (thd->net.last_errno == ER_RECORD_FILE_FULL)
+ {
+ thd->clear_error(); // do not report user about table overflow
+ if (create_myisam_from_heap(table, tmp_table_param, info.last_errno, 0))
+ return 1;
+ }
+ else
return 1;
}
return 0;
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index be69935a49c..e3e0bca9856 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -50,11 +50,11 @@ int mysql_update(THD *thd,
COND *conds,
ORDER *order,
ha_rows limit,
- enum enum_duplicates handle_duplicates,
- thr_lock_type lock_type)
+ enum enum_duplicates handle_duplicates)
{
bool using_limit=limit != HA_POS_ERROR;
- bool used_key_is_modified, using_transactions;
+ bool safe_update= thd->options & OPTION_SAFE_UPDATES;
+ bool used_key_is_modified, transactional_table, log_delayed;
int error=0;
uint save_time_stamp, used_index, want_privilege;
ulong query_id=thd->query_id, timestamp_query_id;
@@ -66,7 +66,7 @@ int mysql_update(THD *thd,
LINT_INIT(used_index);
LINT_INIT(timestamp_query_id);
- if (!(table = open_ltable(thd,table_list,lock_type)))
+ if (!(table = open_ltable(thd,table_list,table_list->lock_type)))
DBUG_RETURN(-1); /* purecov: inspected */
save_time_stamp=table->time_stamp;
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
@@ -117,9 +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 & OPTION_SAFE_UPDATES),
- limit)) ||
- !limit)
+ (select && select->check_quick(safe_update, limit)) || !limit)
{
delete select;
table->time_stamp=save_time_stamp; // Restore timestamp pointer
@@ -134,7 +132,7 @@ int mysql_update(THD *thd,
if (!table->quick_keys)
{
thd->lex.select_lex.options|=QUERY_NO_INDEX_USED;
- if ((thd->options & OPTION_SAFE_UPDATES) && limit == HA_POS_ERROR)
+ if (safe_update && !using_limit)
{
delete select;
table->time_stamp=save_time_stamp;
@@ -301,23 +299,34 @@ int mysql_update(THD *thd,
thd->proc_info="end";
VOID(table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY));
table->time_stamp=save_time_stamp; // Restore auto timestamp pointer
- using_transactions=table->file->has_transactions();
- if (updated && (error <= 0 || !using_transactions))
+ transactional_table= table->file->has_transactions();
+ log_delayed= (transactional_table || table->tmp_table);
+ if (updated && (error <= 0 || !transactional_table))
{
mysql_update_log.write(thd,thd->query,thd->query_length);
if (mysql_bin_log.is_open())
{
Query_log_event qinfo(thd, thd->query, thd->query_length,
- using_transactions);
- if (mysql_bin_log.write(&qinfo) && using_transactions)
- error=1;
+ log_delayed);
+ if (mysql_bin_log.write(&qinfo) && transactional_table)
+ error=1; // Rollback update
}
- if (!using_transactions)
+ if (!log_delayed)
thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
}
- if (using_transactions && ha_autocommit_or_rollback(thd, error >= 0))
- error=1;
- if (updated)
+ if (transactional_table)
+ {
+ if (ha_autocommit_or_rollback(thd, error >= 0))
+ error=1;
+ }
+ /*
+ Only invalidate the query cache if something changed or if we
+ didn't commit the transacion (query cache is automaticly
+ invalidated on commit)
+ */
+ if (updated &&
+ (!transactional_table ||
+ thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))
{
query_cache_invalidate3(thd, table_list, 1);
}
@@ -349,10 +358,12 @@ int mysql_update(THD *thd,
Update multiple tables from join
***************************************************************************/
-multi_update::multi_update(THD *thd_arg, TABLE_LIST *ut, List<Item> &fs,
- enum enum_duplicates handle_duplicates, thr_lock_type lock_option_arg, uint num)
- : update_tables (ut), thd(thd_arg), updated(0), found(0), fields(fs), lock_option(lock_option_arg),
- dupl(handle_duplicates), num_of_tables(num), num_fields(0), num_updated(0) , error(0), do_update(false)
+multi_update::multi_update(THD *thd_arg, TABLE_LIST *ut, List<Item> &fs,
+ enum enum_duplicates handle_duplicates,
+ uint num)
+ : update_tables (ut), thd(thd_arg), updated(0), found(0), fields(fs),
+ dupl(handle_duplicates), num_of_tables(num), num_fields(0), num_updated(0),
+ error(0), do_update(false)
{
save_time_stamps = (uint *) sql_calloc (sizeof(uint) * num_of_tables);
tmp_tables = (TABLE **)NULL;
@@ -695,7 +706,7 @@ void multi_update::send_error(uint errcode,const char *err)
int multi_update::do_updates (bool from_send_error)
{
- int error = 0, counter = 0;
+ int local_error= 0, counter= 0;
if (from_send_error)
{
@@ -720,7 +731,7 @@ int multi_update::do_updates (bool from_send_error)
TABLE *tmp_table=tmp_tables[counter];
if (tmp_table->file->extra(HA_EXTRA_NO_CACHE))
{
- error=1;
+ local_error=1;
break;
}
List<Item> list;
@@ -736,35 +747,36 @@ int multi_update::do_updates (bool from_send_error)
tmp_table->used_keys&=field->part_of_key;
}
tmp_table->used_fields=tmp_table->fields;
- error=0; list.pop(); // we get position some other way ...
- error = tmp_table->file->rnd_init(1);
- if (error)
- return error;
- while (!(error=tmp_table->file->rnd_next(tmp_table->record[0])) &&
+ local_error=0;
+ list.pop(); // we get position some other way ...
+ local_error = tmp_table->file->rnd_init(1);
+ if (local_error)
+ return local_error;
+ while (!(local_error=tmp_table->file->rnd_next(tmp_table->record[0])) &&
(!thd->killed || from_send_error || not_trans_safe))
{
found++;
- error= table->file->rnd_pos(table->record[0],
- (byte*) (*(tmp_table->field))->ptr);
- if (error)
- return error;
+ local_error= table->file->rnd_pos(table->record[0],
+ (byte*) (*(tmp_table->field))->ptr);
+ if (local_error)
+ return local_error;
table->status|= STATUS_UPDATED;
store_record(table,1);
- error= fill_record(*fields_by_tables[counter + 1],list) ||
- /* compare_record(table, query_id) || */
- table->file->update_row(table->record[1],table->record[0]);
- if (error)
+ local_error= (fill_record(*fields_by_tables[counter + 1],list) ||
+ /* compare_record(table, query_id) || */
+ table->file->update_row(table->record[1],table->record[0]));
+ if (local_error)
{
- table->file->print_error(error,MYF(0));
+ table->file->print_error(local_error,MYF(0));
break;
}
else
updated++;
}
- if (error == HA_ERR_END_OF_FILE)
- error = 0;
+ if (local_error == HA_ERR_END_OF_FILE)
+ local_error = 0;
}
- return error;
+ return local_error;
}
@@ -775,18 +787,18 @@ bool multi_update::send_eof()
thd->proc_info="updating the reference tables";
/* Does updates for the last n - 1 tables, returns 0 if ok */
- int error = (num_updated) ? do_updates(false) : 0; /* do_updates returns 0 if success */
+ int local_error = (num_updated) ? do_updates(false) : 0;
/* reset used flags */
#ifndef NOT_USED
update_tables->table->no_keyread=0;
#endif
- if (error == -1)
- error = 0;
- thd->proc_info="end";
- //TODO error should be sent at the query processing end
- if (error)
- send_error(error,"An error occured in multi-table update");
+ if (local_error == -1)
+ local_error= 0;
+ thd->proc_info= "end";
+ // TODO: Error should be sent at the query processing end
+ if (local_error)
+ send_error(local_error, "An error occured in multi-table update");
/*
Write the SQL statement to the binlog if we updated
@@ -798,7 +810,7 @@ bool multi_update::send_eof()
if (updated || not_trans_safe)
{
mysql_update_log.write(thd,thd->query,thd->query_length);
- Query_log_event qinfo(thd, thd->query, thd->query_length);
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
/*
mysql_bin_log is not open if binlogging or replication
@@ -807,14 +819,14 @@ bool multi_update::send_eof()
if (mysql_bin_log.is_open() && mysql_bin_log.write(&qinfo) &&
!not_trans_safe)
- error=1; /* Log write failed: roll back the SQL statement */
+ local_error=1; /* Log write failed: roll back the SQL statement */
/* Commit or rollback the current SQL statement */
- VOID(ha_autocommit_or_rollback(thd,error > 0));
+ VOID(ha_autocommit_or_rollback(thd, local_error > 0));
}
else
- error=0; // this can happen only if it is end of file error
- if (!error) // if the above log write did not fail ...
+ local_error= 0; // this can happen only if it is end of file error
+ if (!local_error) // if the above log write did not fail ...
{
char buff[80];
sprintf(buff,ER(ER_UPDATE_INFO), (long) found, (long) updated,
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index d39ffeb5a6f..afcc115a6da 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -69,6 +69,7 @@ inline Item *or_or_concat(Item* A, Item* B)
enum Item_cast cast_type;
enum Item_udftype udf_type;
CHARSET_INFO *charset;
+ thr_lock_type lock_type;
interval_type interval;
}
@@ -86,6 +87,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token NEXT_SYM
%token PREV_SYM
+%token DIV_SYM
%token EQ
%token EQUAL_SYM
%token GE
@@ -94,6 +96,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token LT
%token NE
%token IS
+%token MOD_SYM
%token SHIFT_LEFT
%token SHIFT_RIGHT
%token SET_VAR
@@ -115,6 +118,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token CROSS
%token CUBE_SYM
%token DELETE_SYM
+%token DUAL_SYM
%token DO_SYM
%token DROP
%token EVENTS_SYM
@@ -167,13 +171,13 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token BOTH
%token BTREE_SYM
%token BY
+%token BYTE_SYM
%token CACHE_SYM
%token CASCADE
%token CAST_SYM
%token CHARSET
%token CHECKSUM_SYM
%token CHECK_SYM
-%token CIPHER
%token COMMITTED_SYM
%token COLLATE_SYM
%token COLUMNS
@@ -199,6 +203,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token ESCAPE_SYM
%token EXISTS
%token EXTENDED_SYM
+%token FALSE_SYM
%token FILE_SYM
%token FIRST_SYM
%token FIXED_SYM
@@ -229,7 +234,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token IN_SYM
%token ISOLATION
%token ISAM_SYM
-%token ISSUER
%token JOIN_SYM
%token KEYS
%token KEY_SYM
@@ -249,7 +253,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token MASTER_USER_SYM
%token MASTER_LOG_FILE_SYM
%token MASTER_LOG_POS_SYM
-%token MASTER_LOG_SEQ_SYM
%token MASTER_PASSWORD_SYM
%token MASTER_PORT_SYM
%token MASTER_CONNECT_RETRY_SYM
@@ -270,10 +273,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token NEW_SYM
%token NCHAR_SYM
%token NOT
-%token NO_FOREIGN_KEY_CHECKS
%token NO_SYM
%token NULL_SYM
%token NUM
+%token OFFSET_SYM
%token ON
%token OPEN_SYM
%token OPTION
@@ -300,7 +303,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token REAL_NUM
%token REFERENCES
%token REGEXP
-%token RELAXED_UNIQUE_CHECKS
%token RELOAD
%token RENAME
%token REPEATABLE_SYM
@@ -314,6 +316,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token ROW_SYM
%token RTREE_SYM
%token SET
+%token SERIAL_SYM
%token SERIALIZABLE_SYM
%token SESSION_SYM
%token SIMPLE_SYM
@@ -332,6 +335,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token TO_SYM
%token TRAILING
%token TRANSACTION_SYM
+%token TRUE_SYM
%token TYPE_SYM
%token TYPES_SYM
%token FUNC_ARG0
@@ -349,6 +353,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token USE_FRM
%token USE_SYM
%token USING
+%token VALUE_SYM
%token VALUES
%token VARIABLES
%token WHERE
@@ -516,7 +521,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%left '&'
%left SHIFT_LEFT SHIFT_RIGHT
%left '-' '+'
-%left '*' '/' '%'
+%left '*' '/' '%' DIV_SYM MOD_SYM
%left NEG '~'
%left XOR
%left '^'
@@ -539,7 +544,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
table_ident references
%type <simple_string>
- remember_name remember_end opt_len opt_ident opt_db text_or_password
+ remember_name remember_end opt_ident opt_db text_or_password
opt_escape
%type <string>
@@ -549,7 +554,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
type int_type real_type order_dir opt_field_spec lock_option
udf_type if_exists opt_local opt_table_options table_options
table_option opt_if_not_exists opt_var_type opt_var_ident_type
- delete_option
+ delete_option opt_temporary
%type <ulong_num>
ULONG_NUM raid_types merge_insert_types
@@ -557,6 +562,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%type <ulonglong_number>
ulonglong_num
+%type <lock_type>
+ replace_lock_option opt_low_priority insert_lock_option load_data_lock
+
%type <item>
literal text_literal insert_ident order_ident
simple_ident select_item2 expr opt_expr opt_else sum_expr in_sum_expr
@@ -628,23 +636,25 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
field_opt_list opt_binary table_lock_list table_lock varchar
ref_list opt_on_delete opt_on_delete_list opt_on_delete_item use
opt_delete_options opt_delete_option
- opt_outer table_list table_name opt_option opt_place opt_low_priority
+ opt_outer table_list table_name opt_option opt_place
opt_attribute opt_attribute_list attribute column_list column_list_id
opt_column_list grant_privileges opt_table user_list grant_option
grant_privilege grant_privilege_list
- flush_options flush_option insert_lock_option replace_lock_option
+ flush_options flush_option
equal optional_braces opt_key_definition key_usage_list2
opt_mi_check_type opt_to mi_check_types normal_join
table_to_table_list table_to_table opt_table_list opt_as
handler_rkey_function handler_read_or_scan
- single_multi table_wild_list table_wild_one opt_wild union union_list
- precision union_option opt_on_delete_item subselect_start opt_and
- subselect_end select_var_list select_var_list_init help
+ single_multi table_wild_list table_wild_one opt_wild
+ union union_list union_option
+ precision opt_on_delete_item subselect_start opt_and
+ subselect_end select_var_list select_var_list_init help opt_len
END_OF_INPUT
%type <NONE>
'-' '+' '*' '/' '%' '(' ')'
- ',' '!' '{' '}' '&' '|' AND OR OR_OR_CONCAT BETWEEN_SYM CASE_SYM THEN_SYM WHEN_SYM
+ ',' '!' '{' '}' '&' '|' AND OR OR_OR_CONCAT BETWEEN_SYM CASE_SYM
+ THEN_SYM WHEN_SYM DIV_SYM MOD_SYM
%%
@@ -721,7 +731,7 @@ change:
{
LEX *lex = Lex;
lex->sql_command = SQLCOM_CHANGE_MASTER;
- memset(&lex->mi, 0, sizeof(lex->mi));
+ bzero((char*) &lex->mi, sizeof(lex->mi));
} master_defs;
master_defs:
@@ -1032,7 +1042,7 @@ field_spec:
};
type:
- int_type opt_len field_options { Lex->length=$2; $$=$1; }
+ int_type opt_len field_options { $$=$1; }
| real_type opt_precision field_options { $$=$1; }
| FLOAT_SYM float_options field_options { $$=FIELD_TYPE_FLOAT; }
| BIT_SYM opt_len { Lex->length=(char*) "1";
@@ -1051,16 +1061,22 @@ type:
| VARBINARY '(' NUM ')' { Lex->length=$3.str;
Lex->charset=my_charset_bin;
$$=FIELD_TYPE_VAR_STRING; }
- | YEAR_SYM opt_len field_options { $$=FIELD_TYPE_YEAR; Lex->length=$2; }
+ | YEAR_SYM opt_len field_options { $$=FIELD_TYPE_YEAR; }
| DATE_SYM { $$=FIELD_TYPE_DATE; }
| TIME_SYM { $$=FIELD_TYPE_TIME; }
- | TIMESTAMP { $$=FIELD_TYPE_TIMESTAMP; }
+ | TIMESTAMP
+ {
+ if (current_thd->sql_mode & MODE_SAPDB)
+ $$=FIELD_TYPE_DATETIME;
+ else
+ $$=FIELD_TYPE_TIMESTAMP;
+ }
| TIMESTAMP '(' NUM ')' { Lex->length=$3.str;
$$=FIELD_TYPE_TIMESTAMP; }
| DATETIME { $$=FIELD_TYPE_DATETIME; }
| TINYBLOB { Lex->charset=my_charset_bin;
$$=FIELD_TYPE_TINY_BLOB; }
- | BLOB_SYM { Lex->charset=my_charset_bin;
+ | BLOB_SYM opt_len { Lex->charset=my_charset_bin;
$$=FIELD_TYPE_BLOB; }
| GEOMETRY_SYM { Lex->charset=my_charset_bin;
$$=FIELD_TYPE_GEOMETRY; }
@@ -1072,13 +1088,15 @@ type:
$$=FIELD_TYPE_MEDIUM_BLOB; }
| LONG_SYM varchar opt_binary { $$=FIELD_TYPE_MEDIUM_BLOB; }
| TINYTEXT opt_binary { $$=FIELD_TYPE_TINY_BLOB; }
- | TEXT_SYM opt_binary { $$=FIELD_TYPE_BLOB; }
+ | TEXT_SYM opt_len opt_binary { $$=FIELD_TYPE_BLOB; }
| MEDIUMTEXT opt_binary { $$=FIELD_TYPE_MEDIUM_BLOB; }
| LONGTEXT opt_binary { $$=FIELD_TYPE_LONG_BLOB; }
| DECIMAL_SYM float_options field_options
{ $$=FIELD_TYPE_DECIMAL;}
| NUMERIC_SYM float_options field_options
{ $$=FIELD_TYPE_DECIMAL;}
+ | FIXED_SYM float_options field_options
+ { $$=FIELD_TYPE_DECIMAL;}
| ENUM {Lex->interval_list.empty();} '(' string_list ')' opt_binary
{
LEX *lex=Lex;
@@ -1090,7 +1108,9 @@ type:
LEX *lex=Lex;
lex->interval=typelib(lex->interval_list);
$$=FIELD_TYPE_SET;
- };
+ }
+ | LONG_SYM opt_binary { $$=FIELD_TYPE_MEDIUM_BLOB; }
+ ;
char:
CHAR_SYM {}
@@ -1143,8 +1163,8 @@ field_option:
| ZEROFILL { Lex->type|= UNSIGNED_FLAG | ZEROFILL_FLAG; };
opt_len:
- /* empty */ { $$=(char*) 0; } /* use default length */
- | '(' NUM ')' { $$=$2.str; };
+ /* empty */ { Lex->length=(char*) 0; } /* use default length */
+ | '(' NUM ')' { Lex->length= $2.str; };
opt_precision:
/* empty */ {}
@@ -1163,6 +1183,8 @@ attribute:
| NOT NULL_SYM { Lex->type|= NOT_NULL_FLAG; }
| DEFAULT literal { Lex->default_value=$2; }
| AUTO_INC { Lex->type|= AUTO_INCREMENT_FLAG | NOT_NULL_FLAG; }
+ | SERIAL_SYM DEFAULT VALUE_SYM
+ { Lex->type|= AUTO_INCREMENT_FLAG | NOT_NULL_FLAG; }
| PRIMARY_SYM KEY_SYM { Lex->type|= PRI_KEY_FLAG | NOT_NULL_FLAG; }
| UNIQUE_SYM { Lex->type|= UNIQUE_FLAG; }
| UNIQUE_SYM KEY_SYM { Lex->type|= UNIQUE_KEY_FLAG; }
@@ -1201,6 +1223,7 @@ opt_db_default_character_set:
opt_binary:
/* empty */ { Lex->charset=NULL; }
+ | BYTE_SYM { Lex->charset=my_charset_bin; }
| BINARY { Lex->charset=my_charset_bin; }
| CHAR_SYM SET charset_name { Lex->charset=$3; } ;
@@ -1435,20 +1458,24 @@ opt_to:
| EQ {}
| AS {};
+/*
+ The first two deprecate the last two--delete the last two for 4.1 release
+*/
+
slave:
START_SYM SLAVE slave_thread_opts
- {
- LEX *lex=Lex;
- lex->sql_command = SQLCOM_SLAVE_START;
- lex->type = 0;
- }
- |
- STOP_SYM SLAVE slave_thread_opts
- {
- LEX *lex=Lex;
- lex->sql_command = SQLCOM_SLAVE_STOP;
- lex->type = 0;
- };
+ {
+ LEX *lex=Lex;
+ lex->sql_command = SQLCOM_SLAVE_START;
+ lex->type = 0;
+ }
+ | STOP_SYM SLAVE slave_thread_opts
+ {
+ LEX *lex=Lex;
+ lex->sql_command = SQLCOM_SLAVE_STOP;
+ lex->type = 0;
+ }
+ ;
slave_thread_opts:
slave_thread_opt
@@ -1609,6 +1636,7 @@ select_part2:
select_into:
limit_clause {}
| select_from
+ | FROM DUAL_SYM
| opt_into
| opt_into select_from
| select_from opt_into;
@@ -1752,6 +1780,8 @@ expr_expr:
| expr '-' expr { $$= new Item_func_minus($1,$3); }
| expr '*' expr { $$= new Item_func_mul($1,$3); }
| expr '/' expr { $$= new Item_func_div($1,$3); }
+ | expr DIV_SYM expr { $$= new Item_func_int_div($1,$3); }
+ | expr MOD_SYM expr { $$= new Item_func_mod($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); }
@@ -1792,10 +1822,12 @@ no_in_expr:
| no_in_expr '-' expr { $$= new Item_func_minus($1,$3); }
| no_in_expr '*' expr { $$= new Item_func_mul($1,$3); }
| no_in_expr '/' expr { $$= new Item_func_div($1,$3); }
+ | no_in_expr DIV_SYM expr { $$= new Item_func_int_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 MOD_SYM expr { $$= new Item_func_mod($1,$3); }
| no_in_expr '+' INTERVAL_SYM expr interval
{ $$= new Item_date_add_interval($1,$4,$5,0); }
| no_in_expr '-' INTERVAL_SYM expr interval
@@ -1834,10 +1866,12 @@ no_and_expr:
| no_and_expr '-' expr { $$= new Item_func_minus($1,$3); }
| no_and_expr '*' expr { $$= new Item_func_mul($1,$3); }
| no_and_expr '/' expr { $$= new Item_func_div($1,$3); }
+ | no_and_expr DIV_SYM expr { $$= new Item_func_int_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 MOD_SYM expr { $$= new Item_func_mod($1,$3); }
| no_and_expr '+' INTERVAL_SYM expr interval
{ $$= new Item_date_add_interval($1,$4,$5,0); }
| no_and_expr '-' INTERVAL_SYM expr interval
@@ -1955,6 +1989,8 @@ simple_expr:
{ $$= new Item_func_export_set($3, $5, $7, $9); }
| EXPORT_SET '(' expr ',' expr ',' expr ',' expr ',' expr ')'
{ $$= new Item_func_export_set($3, $5, $7, $9, $11); }
+ | FALSE_SYM
+ { $$= new Item_int((char*) "FALSE",0,1); }
| FORMAT_SYM '(' expr ',' NUM ')'
{ $$= new Item_func_format($3,atoi($5.str)); }
| FROM_UNIXTIME '(' expr ')'
@@ -2021,6 +2057,8 @@ simple_expr:
{ $$= new Item_func_geometry_from_text($3); }
| MINUTE_SYM '(' expr ')'
{ $$= new Item_func_minute($3); }
+ | MOD_SYM '(' expr ',' expr ')'
+ { $$ = new Item_func_mod( $3, $5); }
| MONTH_SYM '(' expr ')'
{ $$= new Item_func_month($3); }
| MULTILINESTRING '(' expr_list ')'
@@ -2100,6 +2138,8 @@ simple_expr:
{ $$= new Item_func_trim($5,$3); }
| TRUNCATE_SYM '(' expr ',' expr ')'
{ $$= new Item_func_round($3,$5,1); }
+ | TRUE_SYM
+ { $$= new Item_int((char*) "TRUE",1,1); }
| UDA_CHAR_SUM '(' udf_expr_list ')'
{
if ($3 != NULL)
@@ -2451,15 +2491,24 @@ opt_table_alias:
where_clause:
/* empty */ { Select->select_lex()->where= 0; }
- | WHERE expr { Select->select_lex()->where= $2; };
+ | WHERE expr
+ {
+ Select->select_lex()->where= $2;
+ if ($2)
+ $2->top_level_item();
+ }
+ ;
having_clause:
/* empty */
| HAVING { Select->select_lex()->create_refs= 1; } expr
- {
- SELECT_LEX *sel= Select->select_lex();
- sel->having= $3; sel->create_refs=0;
- };
+ {
+ SELECT_LEX *sel= Select->select_lex();
+ sel->having= $3; sel->create_refs=0;
+ if ($3)
+ $3->top_level_item();
+ }
+ ;
opt_escape:
ESCAPE_SYM TEXT_STRING { $$= $2.str; }
@@ -2524,11 +2573,6 @@ order_clause:
ORDER_SYM BY
{
LEX *lex=Lex;
- if (lex->sql_command == SQLCOM_MULTI_UPDATE)
- {
- net_printf(lex->thd, ER_WRONG_USAGE, "UPDATE", "ORDER BY");
- YYABORT;
- }
if (lex->current_select->linkage != GLOBAL_OPTIONS_TYPE &&
lex->current_select->select_lex()->olap !=
UNSPECIFIED_OLAP_TYPE)
@@ -2554,7 +2598,7 @@ order_dir:
limit_clause:
/* empty */ {}
- | LIMIT ULONG_NUM
+ | LIMIT
{
LEX *lex= Lex;
if (lex->current_select->linkage != GLOBAL_OPTIONS_TYPE &&
@@ -2565,35 +2609,36 @@ limit_clause:
"LIMIT");
YYABORT;
}
+ }
+ limit_options
+ ;
+
+limit_options:
+ ULONG_NUM
+ {
+ SELECT_LEX_NODE *sel= Select;
+ sel->select_limit= $1;
+ sel->offset_limit= 0L;
+ }
+ | ULONG_NUM ',' ULONG_NUM
+ {
SELECT_LEX_NODE *sel= Select;
- sel->select_limit= $2;
- sel->offset_limit= 0L;
+ sel->select_limit= $3;
+ sel->offset_limit= $1;
}
- | LIMIT ULONG_NUM ',' ULONG_NUM
+ | ULONG_NUM OFFSET_SYM ULONG_NUM
{
- LEX *lex=Lex;
- if (lex->current_select->linkage != GLOBAL_OPTIONS_TYPE &&
- lex->current_select->select_lex()->olap !=
- UNSPECIFIED_OLAP_TYPE)
- {
- net_printf(lex->thd, ER_WRONG_USAGE, "CUBE/ROLLUP",
- "LIMIT");
- YYABORT;
- }
- SELECT_LEX_NODE *sel= lex->current_select;
- sel->select_limit= $4;
- sel->offset_limit= $2;
- };
+ SELECT_LEX_NODE *sel= Select;
+ sel->select_limit= $1;
+ sel->offset_limit= $3;
+ }
+ ;
+
delete_limit_clause:
/* empty */
{
LEX *lex=Lex;
- if (lex->sql_command == SQLCOM_MULTI_UPDATE)
- {
- net_printf(lex->thd, ER_WRONG_USAGE, "DELETE", "LIMIT");
- YYABORT;
- }
lex->current_select->select_limit= HA_POS_ERROR;
}
| LIMIT ulonglong_num
@@ -2715,11 +2760,12 @@ do: DO_SYM
*/
drop:
- DROP TABLE_SYM if_exists table_list opt_restrict
+ DROP opt_temporary TABLE_SYM if_exists table_list opt_restrict
{
LEX *lex=Lex;
lex->sql_command = SQLCOM_DROP_TABLE;
- lex->drop_if_exists = $3;
+ lex->drop_temporary= $2;
+ lex->drop_if_exists= $4;
}
| DROP INDEX ident ON table_ident {}
{
@@ -2756,14 +2802,25 @@ table_name:
if_exists:
/* empty */ { $$=0; }
- | IF EXISTS { $$= 1; };
+ | IF EXISTS { $$= 1; }
+ ;
+opt_temporary:
+ /* empty */ { $$= 0; }
+ | TEMPORARY { $$= 1; }
+ ;
/*
** Insert : add new data to table
*/
insert:
- INSERT { Lex->sql_command = SQLCOM_INSERT; } insert_lock_option opt_ignore insert2 insert_field_spec;
+ INSERT { Lex->sql_command = SQLCOM_INSERT; } insert_lock_option
+ opt_ignore insert2
+ {
+ Select->set_lock_for_tables($3);
+ }
+ insert_field_spec
+ ;
replace:
REPLACE
@@ -2772,17 +2829,23 @@ replace:
lex->sql_command = SQLCOM_REPLACE;
lex->duplicates= DUP_REPLACE;
}
- replace_lock_option insert2 insert_field_spec;
+ replace_lock_option insert2
+ {
+ Select->set_lock_for_tables($3);
+ }
+ insert_field_spec
+ ;
insert_lock_option:
- /* empty */ { Lex->lock_option= TL_WRITE_CONCURRENT_INSERT; }
- | LOW_PRIORITY { Lex->lock_option= TL_WRITE_LOW_PRIORITY; }
- | DELAYED_SYM { Lex->lock_option= TL_WRITE_DELAYED; }
- | HIGH_PRIORITY { Lex->lock_option= TL_WRITE; };
+ /* empty */ { $$= TL_WRITE_CONCURRENT_INSERT; }
+ | LOW_PRIORITY { $$= TL_WRITE_LOW_PRIORITY; }
+ | DELAYED_SYM { $$= TL_WRITE_DELAYED; }
+ | HIGH_PRIORITY { $$= TL_WRITE; }
+ ;
replace_lock_option:
- opt_low_priority {}
- | DELAYED_SYM { Lex->lock_option= TL_WRITE_DELAYED; };
+ opt_low_priority { $$= $1; }
+ | DELAYED_SYM { $$= TL_WRITE_DELAYED; };
insert2:
INTO insert_table {}
@@ -2828,7 +2891,8 @@ insert_values:
mysql_init_select(lex);
}
select_options select_item_list select_from select_lock_type
- union {};
+ union {}
+ ;
values_list:
values_list ',' no_braces
@@ -2895,13 +2959,18 @@ expr_or_default:
/* Update rows in a table */
update:
- UPDATE_SYM
+ UPDATE_SYM
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_UPDATE;
lex->select_lex.init_order();
}
- opt_low_priority opt_ignore join_table_list SET update_list where_clause opt_order_clause delete_limit_clause;
+ opt_low_priority opt_ignore join_table_list
+ SET update_list where_clause opt_order_clause delete_limit_clause
+ {
+ Select->set_lock_for_tables($3);
+ }
+ ;
update_list:
update_list ',' simple_ident equal expr
@@ -2916,8 +2985,8 @@ update_list:
};
opt_low_priority:
- /* empty */ { Lex->lock_option= current_thd->update_lock_default; }
- | LOW_PRIORITY { Lex->lock_option= TL_WRITE_LOW_PRIORITY; };
+ /* empty */ { $$= current_thd->update_lock_default; }
+ | LOW_PRIORITY { $$= TL_WRITE_LOW_PRIORITY; };
/* Delete rows from a table */
@@ -2930,13 +2999,20 @@ delete:
lex->lock_option= lex->thd->update_lock_default;
lex->select_lex.init_order();
}
- opt_delete_options single_multi {};
+ opt_delete_options single_multi {}
+ ;
single_multi:
- FROM table_name where_clause opt_order_clause delete_limit_clause {}
+ FROM table_ident
+ {
+ if (!Select->add_table_to_list($2, NULL, 1, Lex->lock_option))
+ YYABORT;
+ }
+ where_clause opt_order_clause
+ delete_limit_clause
| table_wild_list
{ mysql_init_multi_delete(Lex); }
- FROM join_table_list where_clause
+ FROM join_table_list where_clause
| FROM table_wild_list
{ mysql_init_multi_delete(Lex); }
USING join_table_list where_clause;
@@ -2946,18 +3022,19 @@ table_wild_list:
| table_wild_list ',' table_wild_one {};
table_wild_one:
- ident opt_wild
- {
- if (!Select->add_table_to_list(new Table_ident($1), NULL, 1,
- TL_WRITE))
- YYABORT;
- }
- | ident '.' ident opt_wild
- {
- if (!Select->add_table_to_list(new Table_ident($1, $3, 0), NULL,
- 1, TL_WRITE))
+ ident opt_wild
+ {
+ if (!Select->add_table_to_list(new Table_ident($1), NULL, 1,
+ Lex->lock_option))
+ YYABORT;
+ }
+ | ident '.' ident opt_wild
+ {
+ if (!Select->add_table_to_list(new Table_ident($1, $3, 0), NULL, 1,
+ Lex->lock_option))
YYABORT;
- };
+ }
+ ;
opt_wild:
/* empty */ {}
@@ -2979,7 +3056,8 @@ truncate:
lex->sql_command= SQLCOM_TRUNCATE;
lex->select_lex.options= 0;
lex->select_lex.init_order();
- lex->lock_option= lex->thd->update_lock_default; };
+ }
+ ;
opt_table_sym:
/* empty */
@@ -3271,7 +3349,8 @@ load: LOAD DATA_SYM load_data_lock opt_local INFILE TEXT_STRING
{
LEX *lex=Lex;
lex->sql_command= SQLCOM_LOAD;
- lex->local_file= $4;
+ lex->lock_option= $3;
+ lex->local_file= $4;
if (!(lex->exchange= new sql_exchange($6.str,0)))
YYABORT;
lex->field_list.empty();
@@ -3301,9 +3380,9 @@ opt_local:
| LOCAL_SYM { $$=1;};
load_data_lock:
- /* empty */ { Lex->lock_option= current_thd->update_lock_default; }
- | CONCURRENT { Lex->lock_option= TL_WRITE_CONCURRENT_INSERT ; }
- | LOW_PRIORITY { Lex->lock_option= TL_WRITE_LOW_PRIORITY; };
+ /* empty */ { $$= current_thd->update_lock_default; }
+ | CONCURRENT { $$= TL_WRITE_CONCURRENT_INSERT ; }
+ | LOW_PRIORITY { $$= TL_WRITE_LOW_PRIORITY; };
opt_duplicate:
@@ -3446,12 +3525,13 @@ ident:
IDENT { $$=$1; }
| keyword
{
- LEX *lex;
- $$.str=sql_strmake($1.str,$1.length);
+ LEX *lex= Lex;
+ $$.str= lex->thd->strmake($1.str,$1.length);
$$.length=$1.length;
- if ((lex=Lex)->next_state != STATE_END)
+ if (lex->next_state != STATE_END)
lex->next_state=STATE_OPERATOR_OR_IDENT;
- };
+ }
+ ;
ident_or_text:
ident { $$=$1;}
@@ -3489,6 +3569,7 @@ keyword:
| BIT_SYM {}
| BOOL_SYM {}
| BOOLEAN_SYM {}
+ | BYTE_SYM {}
| CACHE_SYM {}
| CHANGED {}
| CHARSET {}
@@ -3512,6 +3593,7 @@ keyword:
| DIRECTORY_SYM {}
| DO_SYM {}
| DUMPFILE {}
+ | DUAL_SYM {}
| DYNAMIC_SYM {}
| END {}
| ENUM {}
@@ -3572,6 +3654,7 @@ keyword:
| NEW_SYM {}
| NO_SYM {}
| NONE_SYM {}
+ | OFFSET_SYM {}
| OPEN_SYM {}
| PACK_KEYS_SYM {}
| PARTIAL {}
@@ -3601,6 +3684,7 @@ keyword:
| ROW_FORMAT_SYM {}
| ROW_SYM {}
| SECOND_SYM {}
+ | SERIAL_SYM {}
| SERIALIZABLE_SYM {}
| SESSION_SYM {}
| SIGNED_SYM {}
@@ -3629,6 +3713,7 @@ keyword:
| UNCOMMITTED_SYM {}
| USE_FRM {}
| VARIABLES {}
+ | VALUE_SYM {}
| WORK_SYM {}
| YEAR_SYM {}
;
@@ -4155,9 +4240,10 @@ rollback:
*/
-union:
+union:
/* empty */ {}
- | union_list;
+ | union_list
+ ;
union_list:
UNION_SYM union_option
@@ -4182,11 +4268,15 @@ union_list:
;
union_opt:
- union {}
- | optional_order_or_limit {};
+ union_list {}
+ | optional_order_or_limit {}
+ ;
optional_order_or_limit:
- /* empty */ {}
+ /* empty
+ intentional reduce/reduce conflict here !!!
+ { code } below should not be executed
+ when neither ORDER BY nor LIMIT are used */ {}
|
{
LEX *lex=Lex;
diff --git a/sql/stacktrace.c b/sql/stacktrace.c
index 1aba73dda33..f5c0a59b572 100644
--- a/sql/stacktrace.c
+++ b/sql/stacktrace.c
@@ -206,7 +206,7 @@ resolve it\n");
/* Produce a core for the thread */
-#ifdef HAVE_LINUXTHREADS
+#ifdef NOT_USED /* HAVE_LINUXTHREADS */
void write_core(int sig)
{
signal(sig, SIG_DFL);
diff --git a/sql/table.cc b/sql/table.cc
index bad453f2cad..84a072c886d 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -95,15 +95,15 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
if (my_read(file,(byte*) head,64,MYF(MY_NABP))) goto err_not_open;
if (head[0] != (uchar) 254 || head[1] != 1 ||
- (head[2] < FRM_VER && head[2] > FRM_VER+2))
- goto err_not_open; /* purecov: inspected */
+ (head[2] != FRM_VER && head[2] > FRM_VER+2))
+ goto err_not_open; /* purecov: inspected */
new_field_pack_flag=head[27];
new_frm_ver= (head[2] - FRM_VER);
field_pack_length= new_frm_ver < 2 ? 11 : 15;
error=3;
if (!(pos=get_form_pos(file,head,(TYPELIB*) 0)))
- goto err_not_open; /* purecov: inspected */
+ goto err_not_open; /* purecov: inspected */
*fn_ext(index_file)='\0'; // Remove .frm extension
outparam->db_type=ha_checktype((enum db_type) (uint) *(head+3));
@@ -145,7 +145,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
goto err_not_open; /* purecov: inspected */
bzero((char*) keyinfo,n_length);
outparam->key_info=keyinfo;
- outparam->max_key_length=0;
+ outparam->max_key_length= outparam->total_key_length= 0;
key_part= (KEY_PART_INFO*) (keyinfo+keys);
strpos=disk_buff+6;
@@ -203,11 +203,13 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
}
set_if_bigger(outparam->max_key_length,keyinfo->key_length+
keyinfo->key_parts);
+ outparam->total_key_length+= keyinfo->key_length;
if (keyinfo->flags & HA_NOSAME)
set_if_bigger(outparam->max_unique_length,keyinfo->key_length);
}
keynames=(char*) key_part;
strpos+= (strmov(keynames, (char *) strpos) - keynames)+1;
+
outparam->reclength = uint2korr((head+16));
if (*(head+26) == 1)
outparam->system=1; /* one-record-database */
@@ -391,6 +393,11 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
(TYPELIB*) 0),
outparam->fieldnames.type_names[i],
outparam);
+ if (!reg_field) // Not supported field type
+ {
+ error= 4;
+ goto err_not_open; /* purecov: inspected */
+ }
reg_field->comment=comment;
reg_field->set_charset(charset);
if (!(reg_field->flags & NOT_NULL_FLAG))
diff --git a/sql/table.h b/sql/table.h
index d09194442c8..18079e183ce 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -58,6 +58,7 @@ struct st_table {
uint reclength; /* Recordlength */
uint rec_buff_length;
uint keys,key_parts,primary_key,max_key_length,max_unique_length;
+ uint total_key_length;
uint uniques;
uint null_fields; /* number of null fields */
uint blob_fields; /* number of blob fields */