summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/field.cc28
-rw-r--r--sql/field.h2
-rw-r--r--sql/filesort.cc11
-rw-r--r--sql/ha_heap.h5
-rw-r--r--sql/ha_innodb.cc173
-rw-r--r--sql/ha_innodb.h17
-rw-r--r--sql/ha_myisam.cc22
-rw-r--r--sql/handler.cc40
-rw-r--r--sql/handler.h4
-rw-r--r--sql/init.cc2
-rw-r--r--sql/item.cc8
-rw-r--r--sql/item_create.cc2
-rw-r--r--sql/item_func.cc89
-rw-r--r--sql/item_strfunc.cc21
-rw-r--r--sql/item_sum.cc13
-rw-r--r--sql/item_sum.h8
-rw-r--r--sql/log.cc63
-rw-r--r--sql/log_event.cc610
-rw-r--r--sql/log_event.h27
-rw-r--r--sql/mini_client.cc2
-rw-r--r--sql/mysql_priv.h12
-rw-r--r--sql/mysqld.cc109
-rw-r--r--sql/net_serv.cc22
-rw-r--r--sql/opt_range.cc12
-rw-r--r--sql/opt_sum.cc79
-rw-r--r--sql/records.cc2
-rw-r--r--sql/set_var.cc56
-rw-r--r--sql/set_var.h14
-rw-r--r--sql/share/czech/errmsg.txt2
-rw-r--r--sql/share/danish/errmsg.txt2
-rw-r--r--sql/share/dutch/errmsg.txt2
-rw-r--r--sql/share/english/errmsg.txt2
-rw-r--r--sql/share/estonian/errmsg.txt2
-rw-r--r--sql/share/french/errmsg.txt2
-rw-r--r--sql/share/german/errmsg.txt2
-rw-r--r--sql/share/greek/errmsg.txt2
-rw-r--r--sql/share/hungarian/errmsg.txt2
-rw-r--r--sql/share/italian/errmsg.txt2
-rw-r--r--sql/share/japanese/errmsg.txt2
-rw-r--r--sql/share/korean/errmsg.txt2
-rw-r--r--sql/share/norwegian-ny/errmsg.txt2
-rw-r--r--sql/share/norwegian/errmsg.txt2
-rw-r--r--sql/share/portuguese/errmsg.txt2
-rw-r--r--sql/share/romanian/errmsg.txt2
-rw-r--r--sql/share/russian/errmsg.txt2
-rw-r--r--sql/share/slovak/errmsg.txt2
-rw-r--r--sql/share/spanish/errmsg.txt2
-rw-r--r--sql/share/swedish/errmsg.txt2
-rw-r--r--sql/share/ukrainian/errmsg.txt2
-rw-r--r--sql/slave.cc4
-rw-r--r--sql/sql_acl.cc72
-rw-r--r--sql/sql_acl.h3
-rw-r--r--sql/sql_base.cc27
-rw-r--r--sql/sql_cache.cc22
-rw-r--r--sql/sql_class.cc1
-rw-r--r--sql/sql_class.h4
-rw-r--r--sql/sql_db.cc25
-rw-r--r--sql/sql_delete.cc2
-rw-r--r--sql/sql_insert.cc19
-rw-r--r--sql/sql_list.h2
-rw-r--r--sql/sql_load.cc2
-rw-r--r--sql/sql_parse.cc133
-rw-r--r--sql/sql_repl.cc3
-rw-r--r--sql/sql_select.cc30
-rw-r--r--sql/sql_show.cc8
-rw-r--r--sql/sql_table.cc173
-rw-r--r--sql/sql_union.cc2
-rw-r--r--sql/sql_update.cc195
-rw-r--r--sql/sql_yacc.yy40
-rw-r--r--sql/time.cc143
-rw-r--r--sql/unireg.h1
71 files changed, 1394 insertions, 1012 deletions
diff --git a/sql/field.cc b/sql/field.cc
index 3695268a888..d6f9797071b 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -161,6 +161,14 @@ static bool test_if_real(const char *str,int length, CHARSET_INFO *cs)
}
+static inline uint field_length_without_space(const char *ptr, uint length)
+{
+ const char *end= ptr+length;
+ while (end > ptr && end[-1] == ' ')
+ end--;
+ return (uint) (end-ptr);
+}
+
/****************************************************************************
** Functions for the base classes
** This is an unpacked number.
@@ -3604,11 +3612,11 @@ bool Field_newdate::get_date(TIME *ltime,bool fuzzydate)
if (is_null())
return 1;
uint32 tmp=(uint32) uint3korr(ptr);
- bzero((char*) ltime,sizeof(*ltime));
ltime->day= tmp & 31;
ltime->month= (tmp >> 5) & 15;
ltime->year= (tmp >> 9);
ltime->time_type=TIMESTAMP_DATE;
+ ltime->hour= ltime->minute= ltime->second= ltime->second_part= 0;
return (!fuzzydate && (!ltime->month || !ltime->day)) ? 1 : 0;
}
@@ -3969,9 +3977,23 @@ String *Field_string::val_str(String *val_buffer __attribute__((unused)),
int Field_string::cmp(const char *a_ptr, const char *b_ptr)
{
+#ifdef USE_STRCOLL
+ if (field_charset->mbmaxlen > 1)
+ {
+ /*
+ We have to remove end space to be able to compare multi-byte-characters
+ like in latin_de 'ae' and 0xe4
+ */
+ uint a_length= field_length_without_space(a_ptr, field_length);
+ uint b_length= field_length_without_space(b_ptr, field_length);
+ return my_strnncoll(field_charset,
+ (const uchar*) a_ptr, a_length,
+ (const uchar*) b_ptr, b_length);
+ }
+#endif
return my_strnncoll(field_charset,
- (const uchar*)a_ptr,field_length,
- (const uchar*)b_ptr,field_length);
+ (const uchar*) a_ptr, field_length,
+ (const uchar*) b_ptr, field_length);
}
void Field_string::sort_string(char *to,uint length)
diff --git a/sql/field.h b/sql/field.h
index 80bfc516ef7..2ee984e3a2a 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -134,6 +134,8 @@ public:
Field *tmp= (Field*) memdup_root(root,(char*) this,size_of());
if (tmp)
{
+ if (tmp->table->maybe_null)
+ tmp->flags&= ~NOT_NULL_FLAG;
tmp->table= new_table;
tmp->key_start= tmp->part_of_key= tmp->part_of_sortkey= 0;
tmp->unireg_check=Field::NONE;
diff --git a/sql/filesort.cc b/sql/filesort.cc
index a3d24cd9242..68b8737bc79 100644
--- a/sql/filesort.cc
+++ b/sql/filesort.cc
@@ -494,6 +494,7 @@ static void make_sortkey(register SORTPARAM *param,
sort_field != param->end ;
sort_field++)
{
+ bool maybe_null=0;
if ((field=sort_field->field))
{ // Field
if (field->maybe_null())
@@ -519,7 +520,7 @@ static void make_sortkey(register SORTPARAM *param,
case STRING_RESULT:
{
CHARSET_INFO *cs=item->charset();
- if (item->maybe_null)
+ if ((maybe_null=item->maybe_null))
*to++=1;
/* All item->str() to use some extra byte for end null.. */
String tmp((char*) to,sort_field->length+4,cs);
@@ -567,7 +568,7 @@ static void make_sortkey(register SORTPARAM *param,
case INT_RESULT:
{
longlong value=item->val_int();
- if (item->maybe_null)
+ if ((maybe_null=item->maybe_null))
*to++=1; /* purecov: inspected */
if (item->null_value)
{
@@ -601,13 +602,13 @@ static void make_sortkey(register SORTPARAM *param,
case REAL_RESULT:
{
double value=item->val();
- if (item->null_value)
+ if ((maybe_null=item->null_value))
{
bzero((char*) to,sort_field->length+1);
to++;
break;
}
- if (item->maybe_null)
+ if ((maybe_null=item->maybe_null))
*to++=1;
change_double_for_sort(value,(byte*) to);
break;
@@ -621,6 +622,8 @@ static void make_sortkey(register SORTPARAM *param,
}
if (sort_field->reverse)
{ /* Revers key */
+ if (maybe_null)
+ to[-1]= ~to[-1];
length=sort_field->length;
while (length--)
{
diff --git a/sql/ha_heap.h b/sql/ha_heap.h
index fe874dab3f2..c369c7029b4 100644
--- a/sql/ha_heap.h
+++ b/sql/ha_heap.h
@@ -53,8 +53,9 @@ class ha_heap: public handler
uint max_keys() const { return MAX_KEY; }
uint max_key_parts() const { return MAX_REF_PARTS; }
uint max_key_length() const { return HA_MAX_REC_LENGTH; }
- virtual double scan_time() { return (double) (records+deleted) / 20.0+10; }
- virtual double read_time(ha_rows rows) { return (double) rows / 20.0+1; }
+ double scan_time() { return (double) (records+deleted) / 20.0+10; }
+ double read_time(uint index, uint ranges, ha_rows rows)
+ { return (double) rows / 20.0+1; }
virtual bool fast_key_read() { return 1;}
int open(const char *name, int mode, uint test_if_locked);
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index 4f955d8f79e..a426dc5a9a9 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -100,7 +100,7 @@ char* innobase_unix_file_flush_method = NULL;
/* Below we have boolean-valued start-up parameters, and their default
values */
-uint innobase_flush_log_at_trx_commit = 0;
+uint innobase_flush_log_at_trx_commit = 1;
my_bool innobase_log_archive = FALSE;
my_bool innobase_use_native_aio = FALSE;
my_bool innobase_fast_shutdown = TRUE;
@@ -242,6 +242,10 @@ convert_error_code_to_mysql(
return(HA_ERR_CANNOT_ADD_FOREIGN);
+ } else if (error == (int) DB_CANNOT_DROP_CONSTRAINT) {
+
+ return(HA_WRONG_CREATE_OPTION);
+
} else if (error == (int) DB_COL_APPEARS_TWICE_IN_INDEX) {
return(HA_ERR_CRASHED);
@@ -597,7 +601,7 @@ innobase_invalidate_query_cache(
Call this when you have opened a new table handle in HANDLER, before you
call index_read_idx() etc. Actually, we can let the cursor stay open even
over a transaction commit! Then you should call this before every operation,
-fecth next etc. This function inits the necessary things even after a
+fetch next etc. This function inits the necessary things even after a
transaction commit. */
void
@@ -644,6 +648,8 @@ ha_innobase::init_table_handle_for_HANDLER(void)
we???? */
prebuilt->read_just_key = FALSE;
+
+ prebuilt->used_in_HANDLER = TRUE;
}
/*************************************************************************
@@ -883,7 +889,7 @@ innobase_flush_logs(void)
DBUG_ENTER("innobase_flush_logs");
- log_flush_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP);
+ log_write_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP, TRUE);
DBUG_RETURN(result);
}
@@ -932,7 +938,7 @@ Commits a transaction in an InnoDB database. */
int
innobase_commit(
/*============*/
- /* out: 0 or error number */
+ /* out: 0 */
THD* thd, /* in: MySQL thread handle of the user for whom
the transaction should be committed */
void* trx_handle)/* in: InnoDB trx handle or
@@ -940,7 +946,6 @@ innobase_commit(
that the current SQL statement ended, and we should
mark the start of a new statement with a savepoint */
{
- int error = 0;
trx_t* trx;
DBUG_ENTER("innobase_commit");
@@ -967,29 +972,27 @@ innobase_commit(
innobase_release_stat_resources(trx);
trx_mark_sql_stat_end(trx);
-#ifndef DBUG_OFF
- if (error) {
- DBUG_PRINT("error", ("error: %d", error));
- }
-#endif
/* Tell InnoDB server that there might be work for
utility threads: */
srv_active_wake_master_thread();
- DBUG_RETURN(error);
+ DBUG_RETURN(0);
}
/*********************************************************************
This is called when MySQL writes the binlog entry for the current
transaction. Writes to the InnoDB tablespace info which tells where the
MySQL binlog entry for the current transaction ended. Also commits the
-transaction inside InnoDB. */
+transaction inside InnoDB but does NOT flush InnoDB log files to disk.
+To flush you have to call innobase_flush_log_to_disk. We have separated
+flushing to eliminate the bottleneck of LOCK_log in log.cc which disabled
+InnoDB's group commit capability. */
int
innobase_report_binlog_offset_and_commit(
/*=====================================*/
- /* out: 0 or error code */
+ /* out: 0 */
THD* thd, /* in: user thread */
void* trx_handle, /* in: InnoDB trx handle */
char* log_file_name, /* in: latest binlog file name */
@@ -1005,7 +1008,39 @@ innobase_report_binlog_offset_and_commit(
trx->mysql_log_file_name = log_file_name;
trx->mysql_log_offset = (ib_longlong)end_offset;
- return(innobase_commit(thd, trx_handle));
+ trx->flush_log_later = TRUE;
+
+ innobase_commit(thd, trx_handle);
+
+ trx->flush_log_later = FALSE;
+
+ return(0);
+}
+
+/*********************************************************************
+This is called after MySQL has written the binlog entry for the current
+transaction. Flushes the InnoDB log files to disk if required. */
+
+int
+innobase_commit_complete(
+/*=====================*/
+ /* out: 0 */
+ void* trx_handle) /* in: InnoDB trx handle */
+{
+ trx_t* trx;
+
+ if (srv_flush_log_at_trx_commit == 0) {
+
+ return(0);
+ }
+
+ trx = (trx_t*)trx_handle;
+
+ ut_a(trx != NULL);
+
+ trx_commit_complete_for_mysql(trx);
+
+ return(0);
}
/*********************************************************************
@@ -1195,6 +1230,9 @@ ha_innobase::open(
last_query_id = (ulong)-1;
+ active_index = 0;
+ active_index_before_scan = (uint)-1; /* undefined value */
+
if (!(share=get_share(name)))
DBUG_RETURN(1);
@@ -1938,13 +1976,6 @@ ha_innobase::write_row(
build_template(prebuilt, NULL, table, ROW_MYSQL_WHOLE_ROW);
}
- if (user_thd->lex.sql_command == SQLCOM_INSERT
- && user_thd->lex.duplicates == DUP_IGNORE) {
- prebuilt->trx->ignore_duplicates_in_insert = TRUE;
- } else {
- prebuilt->trx->ignore_duplicates_in_insert = FALSE;
- }
-
srv_conc_enter_innodb(prebuilt->trx);
error = row_insert_for_mysql((byte*) record, prebuilt);
@@ -1985,8 +2016,6 @@ ha_innobase::write_row(
}
}
- prebuilt->trx->ignore_duplicates_in_insert = FALSE;
-
error = convert_error_code_to_mysql(error, user_thd);
/* Tell InnoDB server that there might be work for
@@ -2057,7 +2086,8 @@ calc_row_difference(
upd_t* uvect, /* in/out: update vector */
mysql_byte* old_row, /* in: old row in MySQL format */
mysql_byte* new_row, /* in: new row in MySQL format */
- struct st_table* table, /* in: table in MySQL data dictionary */
+ struct st_table* table, /* in: table in MySQL data
+ dictionary */
mysql_byte* upd_buff, /* in: buffer to use */
row_prebuilt_t* prebuilt, /* in: InnoDB prebuilt struct */
THD* thd) /* in: user thread */
@@ -2107,8 +2137,10 @@ calc_row_difference(
case DATA_VARCHAR:
case DATA_BINARY:
case DATA_VARMYSQL:
- o_ptr = row_mysql_read_var_ref_noninline(&o_len, o_ptr);
- n_ptr = row_mysql_read_var_ref_noninline(&n_len, n_ptr);
+ o_ptr = row_mysql_read_var_ref_noninline(&o_len,
+ o_ptr);
+ n_ptr = row_mysql_read_var_ref_noninline(&n_len,
+ n_ptr);
default:
;
}
@@ -2556,7 +2588,7 @@ ha_innobase::change_active_index(
/* MySQL changes the active index for a handle also during some
queries, for example SELECT MAX(a), SUM(a) first retrieves the MAX()
- and then calculates te sum. Previously we played safe and used
+ and then calculates the sum. Previously we played safe and used
the flag ROW_MYSQL_WHOLE_ROW below, but that caused unnecessary
copying. Starting from MySQL-4.1 we use a more efficient flag here. */
@@ -2755,6 +2787,11 @@ ha_innobase::rnd_init(
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
+ /* Store the active index value so that we can restore the original
+ value after a scan */
+
+ active_index_before_scan = active_index;
+
if (prebuilt->clust_index_was_generated) {
err = change_active_index(MAX_KEY);
} else {
@@ -2767,13 +2804,25 @@ ha_innobase::rnd_init(
}
/*********************************************************************
-Ends a table scan ???????????????? */
+Ends a table scan. */
int
ha_innobase::rnd_end(void)
/*======================*/
/* out: 0 or error number */
{
+ /* Restore the old active_index back; MySQL may assume that a table
+ scan does not change active_index. We only restore the value if
+ MySQL has called rnd_init before: sometimes MySQL seems to call
+ rnd_end WITHOUT calling rnd_init. */
+
+ if (active_index_before_scan != (uint)-1) {
+
+ change_active_index(active_index_before_scan);
+
+ active_index_before_scan = (uint)-1;
+ }
+
return(index_end());
}
@@ -3088,6 +3137,9 @@ ha_innobase::create(
trx_search_latch_release_if_reserved(parent_trx);
trx = trx_allocate_for_mysql();
+
+ trx->mysql_thd = thd;
+ trx->mysql_query_str = &((*thd).query);
if (thd->options & OPTION_NO_FOREIGN_KEY_CHECKS) {
trx->check_foreigns = FALSE;
@@ -3216,7 +3268,7 @@ ha_innobase::create(
the InnoDB data dictionary get out-of-sync if the user runs
with innodb_flush_log_at_trx_commit = 0 */
- log_flush_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP);
+ log_write_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP, TRUE);
innobase_table = dict_table_get(norm_name, NULL);
@@ -3271,6 +3323,9 @@ ha_innobase::delete_table(
trx = trx_allocate_for_mysql();
+ trx->mysql_thd = current_thd;
+ trx->mysql_query_str = &((*current_thd).query);
+
name_len = strlen(name);
assert(name_len < 1000);
@@ -3288,7 +3343,7 @@ ha_innobase::delete_table(
the InnoDB data dictionary get out-of-sync if the user runs
with innodb_flush_log_at_trx_commit = 0 */
- log_flush_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP);
+ log_write_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP, TRUE);
/* Tell the InnoDB server that there might be work for
utility threads: */
@@ -3349,6 +3404,8 @@ innobase_drop_database(
my_casedn_str(system_charset_info, namebuf);
#endif
trx = trx_allocate_for_mysql();
+ trx->mysql_thd = current_thd;
+ trx->mysql_query_str = &((*current_thd).query);
error = row_drop_database_for_mysql(namebuf, trx);
@@ -3356,7 +3413,7 @@ innobase_drop_database(
the InnoDB data dictionary get out-of-sync if the user runs
with innodb_flush_log_at_trx_commit = 0 */
- log_flush_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP);
+ log_write_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP, TRUE);
/* Tell the InnoDB server that there might be work for
utility threads: */
@@ -3408,6 +3465,8 @@ ha_innobase::rename_table(
}
trx = trx_allocate_for_mysql();
+ trx->mysql_thd = current_thd;
+ trx->mysql_query_str = &((*current_thd).query);
name_len1 = strlen(from);
name_len2 = strlen(to);
@@ -3426,7 +3485,7 @@ ha_innobase::rename_table(
the InnoDB data dictionary get out-of-sync if the user runs
with innodb_flush_log_at_trx_commit = 0 */
- log_flush_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP);
+ log_write_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP, TRUE);
/* Tell the InnoDB server that there might be work for
utility threads: */
@@ -3541,10 +3600,8 @@ ha_innobase::records_in_range(
/*************************************************************************
Gives an UPPER BOUND to the number of rows in a table. This is used in
-filesort.cc and the upper bound must hold. TODO: Since the number of
-rows in a table may change after this function is called, we still may
-get a 'Sort aborted' error in filesort.cc of MySQL. The ultimate fix is to
-improve the algorithm of filesort.cc. */
+filesort.cc and its better if the upper bound hold.
+*/
ha_rows
ha_innobase::estimate_number_of_rows(void)
@@ -3610,6 +3667,29 @@ ha_innobase::scan_time()
return((double) (prebuilt->table->stat_clustered_index_size));
}
+/*
+ Calculate the time it takes to read a set of ranges through and index
+ This enables us to optimise reads for clustered indexes.
+*/
+
+double ha_innobase::read_time(uint index, uint ranges, ha_rows rows)
+{
+ ha_rows total_rows;
+ double time_for_scan;
+ if (index != table->primary_key)
+ return handler::read_time(index, ranges, rows); // Not clustered
+ if (rows <= 2)
+ return (double) rows;
+ /*
+ Assume that the read is proportional to scan time for all rows + one
+ seek per range.
+ */
+ time_for_scan= scan_time();
+ if ((total_rows= estimate_number_of_rows()) < rows)
+ return time_for_scan;
+ return (ranges + (double) rows / (double) total_rows * time_for_scan);
+}
+
/*************************************************************************
Returns statistics information of the table to the MySQL interpreter,
in various fields of the handle object. */
@@ -3734,6 +3814,23 @@ ha_innobase::info(
DBUG_VOID_RETURN;
}
+/**************************************************************************
+Updates index cardinalities of the table, based on 10 random dives into
+each index tree. This does NOT calculate exact statistics of the table. */
+
+int
+ha_innobase::analyze(
+/*=================*/
+ /* out: returns always 0 (success) */
+ THD* thd, /* in: connection thread handle */
+ HA_CHECK_OPT* check_opt) /* in: currently ignored */
+{
+ /* Simply call ::info() with all the flags */
+ info(HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE);
+
+ return(0);
+}
+
/***********************************************************************
Tries to check that an InnoDB table is not corrupted. If corruption is
noticed, prints to stderr information about it. In case of corruption
@@ -3915,7 +4012,7 @@ ha_innobase::extra(
break;
case HA_EXTRA_RESET_STATE:
prebuilt->read_just_key = 0;
- break;
+ break;
case HA_EXTRA_NO_KEYREAD:
prebuilt->read_just_key = 0;
break;
@@ -4084,6 +4181,8 @@ ha_innobase::external_lock(
trx->mysql_n_tables_locked = 0;
+ prebuilt->used_in_HANDLER = FALSE;
+
/* Here we release the search latch and InnoDB
thread FIFO ticket if they were reserved. */
diff --git a/sql/ha_innodb.h b/sql/ha_innodb.h
index be1174added..9ca8475e75e 100644
--- a/sql/ha_innodb.h
+++ b/sql/ha_innodb.h
@@ -58,7 +58,15 @@ class ha_innobase: public handler
ulong start_of_scan; /* this is set to 1 when we are
starting a table scan but have not
yet fetched any row, else 0 */
-
+ uint active_index_before_scan;
+ /* since a table scan in InnoDB is
+ always done through an index, a table
+ scan may change active_index; but
+ MySQL may assume that active_index
+ after a table scan is the same as
+ before; we store the value here so
+ that we can restore the value after
+ a scan */
uint last_match_mode;/* match mode of the latest search:
ROW_SEL_EXACT, ROW_SEL_EXACT_PREFIX,
or undefined */
@@ -118,6 +126,7 @@ class ha_innobase: public handler
void initialize(void);
int close(void);
double scan_time();
+ double read_time(uint index, uint ranges, ha_rows rows);
int write_row(byte * buf);
int update_row(const byte * old_data, byte * new_data);
@@ -143,6 +152,7 @@ class ha_innobase: public handler
void position(const byte *record);
void info(uint);
+ int analyze(THD* thd,HA_CHECK_OPT* check_opt);
int extra(enum ha_extra_function operation);
int reset(void);
int external_lock(THD *thd, int lock_type);
@@ -189,6 +199,9 @@ extern char *innobase_unix_file_flush_method;
/* The following variables have to be my_bool for SHOW VARIABLES to work */
extern my_bool innobase_log_archive,
innobase_use_native_aio, innobase_fast_shutdown;
+extern "C" {
+extern ulong srv_max_buf_pool_modified_pct;
+}
extern TYPELIB innobase_lock_typelib;
@@ -203,6 +216,8 @@ int innobase_report_binlog_offset_and_commit(
void* trx_handle,
char* log_file_name,
my_off_t end_offset);
+int innobase_commit_complete(
+ void* trx_handle);
int innobase_rollback(THD *thd, void* trx_handle);
int innobase_close_connection(THD *thd);
int innobase_drop_database(char *path);
diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc
index 213f5baf388..a9c3ddaef60 100644
--- a/sql/ha_myisam.cc
+++ b/sql/ha_myisam.cc
@@ -499,7 +499,7 @@ int ha_myisam::repair(THD* thd, HA_CHECK_OPT *check_opt)
param.thd = thd;
param.op_name = (char*) "repair";
param.testflag = ((check_opt->flags & ~(T_EXTEND)) |
- T_SILENT | T_FORCE_CREATE |
+ T_SILENT | T_FORCE_CREATE | T_CALC_CHECKSUM |
(check_opt->flags & T_EXTEND ? T_REP : T_REP_BY_SORT));
param.sort_buffer_length= check_opt->sort_buffer_size;
start_records=file->state->records;
@@ -592,10 +592,24 @@ int ha_myisam::repair(THD *thd, MI_CHECK &param, bool optimize)
{
local_testflag|= T_STATISTICS;
param.testflag|= T_STATISTICS; // We get this for free
- thd->proc_info="Repair by sorting";
statistics_done=1;
- error = mi_repair_by_sort(&param, file, fixed_name,
- param.testflag & T_QUICK);
+ if (current_thd->variables.myisam_repair_threads>1)
+ {
+ char buf[40];
+ /* TODO: respect myisam_repair_threads variable */
+ my_snprintf(buf, 40, "Repair with %d threads", my_count_bits(key_map));
+ thd->proc_info=buf;
+ error = mi_repair_parallel(&param, file, fixed_name,
+ param.testflag & T_QUICK);
+ thd->proc_info="Repair done"; // to reset proc_info, as
+ // it was pointing to local buffer
+ }
+ else
+ {
+ thd->proc_info="Repair by sorting";
+ error = mi_repair_by_sort(&param, file, fixed_name,
+ param.testflag & T_QUICK);
+ }
}
else
{
diff --git a/sql/handler.cc b/sql/handler.cc
index f2b7dbdf531..db1857e938c 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -253,6 +253,9 @@ int ha_autocommit_or_rollback(THD *thd, int error)
replication. This function also calls the commit of the table
handler, because the order of transactions in the log of the table
handler must be the same as in the binlog.
+ NOTE that to eliminate the bottleneck of the group commit, we do not
+ flush the handler log files here, but only later in a call of
+ ha_commit_complete().
arguments:
thd: the thread handle of the current connection
@@ -279,13 +282,38 @@ int ha_report_binlog_offset_and_commit(THD *thd,
my_error(ER_ERROR_DURING_COMMIT, MYF(0), error);
error=1;
}
- trans->innodb_active_trans=0;
}
#endif
return error;
}
/*
+ Flushes the handler log files (if my.cnf settings do not free us from it)
+ after we have called ha_report_binlog_offset_and_commit(). To eliminate
+ the bottleneck from the group commit, this should be called when
+ LOCK_log has been released in log.cc.
+
+ arguments:
+ thd: the thread handle of the current connection
+ return value: always 0
+*/
+
+int ha_commit_complete(THD *thd)
+{
+#ifdef HAVE_INNOBASE_DB
+ THD_TRANS *trans;
+ trans = &thd->transaction.all;
+ if (trans->innobase_tid)
+ {
+ innobase_commit_complete(trans->innobase_tid);
+
+ trans->innodb_active_trans=0;
+ }
+#endif
+ return 0;
+}
+
+/*
This function should be called when MySQL sends rows of a SELECT result set
or the EOF mark to the client. It releases a possible adaptive hash index
S-latch held by thd in InnoDB and also releases a possible InnoDB query
@@ -812,7 +840,8 @@ void handler::print_error(int error, myf errflag)
DBUG_VOID_RETURN;
}
- /* Return key if error because of duplicated keys */
+
+/* Return key if error because of duplicated keys */
uint handler::get_dup_key(int error)
{
@@ -823,6 +852,7 @@ uint handler::get_dup_key(int error)
DBUG_RETURN(table->file->errkey);
}
+
int handler::delete_table(const char *name)
{
int error=0;
@@ -849,9 +879,10 @@ int handler::rename_table(const char * from, const char * to)
DBUG_RETURN(0);
}
-/* Tell the handler to turn on or off logging to the handler's
- recovery log
+/*
+ Tell the handler to turn on or off logging to the handler's recovery log
*/
+
int ha_recovery_logging(THD *thd, bool on)
{
int error=0;
@@ -906,7 +937,6 @@ bool handler::caching_allowed(THD* thd, char* table_key,
int ha_create_table(const char *name, HA_CREATE_INFO *create_info,
bool update_create_info)
-
{
int error;
TABLE table;
diff --git a/sql/handler.h b/sql/handler.h
index 8c23a3625e0..97ce295d520 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -235,7 +235,8 @@ 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 rows2double(rows); }
+ virtual double read_time(uint index, uint ranges, ha_rows rows)
+ { return rows2double(ranges+rows); }
virtual bool fast_key_read() { return 0;}
virtual key_map keys_to_use_for_scanning() { return 0; }
virtual bool has_transactions(){ return 0;}
@@ -389,6 +390,7 @@ void ha_resize_key_cache(void);
int ha_start_stmt(THD *thd);
int ha_report_binlog_offset_and_commit(THD *thd, char *log_file_name,
my_off_t end_offset);
+int ha_commit_complete(THD *thd);
int ha_release_temporary_latches(THD *thd);
int ha_commit_trans(THD *thd, THD_TRANS *trans);
int ha_rollback_trans(THD *thd, THD_TRANS *trans);
diff --git a/sql/init.cc b/sql/init.cc
index 8834fd3a89c..50d504068a0 100644
--- a/sql/init.cc
+++ b/sql/init.cc
@@ -38,13 +38,11 @@ void unireg_init(ulong options)
init_my_atof(); /* use our atof */
#endif
my_abort_hook=unireg_abort; /* Abort with close of databases */
- f_fyllchar=' '; /* Input fill char */
VOID(strmov(reg_ext,".frm"));
for (i=0 ; i < 6 ; i++) // YYMMDDHHMMSS
dayord.pos[i]=i;
specialflag=SPECIAL_SAME_DB_NAME;
- blob_newline='^'; /* Convert newline in blobs to this */
/* Make a tab of powers of 10 */
for (i=0,nr=1.0; i < array_elements(log_10) ; i++)
{ /* It's used by filesort... */
diff --git a/sql/item.cc b/sql/item.cc
index 053a94cb695..7599ae6486f 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -1048,6 +1048,14 @@ inline uint char_val(char X)
X-'a'+10);
}
+/* In MySQL 4.1 this will always return STRING_RESULT */
+
+enum Item_result Item_varbinary::result_type () const
+{
+ return (current_thd->variables.new_mode) ? STRING_RESULT : INT_RESULT;
+}
+
+
Item_varbinary::Item_varbinary(const char *str, uint str_length)
{
name=(char*) str-2; // Lex makes this start with 0x
diff --git a/sql/item_create.cc b/sql/item_create.cc
index 1e547a9c76e..b027b156641 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -321,7 +321,7 @@ Item *create_func_current_user()
char buff[HOSTNAME_LENGTH+USERNAME_LENGTH+2];
uint length;
- length= (uint) (strxmov(buff, thd->priv_user, "@", thd->host_or_ip, NullS) -
+ length= (uint) (strxmov(buff, thd->priv_user, "@", thd->priv_host, NullS) -
buff);
return new Item_string(NullS, thd->memdup(buff, length), length,
default_charset_info);
diff --git a/sql/item_func.cc b/sql/item_func.cc
index d427e3c5a3a..eeab2367b2e 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -109,15 +109,16 @@ Item_func::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{ // Print purify happy
for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++)
{
- if ((*arg)->fix_fields(thd, tables, arg) ||
- (*arg)->check_cols(allowed_arg_cols))
+ Item *item= *arg;
+ if (item->fix_fields(thd, tables, arg) ||
+ item->check_cols(allowed_arg_cols))
return 1; /* purecov: inspected */
- if ((*arg)->maybe_null)
+ if (item->maybe_null)
maybe_null=1;
- with_sum_func= with_sum_func || (*arg)->with_sum_func;
- used_tables_cache|=(*arg)->used_tables();
- const_item_cache&= (*arg)->const_item();
+ with_sum_func= with_sum_func || item->with_sum_func;
+ used_tables_cache|=item->used_tables();
+ const_item_cache&= item->const_item();
}
}
fix_length_and_dec();
@@ -140,14 +141,15 @@ void Item_func::split_sum_func(Item **ref_pointer_array, List<Item> &fields)
Item **arg, **arg_end;
for (arg= args, arg_end= args+arg_count; arg != arg_end ; arg++)
{
- if ((*arg)->with_sum_func && (*arg)->type() != SUM_FUNC_ITEM)
- (*arg)->split_sum_func(ref_pointer_array, fields);
- else if ((*arg)->used_tables() || (*arg)->type() == SUM_FUNC_ITEM)
+ Item *item=* arg;
+ if (item->with_sum_func && item->type() != SUM_FUNC_ITEM)
+ item->split_sum_func(ref_pointer_array, fields);
+ else if (item->used_tables() || item->type() == SUM_FUNC_ITEM)
{
uint el= fields.elements;
- fields.push_front(*arg);
- ref_pointer_array[el]= *arg;
- *arg= new Item_ref(ref_pointer_array + el, 0, (*arg)->name);
+ fields.push_front(item);
+ ref_pointer_array[el]= item;
+ *arg= new Item_ref(ref_pointer_array + el, 0, item->name);
}
}
}
@@ -1247,47 +1249,6 @@ longlong Item_func_find_in_set::val_int()
return 0;
}
-static char nbits[256] = {
- 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
- 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
- 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
- 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
- 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
- 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
- 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
- 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
- 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
- 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
- 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
- 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
- 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
- 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
- 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
- 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8,
-};
-
-uint count_bits(ulonglong v)
-{
-#if SIZEOF_LONG_LONG > 4
- /* The following code is a bit faster on 16 bit machines than if we would
- only shift v */
- ulong v2=(ulong) (v >> 32);
- return (uint) (uchar) (nbits[(uchar) v] +
- nbits[(uchar) (v >> 8)] +
- nbits[(uchar) (v >> 16)] +
- nbits[(uchar) (v >> 24)] +
- nbits[(uchar) (v2)] +
- nbits[(uchar) (v2 >> 8)] +
- nbits[(uchar) (v2 >> 16)] +
- nbits[(uchar) (v2 >> 24)]);
-#else
- return (uint) (uchar) (nbits[(uchar) v] +
- nbits[(uchar) (v >> 8)] +
- nbits[(uchar) (v >> 16)] +
- nbits[(uchar) (v >> 24)]);
-#endif
-}
-
longlong Item_func_bit_count::val_int()
{
ulonglong value= (ulonglong) args[0]->val_int();
@@ -1296,7 +1257,7 @@ longlong Item_func_bit_count::val_int()
null_value=1; /* purecov: inspected */
return 0; /* purecov: inspected */
}
- return (longlong) count_bits(value);
+ return (longlong) my_count_bits(value);
}
@@ -1370,16 +1331,17 @@ udf_handler::fix_fields(THD *thd, TABLE_LIST *tables, Item_result_field *func,
arg != arg_end ;
arg++,i++)
{
- if ((*arg)->fix_fields(thd, tables, arg) || (*arg)->check_cols(1))
+ Item *item= *arg;
+ if (item->fix_fields(thd, tables, arg) || item->check_cols(1))
return 1;
- if ((*arg)->binary())
+ if (item->binary())
func->set_charset(&my_charset_bin);
- if ((*arg)->maybe_null)
+ if (item->maybe_null)
func->maybe_null=1;
- func->with_sum_func= func->with_sum_func || (*arg)->with_sum_func;
- used_tables_cache|=(*arg)->used_tables();
- const_item_cache&=(*arg)->const_item();
- f_args.arg_type[i]=(*arg)->result_type();
+ func->with_sum_func= func->with_sum_func || item->with_sum_func;
+ used_tables_cache|=item->used_tables();
+ const_item_cache&=item->const_item();
+ f_args.arg_type[i]=item->result_type();
}
if (!(buffers=new String[arg_count]) ||
!(f_args.args= (char**) sql_alloc(arg_count * sizeof(char *))) ||
@@ -2449,7 +2411,7 @@ bool Item_func_match::fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
used_tables_cache|=item->used_tables();
}
/* check that all columns come from the same table */
- if (count_bits(used_tables_cache) != 1)
+ if (my_count_bits(used_tables_cache) != 1)
key=NO_SUCH_KEY;
const_item_cache=0;
table=((Item_field *)fields.head())->field->table;
@@ -2623,10 +2585,7 @@ Item *get_system_var(enum_var_type var_type, LEX_STRING name)
char buff[MAX_SYS_VAR_LENGTH+3+8], *pos;
if (!(var= find_sys_var(name.str, name.length)))
- {
- net_printf(thd, ER_UNKNOWN_SYSTEM_VARIABLE, name.str);
return 0;
- }
if (!(item=var->item(thd, var_type)))
return 0; // Impossible
thd->lex.uncacheable();
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 6118b25a88c..d28341c3bd0 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -27,9 +27,6 @@
#include "mysql_priv.h"
#include "sql_acl.h"
#include <m_ctype.h>
-#ifdef HAVE_CRYPT_H
-#include <crypt.h>
-#endif
#ifdef HAVE_OPENSSL
#include <openssl/des.h>
#endif /* HAVE_OPENSSL */
@@ -925,7 +922,7 @@ void Item_str_func::left_right_max_length()
max_length=args[0]->max_length;
if (args[1]->const_item())
{
- int length=(int) args[1]->val_int();
+ int length=(int) args[1]->val_int()*default_charset_info->mbmaxlen;
if (length <= 0)
max_length=0;
else
@@ -1006,7 +1003,7 @@ void Item_func_substr::fix_length_and_dec()
}
if (arg_count == 3 && args[2]->const_item())
{
- int32 length= (int32) args[2]->val_int();
+ int32 length= (int32) args[2]->val_int() * default_charset_info->mbmaxlen;
if (length <= 0)
max_length=0; /* purecov: inspected */
else
@@ -1585,15 +1582,17 @@ String *Item_func_format::val_str(String *str)
str_length=str->length();
if (nr < 0)
str_length--; // Don't count sign
- length=str->length()+(diff=(str_length- dec-1)/3);
- if (diff)
+
+ /* We need this test to handle 'nan' values */
+ if (str_length >= dec+4)
{
char *tmp,*pos;
- str=copy_if_not_alloced(&tmp_str,str,length);
+ length= str->length()+(diff=(str_length- dec-1)/3);
+ str= copy_if_not_alloced(&tmp_str,str,length);
str->length(length);
- tmp=(char*) str->ptr()+length - dec-1;
- for (pos=(char*) str->ptr()+length ; pos != tmp; pos--)
- pos[0]=pos[- (int) diff];
+ tmp= (char*) str->ptr()+length - dec-1;
+ for (pos= (char*) str->ptr()+length ; pos != tmp; pos--)
+ pos[0]= pos[-(int) diff];
while (diff)
{
pos[0]=pos[-(int) diff]; pos--;
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 11c850f9d5f..fa8bf7e6e0f 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -219,12 +219,14 @@ Item_sum_hybrid::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
void Item_sum_sum::reset()
{
- null_value=0; sum=0.0; Item_sum_sum::add();
+ null_value=1; sum=0.0; Item_sum_sum::add();
}
bool Item_sum_sum::add()
{
sum+=args[0]->val();
+ if (!args[0]->null_value)
+ null_value= 0;
return 0;
}
@@ -641,8 +643,10 @@ void Item_sum_sum::reset_field()
{
double nr=args[0]->val(); // Nulls also return 0
float8store(result_field->ptr,nr);
- null_value=0;
- result_field->set_notnull();
+ if (args[0]->null_value)
+ result_field->set_null();
+ else
+ result_field->set_notnull();
}
@@ -698,7 +702,10 @@ void Item_sum_sum::update_field(int offset)
float8get(old_nr,res+offset);
nr=args[0]->val();
if (!args[0]->null_value)
+ {
old_nr+=nr;
+ result_field->set_notnull();
+ }
float8store(res,old_nr);
}
diff --git a/sql/item_sum.h b/sql/item_sum.h
index 37d7e7f79d0..f996f980fff 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -99,9 +99,6 @@ public:
class Item_sum_int :public Item_sum_num
{
- void fix_length_and_dec()
- { decimals=0; max_length=21; maybe_null=null_value=0; }
-
public:
Item_sum_int(Item *item_par) :Item_sum_num(item_par) {}
Item_sum_int(List<Item> &list) :Item_sum_num(list) {}
@@ -109,6 +106,8 @@ public:
double val() { return (double) val_int(); }
String *val_str(String*str);
enum Item_result result_type () const { return INT_RESULT; }
+ void fix_length_and_dec()
+ { decimals=0; max_length=21; maybe_null=null_value=0; }
};
@@ -127,6 +126,7 @@ class Item_sum_sum :public Item_sum_num
double val();
void reset_field();
void update_field(int offset);
+ void no_rows_in_result() {}
const char *func_name() const { return "sum"; }
Item *copy_or_same(THD* thd) { return new Item_sum_sum(thd, *this); }
};
@@ -449,6 +449,8 @@ class Item_sum_bit :public Item_sum_int
void reset();
longlong val_int();
void reset_field();
+ void fix_length_and_dec()
+ { decimals=0; max_length=21; unsigned_flag=1; maybe_null=null_value=0; }
};
diff --git a/sql/log.cc b/sql/log.cc
index c9e20bc0cc9..c05d52bdc5d 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -317,7 +317,10 @@ bool MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg,
DBUG_RETURN(0);
err:
- sql_print_error("Could not use %s for logging (error %d)", log_name, errno);
+ sql_print_error("Could not use %s for logging (error %d). \
+Turning logging off for the whole duration of the MySQL server process. \
+To turn it on again: fix the cause, \
+shutdown the MySQL server and restart it.", log_name, errno);
if (file >= 0)
my_close(file,MYF(0));
if (index_file_nr >= 0)
@@ -1157,6 +1160,8 @@ bool MYSQL_LOG::write(THD *thd,enum enum_server_command command,
bool MYSQL_LOG::write(Log_event* event_info)
{
+ THD *thd=event_info->thd;
+ bool called_handler_commit=0;
bool error=0;
bool should_rotate = 0;
DBUG_ENTER("MYSQL_LOG::write(event)");
@@ -1171,7 +1176,6 @@ bool MYSQL_LOG::write(Log_event* event_info)
/* In most cases this is only called if 'is_open()' is true */
if (is_open())
{
- THD *thd=event_info->thd;
const char *local_db = event_info->get_db();
#ifdef USING_TRANSACTIONS
IO_CACHE *file = ((event_info->get_cache_stmt()) ?
@@ -1268,24 +1272,35 @@ bool MYSQL_LOG::write(Log_event* event_info)
the table handler commit here, protected by the LOCK_log mutex,
because otherwise the transactions may end up in a different order
in the table handler log!
+
+ Note that we will NOT call ha_report_binlog_offset_and_commit() if
+ there are binlog events cached in the transaction cache. That is
+ because then the log event which we write to the binlog here is
+ not a transactional event. In versions < 4.0.13 before this fix this
+ caused an InnoDB transaction to be committed if in the middle there
+ was a MyISAM event!
*/
- if (file == &log_file)
+ if (file == &log_file) // we are writing to the real log (disk)
{
- /*
- LOAD DATA INFILE in AUTOCOMMIT=1 mode writes to the binlog
- chunks also before it is successfully completed. We only report
- the binlog write and do the commit inside the transactional table
- handler if the log event type is appropriate.
- */
-
- if (event_info->get_type_code() == QUERY_EVENT
- || event_info->get_type_code() == EXEC_LOAD_EVENT)
+ if (opt_using_transactions && !my_b_tell(&thd->transaction.trans_log))
{
- error = ha_report_binlog_offset_and_commit(thd, log_file_name,
- file->pos_in_file);
+ /*
+ LOAD DATA INFILE in AUTOCOMMIT=1 mode writes to the binlog
+ chunks also before it is successfully completed. We only report
+ the binlog write and do the commit inside the transactional table
+ handler if the log event type is appropriate.
+ */
+
+ if (event_info->get_type_code() == QUERY_EVENT
+ || event_info->get_type_code() == EXEC_LOAD_EVENT)
+ {
+ error = ha_report_binlog_offset_and_commit(thd, log_file_name,
+ file->pos_in_file);
+ called_handler_commit=1;
+ }
}
-
+ /* we wrote to the real log, check automatic rotation */
should_rotate= (my_b_tell(file) >= (my_off_t) max_binlog_size);
}
@@ -1309,6 +1324,16 @@ err:
}
pthread_mutex_unlock(&LOCK_log);
+
+ /*
+ Flush the transactional handler log file now that we have released
+ LOCK_log; the flush is placed here to eliminate the bottleneck on the
+ group commit
+ */
+
+ if (called_handler_commit)
+ ha_commit_complete(thd);
+
#ifdef HAVE_REPLICATION
if (should_rotate && expire_logs_days)
{
@@ -1316,7 +1341,6 @@ err:
if (purge_time >= 0)
error= purge_logs_before_date(purge_time);
}
-
#endif
DBUG_RETURN(error);
}
@@ -1423,6 +1447,13 @@ bool MYSQL_LOG::write(THD *thd, IO_CACHE *cache)
}
VOID(pthread_mutex_unlock(&LOCK_log));
+
+ /* Flush the transactional handler log file now that we have released
+ LOCK_log; the flush is placed here to eliminate the bottleneck on the
+ group commit */
+
+ ha_commit_complete(thd);
+
DBUG_RETURN(0);
err:
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 39db264d898..be5b5079eee 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -26,11 +26,10 @@
#define log_cs &my_charset_latin1
-/*****************************************************************************
-
+/*
my_b_safe_write()
+*/
- ****************************************************************************/
inline int my_b_safe_write(IO_CACHE* file, const byte *buf,
int len)
{
@@ -45,11 +44,11 @@ inline int my_b_safe_write(IO_CACHE* file, const byte *buf,
return my_b_write(file, buf,len);
}
-/*****************************************************************************
+/*
pretty_print_str()
+*/
- ****************************************************************************/
#ifdef MYSQL_CLIENT
static void pretty_print_str(FILE* file, char* str, int len)
{
@@ -75,11 +74,11 @@ static void pretty_print_str(FILE* file, char* str, int len)
}
#endif // MYSQL_CLIENT
-/*****************************************************************************
+/*
ignored_error_code()
+*/
- ****************************************************************************/
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
inline int ignored_error_code(int err_code)
{
@@ -87,11 +86,10 @@ inline int ignored_error_code(int err_code)
}
#endif
-/*****************************************************************************
-
+/*
pretty_print_str()
+*/
- ****************************************************************************/
#ifndef MYSQL_CLIENT
static char* pretty_print_str(char* packet, char* str, int len)
{
@@ -117,13 +115,13 @@ static char* pretty_print_str(char* packet, char* str, int len)
*pos++= '\'';
return pos;
}
-#endif // !MYSQL_CLIENT
+#endif /* !MYSQL_CLIENT */
-/*****************************************************************************
+/*
slave_load_file_stem()
+*/
- ****************************************************************************/
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
static inline char* slave_load_file_stem(char*buf, uint file_id,
int event_server_id)
@@ -138,8 +136,7 @@ static inline char* slave_load_file_stem(char*buf, uint file_id,
}
#endif
-/*****************************************************************************
-
+/*
cleanup_load_tmpdir()
Delete all temporary files used for SQL_LOAD.
@@ -148,8 +145,8 @@ static inline char* slave_load_file_stem(char*buf, uint file_id,
- When we get a 'server start' event, we should only remove
the files associated with the server id that just started.
Easily fixable by adding server_id as a prefix to the log files.
+*/
- ****************************************************************************/
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
static void cleanup_load_tmpdir()
{
@@ -170,22 +167,22 @@ static void cleanup_load_tmpdir()
}
#endif
-/*****************************************************************************
+/*
write_str()
+*/
- ****************************************************************************/
static bool write_str(IO_CACHE *file, char *str, byte length)
{
return (my_b_safe_write(file, &length, 1) ||
my_b_safe_write(file, (byte*) str, (int) length));
}
-/*****************************************************************************
+/*
read_str()
+*/
- ****************************************************************************/
static inline int read_str(char * &buf, char *buf_end, char * &str,
uint8 &len)
{
@@ -198,19 +195,14 @@ static inline int read_str(char * &buf, char *buf_end, char * &str,
}
-/*****************************************************************************
- *****************************************************************************
-
- Log_event methods
-
- *****************************************************************************
- ****************************************************************************/
-
-/*****************************************************************************
+/**************************************************************************/
+ Log_event methods
+***************************************************************************/
+/*
Log_event::get_type_str()
+*/
- ****************************************************************************/
const char* Log_event::get_type_str()
{
switch(get_type_code()) {
@@ -232,11 +224,11 @@ const char* Log_event::get_type_str()
}
}
-/*****************************************************************************
+/*
Log_event::Log_event()
+*/
- ****************************************************************************/
#ifndef MYSQL_CLIENT
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),
@@ -258,13 +250,13 @@ Log_event::Log_event()
when= time(NULL);
log_pos= 0;
}
-#endif // !MYSQL_CLIENT
+#endif /* !MYSQL_CLIENT */
-/*****************************************************************************
+/*
Log_event::Log_event()
+*/
- ****************************************************************************/
Log_event::Log_event(const char* buf, bool old_format)
:temp_buf(0), cached_event_len(0), cache_stmt(0)
{
@@ -285,15 +277,13 @@ Log_event::Log_event(const char* buf, bool old_format)
#endif
}
-
#ifndef MYSQL_CLIENT
#ifdef HAVE_REPLICATION
-/*****************************************************************************
-
+/*
Log_event::exec_event()
+*/
- ****************************************************************************/
int Log_event::exec_event(struct st_relay_log_info* rli)
{
/*
@@ -324,15 +314,15 @@ int Log_event::exec_event(struct st_relay_log_info* rli)
- then it will be MyISAM on the slave
- but as opt_using_transactions is true, the slave will believe he is
transactional with the MyISAM table. And problems will come when one
- does START SLAVE; STOP SLAVE; START SLAVE; (the slave will resume at BEGIN
- whereas there has not been any rollback). This is the problem of
+ does START SLAVE; STOP SLAVE; START SLAVE; (the slave will resume at
+ BEGIN whereas there has not been any rollback). This is the problem of
using opt_using_transactions instead of a finer
"does the slave support _the_transactional_handler_used_on_the_master_".
More generally, we'll have problems when a query mixes a transactional
handler and MyISAM and STOP SLAVE is issued in the middle of the
- "transaction". START SLAVE will resume at BEGIN while the MyISAM table has
- already been updated.
+ "transaction". START SLAVE will resume at BEGIN while the MyISAM table
+ has already been updated.
*/
if ((thd->options & OPTION_BEGIN) && opt_using_transactions)
@@ -346,24 +336,22 @@ int Log_event::exec_event(struct st_relay_log_info* rli)
return 0;
}
-/*****************************************************************************
+/*
Log_event::pack_info()
+*/
- ****************************************************************************/
void Log_event::pack_info(Protocol *protocol)
{
protocol->store("", &my_charset_bin);
}
-/*****************************************************************************
-
+/*
Log_event::net_send()
Only called by SHOW BINLOG EVENTS
-
- ****************************************************************************/
+*/
int Log_event::net_send(Protocol *protocol, const char* log_name, my_off_t pos)
{
@@ -384,11 +372,11 @@ int Log_event::net_send(Protocol *protocol, const char* log_name, my_off_t pos)
}
#endif /* HAVE_REPLICATION */
-/*****************************************************************************
+/*
Log_event::init_show_field_list()
+*/
- ****************************************************************************/
void Log_event::init_show_field_list(List<Item>* field_list)
{
field_list->push_back(new Item_empty_string("Log_name", 20));
@@ -404,21 +392,20 @@ void Log_event::init_show_field_list(List<Item>* field_list)
#endif // !MYSQL_CLIENT
-/*****************************************************************************
-
+/*
Log_event::write()
+*/
- ****************************************************************************/
int Log_event::write(IO_CACHE* file)
{
return (write_header(file) || write_data(file)) ? -1 : 0;
}
-/*****************************************************************************
+/*
Log_event::write_header()
+*/
- ****************************************************************************/
int Log_event::write_header(IO_CACHE* file)
{
char buf[LOG_EVENT_HEADER_LEN];
@@ -439,11 +426,10 @@ int Log_event::write_header(IO_CACHE* file)
}
-/*****************************************************************************
-
+/*
Log_event::read_log_event()
+*/
- ****************************************************************************/
#ifndef MYSQL_CLIENT
int Log_event::read_log_event(IO_CACHE* file, String* packet,
pthread_mutex_t* log_lock)
@@ -510,13 +496,13 @@ end:
#define LOCK_MUTEX
#endif
-/*****************************************************************************
-
+/*
Log_event::read_log_event()
- Allocates memory--the caller is responsible for clean-up
+ NOTE:
+ Allocates memory; The caller is responsible for clean-up
+*/
- ****************************************************************************/
#ifndef MYSQL_CLIENT
Log_event* Log_event::read_log_event(IO_CACHE* file,
pthread_mutex_t* log_lock,
@@ -588,11 +574,11 @@ data_len=%d,event_type=%d",error,data_len,head[EVENT_TYPE_OFFSET]);
return res;
}
-/*****************************************************************************
+/*
Log_event::read_log_event()
+*/
- ****************************************************************************/
Log_event* Log_event::read_log_event(const char* buf, int event_len,
const char **error, bool old_format)
{
@@ -657,9 +643,18 @@ Log_event* Log_event::read_log_event(const char* buf, int event_len,
}
if (!ev || !ev->is_valid())
{
- *error= "Found invalid event in binary log";
delete ev;
+#ifdef MYSQL_CLIENT
+ if (!force_opt)
+ {
+ *error= "Found invalid event in binary log";
+ return 0;
+ }
+ ev= new Unknown_log_event(buf, old_format);
+#else
+ *error= "Found invalid event in binary log";
return 0;
+#endif
}
ev->cached_event_len = event_len;
return ev;
@@ -667,11 +662,10 @@ Log_event* Log_event::read_log_event(const char* buf, int event_len,
#ifdef MYSQL_CLIENT
-/*****************************************************************************
-
+/*
Log_event::print_header()
+*/
- ****************************************************************************/
void Log_event::print_header(FILE* file)
{
char llbuff[22];
@@ -681,11 +675,10 @@ void Log_event::print_header(FILE* file)
llstr(log_pos,llbuff));
}
-/*****************************************************************************
-
+/*
Log_event::print_timestamp()
+*/
- ****************************************************************************/
void Log_event::print_timestamp(FILE* file, time_t* ts)
{
struct tm *res;
@@ -709,11 +702,10 @@ void Log_event::print_timestamp(FILE* file, time_t* ts)
#endif // MYSQL_CLIENT
-/*****************************************************************************
-
+/*
Log_event::set_log_pos()
+*/
- ****************************************************************************/
#ifndef MYSQL_CLIENT
void Log_event::set_log_pos(MYSQL_LOG* log)
{
@@ -723,21 +715,16 @@ void Log_event::set_log_pos(MYSQL_LOG* log)
#endif // !MYSQL_CLIENT
-
-/*****************************************************************************
- *****************************************************************************
-
- Query_log_event methods
-
- *****************************************************************************
- ****************************************************************************/
+/**************************************************************************/
+ Query_log_event methods
+***************************************************************************/
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
-/*****************************************************************************
+/*
Query_log_event::pack_info()
+*/
- ****************************************************************************/
void Query_log_event::pack_info(Protocol *protocol)
{
char *buf, *pos;
@@ -761,21 +748,21 @@ void Query_log_event::pack_info(Protocol *protocol)
}
#endif
-/*****************************************************************************
+/*
Query_log_event::write()
+*/
- ****************************************************************************/
int Query_log_event::write(IO_CACHE* file)
{
return query ? Log_event::write(file) : -1;
}
-/*****************************************************************************
+/*
Query_log_event::write_data()
+*/
- ****************************************************************************/
int Query_log_event::write_data(IO_CACHE* file)
{
if (!query)
@@ -792,11 +779,11 @@ int Query_log_event::write_data(IO_CACHE* file)
my_b_safe_write(file, (byte*) query, q_len)) ? -1 : 0;
}
-/*****************************************************************************
+/*
Query_log_event::Query_log_event()
+*/
- ****************************************************************************/
#ifndef MYSQL_CLIENT
Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg,
ulong query_length, bool using_trans)
@@ -812,13 +799,12 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg,
exec_time = (ulong) (end_time - thd->start_time);
db_len = (db) ? (uint32) strlen(db) : 0;
}
-#endif // MYSQL_CLIENT
-
-/*****************************************************************************
+#endif /* MYSQL_CLIENT */
+/*
Query_log_event::Query_log_event()
+*/
- ****************************************************************************/
Query_log_event::Query_log_event(const char* buf, int event_len,
bool old_format)
:Log_event(buf, old_format),data_buf(0), query(NULL), db(NULL)
@@ -854,11 +840,11 @@ Query_log_event::Query_log_event(const char* buf, int event_len,
*((char*)query+q_len) = 0;
}
-/*****************************************************************************
+/*
Query_log_event::print()
+*/
- ****************************************************************************/
#ifdef MYSQL_CLIENT
void Query_log_event::print(FILE* file, bool short_form, char* last_db)
{
@@ -889,13 +875,13 @@ void Query_log_event::print(FILE* file, bool short_form, char* last_db)
my_fwrite(file, (byte*) query, q_len, MYF(MY_NABP | MY_WME));
fprintf(file, ";\n");
}
-#endif // MYSQL_CLIENT
+#endif /* MYSQL_CLIENT */
-/*****************************************************************************
+/*
Query_log_event::exec_event()
+*/
- ****************************************************************************/
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
int Query_log_event::exec_event(struct st_relay_log_info* rli)
{
@@ -996,19 +982,14 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli)
#endif
-/*****************************************************************************
- *****************************************************************************
-
- Start_log_event methods
-
- *****************************************************************************
- ****************************************************************************/
-
-/*****************************************************************************
+/**************************************************************************/
+ Start_log_event methods
+***************************************************************************/
+/*
Start_log_event::pack_info()
+*/
- ****************************************************************************/
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
void Start_log_event::pack_info(Protocol *protocol)
{
@@ -1021,11 +1002,11 @@ void Start_log_event::pack_info(Protocol *protocol)
}
#endif
-/*****************************************************************************
+/*
Start_log_event::print()
+*/
- ****************************************************************************/
#ifdef MYSQL_CLIENT
void Start_log_event::print(FILE* file, bool short_form, char* last_db)
{
@@ -1035,17 +1016,16 @@ void Start_log_event::print(FILE* file, bool short_form, char* last_db)
print_header(file);
fprintf(file, "\tStart: binlog v %d, server v %s created ", binlog_version,
server_version);
- print_timestamp(file, (time_t*)&created);
+ print_timestamp(file, &created);
fputc('\n', file);
fflush(file);
}
-#endif // MYSQL_CLIENT
-
-/*****************************************************************************
+#endif /* MYSQL_CLIENT */
+/*
Start_log_event::Start_log_event()
+*/
- ****************************************************************************/
Start_log_event::Start_log_event(const char* buf,
bool old_format)
:Log_event(buf, old_format)
@@ -1057,11 +1037,11 @@ Start_log_event::Start_log_event(const char* buf,
created = uint4korr(buf+ST_CREATED_OFFSET);
}
-/*****************************************************************************
+/*
Start_log_event::write_data()
+*/
- ****************************************************************************/
int Start_log_event::write_data(IO_CACHE* file)
{
char buff[START_HEADER_LEN];
@@ -1071,8 +1051,7 @@ int Start_log_event::write_data(IO_CACHE* file)
return (my_b_safe_write(file, (byte*) buff, sizeof(buff)) ? -1 : 0);
}
-/*****************************************************************************
-
+/*
Start_log_event::exec_event()
The master started
@@ -1080,6 +1059,10 @@ int Start_log_event::write_data(IO_CACHE* file)
IMPLEMENTATION
- To handle the case where the master died without a stop event,
we clean up all temporary tables + locks that we got.
+ However, we don't clean temporary tables if the master was 3.23
+ (this is because a 3.23 master writes a Start_log_event at every
+ binlog rotation; if we were not careful we would remove temp tables
+ on the slave when FLUSH LOGS is issued on the master).
TODO
- Remove all active user locks
@@ -1087,36 +1070,37 @@ int Start_log_event::write_data(IO_CACHE* file)
in the middle while writing the transaction to the binary log.
In this case we should stop the slave.
- ****************************************************************************/
+*/
+
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
int Start_log_event::exec_event(struct st_relay_log_info* rli)
{
DBUG_ENTER("Start_log_event::exec_event");
- /* All temporary tables was deleted on the master */
- close_temporary_tables(thd);
- /*
- If we have old format, load_tmpdir is cleaned up by the I/O thread
- */
+
if (!rli->mi->old_format)
+ {
+ /*
+ If 4.0 master, all temporary tables have been deleted on the master;
+ if 3.23 master, this is far from sure.
+ */
+ close_temporary_tables(thd);
+ /*
+ If we have old format, load_tmpdir is cleaned up by the I/O thread
+ */
cleanup_load_tmpdir();
+ }
DBUG_RETURN(Log_event::exec_event(rli));
}
-#endif
-
+#endif /* defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) */
-/*****************************************************************************
- *****************************************************************************
-
- Load_log_event methods
-
- *****************************************************************************
- ****************************************************************************/
-
-/*****************************************************************************
+/**************************************************************************/
+ Load_log_event methods
+***************************************************************************/
+/*
Load_log_event::pack_info()
+*/
- ****************************************************************************/
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
void Load_log_event::pack_info(Protocol *protocol)
{
@@ -1220,13 +1204,13 @@ void Load_log_event::pack_info(Protocol *protocol)
protocol->store(buf, pos-buf, &my_charset_bin);
my_free(buf, MYF(MY_ALLOW_ZERO_PTR));
}
-#endif
+#endif /* defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) */
-/*****************************************************************************
+/*
Load_log_event::write_data_header()
+*/
- ****************************************************************************/
int Load_log_event::write_data_header(IO_CACHE* file)
{
char buf[LOAD_HEADER_LEN];
@@ -1239,11 +1223,11 @@ int Load_log_event::write_data_header(IO_CACHE* file)
return my_b_safe_write(file, (byte*)buf, LOAD_HEADER_LEN);
}
-/*****************************************************************************
+/*
Load_log_event::write_data_body()
+*/
- ****************************************************************************/
int Load_log_event::write_data_body(IO_CACHE* file)
{
if (sql_ex.write_data(file))
@@ -1259,11 +1243,11 @@ int Load_log_event::write_data_body(IO_CACHE* file)
my_b_safe_write(file, (byte*)fname, fname_len));
}
-/*****************************************************************************
+/*
Load_log_event::Load_log_event()
+*/
- ****************************************************************************/
#ifndef MYSQL_CLIENT
Load_log_event::Load_log_event(THD *thd_arg, sql_exchange *ex,
const char *db_arg, const char *table_name_arg,
@@ -1343,16 +1327,16 @@ Load_log_event::Load_log_event(THD *thd_arg, sql_exchange *ex,
field_lens = (const uchar*)field_lens_buf.ptr();
fields = fields_buf.ptr();
}
-#endif // !MYSQL_CLIENT
-
-/*****************************************************************************
+#endif /* !MYSQL_CLIENT */
+/*
Load_log_event::Load_log_event()
- The caller must do buf[event_len] = 0 before he starts using the
- constructed event.
+ NOTE
+ The caller must do buf[event_len] = 0 before he starts using the
+ constructed event.
+*/
- ****************************************************************************/
Load_log_event::Load_log_event(const char *buf, int event_len,
bool old_format)
:Log_event(buf, old_format),num_fields(0),fields(0),
@@ -1364,11 +1348,11 @@ Load_log_event::Load_log_event(const char *buf, int event_len,
copy_log_event(buf, event_len, old_format);
}
-/*****************************************************************************
+/*
Load_log_event::copy_log_event()
+*/
- ****************************************************************************/
int Load_log_event::copy_log_event(const char *buf, ulong event_len,
bool old_format)
{
@@ -1413,11 +1397,11 @@ int Load_log_event::copy_log_event(const char *buf, ulong event_len,
return 0;
}
-/*****************************************************************************
+/*
Load_log_event::print()
+*/
- ****************************************************************************/
#ifdef MYSQL_CLIENT
void Load_log_event::print(FILE* file, bool short_form, char* last_db)
{
@@ -1502,13 +1486,13 @@ void Load_log_event::print(FILE* file, bool short_form, char* last_db)
fprintf(file, ";\n");
}
-#endif /* #ifdef MYSQL_CLIENT */
+#endif /* MYSQL_CLIENT */
-/*****************************************************************************
+/*
Load_log_event::set_fields()
+*/
- ****************************************************************************/
#ifndef MYSQL_CLIENT
void Load_log_event::set_fields(List<Item> &field_list)
{
@@ -1645,12 +1629,11 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli,
close_thread_tables(thd);
if (thd->query_error)
{
- int sql_error = thd->net.last_errno;
+ int sql_error= thd->net.last_errno;
if (!sql_error)
- sql_error = ER_UNKNOWN_ERROR;
-
+ sql_error= ER_UNKNOWN_ERROR;
slave_print_error(rli,sql_error,
- "Slave: Error '%s' running load data infile ",
+ "Error '%s' running LOAD DATA INFILE",
ER_SAFE(sql_error));
free_root(&thd->mem_root,0);
return 1;
@@ -1659,7 +1642,7 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli,
if (thd->is_fatal_error)
{
- sql_print_error("Slave: Fatal error running LOAD DATA INFILE ");
+ sql_print_error("Fatal error running LOAD DATA INFILE");
return 1;
}
@@ -1668,19 +1651,14 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli,
#endif
-/*****************************************************************************
- *****************************************************************************
-
- Rotate_log_event methods
-
- *****************************************************************************
- ****************************************************************************/
-
-/*****************************************************************************
+/****************************************************************************/
+ Rotate_log_event methods
+*****************************************************************************/
+/*
Rotate_log_event::pack_info()
+*/
- ****************************************************************************/
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
void Rotate_log_event::pack_info(Protocol *protocol)
{
@@ -1699,11 +1677,11 @@ void Rotate_log_event::pack_info(Protocol *protocol)
}
#endif
-/*****************************************************************************
+/*
Rotate_log_event::print()
+*/
- ****************************************************************************/
#ifdef MYSQL_CLIENT
void Rotate_log_event::print(FILE* file, bool short_form, char* last_db)
{
@@ -1724,11 +1702,11 @@ void Rotate_log_event::print(FILE* file, bool short_form, char* last_db)
}
#endif // MYSQL_CLIENT
-/*****************************************************************************
+/*
Rotate_log_event::Rotate_log_event()
+*/
- ****************************************************************************/
Rotate_log_event::Rotate_log_event(const char* buf, int event_len,
bool old_format)
:Log_event(buf, old_format),new_log_ident(NULL),alloced(0)
@@ -1760,11 +1738,11 @@ Rotate_log_event::Rotate_log_event(const char* buf, int event_len,
alloced = 1;
}
-/*****************************************************************************
+/*
Rotate_log_event::write_data()
+*/
- ****************************************************************************/
int Rotate_log_event::write_data(IO_CACHE* file)
{
char buf[ROTATE_HEADER_LEN];
@@ -1773,8 +1751,8 @@ int Rotate_log_event::write_data(IO_CACHE* file)
my_b_safe_write(file, (byte*)new_log_ident, (uint) ident_len));
}
-/*****************************************************************************
+/*
Rotate_log_event::exec_event()
Got a rotate log even from the master
@@ -1788,8 +1766,8 @@ int Rotate_log_event::write_data(IO_CACHE* file)
RETURN VALUES
0 ok
+*/
- ****************************************************************************/
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
int Rotate_log_event::exec_event(struct st_relay_log_info* rli)
{
@@ -1810,19 +1788,14 @@ int Rotate_log_event::exec_event(struct st_relay_log_info* rli)
#endif
-/*****************************************************************************
- *****************************************************************************
-
- Intvar_log_event methods
-
- *****************************************************************************
- ****************************************************************************/
-
-/*****************************************************************************
+/***************************************************************************/
+ Intvar_log_event methods
+****************************************************************************/
+/*
Intvar_log_event::pack_info()
+*/
- ****************************************************************************/
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
void Intvar_log_event::pack_info(Protocol *protocol)
{
@@ -1834,11 +1807,11 @@ void Intvar_log_event::pack_info(Protocol *protocol)
}
#endif
-/*****************************************************************************
+/*
Intvar_log_event::Intvar_log_event()
+*/
- ****************************************************************************/
Intvar_log_event::Intvar_log_event(const char* buf, bool old_format)
:Log_event(buf, old_format)
{
@@ -1847,11 +1820,11 @@ Intvar_log_event::Intvar_log_event(const char* buf, bool old_format)
val = uint8korr(buf+I_VAL_OFFSET);
}
-/*****************************************************************************
+/*
Intvar_log_event::get_var_type_name()
+*/
- ****************************************************************************/
const char* Intvar_log_event::get_var_type_name()
{
switch(type) {
@@ -1861,11 +1834,11 @@ const char* Intvar_log_event::get_var_type_name()
}
}
-/*****************************************************************************
+/*
Intvar_log_event::write_data()
+*/
- ****************************************************************************/
int Intvar_log_event::write_data(IO_CACHE* file)
{
char buf[9];
@@ -1874,11 +1847,11 @@ int Intvar_log_event::write_data(IO_CACHE* file)
return my_b_safe_write(file, (byte*) buf, sizeof(buf));
}
-/*****************************************************************************
+/*
Intvar_log_event::print()
+*/
- ****************************************************************************/
#ifdef MYSQL_CLIENT
void Intvar_log_event::print(FILE* file, bool short_form, char* last_db)
{
@@ -1904,13 +1877,13 @@ void Intvar_log_event::print(FILE* file, bool short_form, char* last_db)
fprintf(file, "%s=%s;\n", msg, llstr(val,llbuff));
fflush(file);
}
-#endif // MYSQL_CLIENT
+#endif
-/*****************************************************************************
+/*
Intvar_log_event::exec_event()
+*/
- ****************************************************************************/
#if defined(HAVE_REPLICATION)&& !defined(MYSQL_CLIENT)
int Intvar_log_event::exec_event(struct st_relay_log_info* rli)
{
@@ -2121,11 +2094,10 @@ int User_var_log_event::write_data(IO_CACHE* file)
}
-/*****************************************************************************
-
+/*
User_var_log_event::print()
+*/
- ****************************************************************************/
#ifdef MYSQL_CLIENT
void User_var_log_event::print(FILE* file, bool short_form, char* last_db)
{
@@ -2168,11 +2140,11 @@ void User_var_log_event::print(FILE* file, bool short_form, char* last_db)
}
#endif
-/*****************************************************************************
+/*
User_var_log_event::exec_event()
+*/
- ****************************************************************************/
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
int User_var_log_event::exec_event(struct st_relay_log_info* rli)
{
@@ -2226,7 +2198,18 @@ int User_var_log_event::exec_event(struct st_relay_log_info* rli)
/****************************************************************************
Slave_log_event methods
****************************************************************************/
+
#ifdef HAVE_REPLICATION
+#ifdef MYSQL_CLIENT
+void Unknown_log_event::print(FILE* file, bool short_form, char* last_db)
+{
+ if (short_form)
+ return;
+ print_header(file);
+ fputc('\n', file);
+ fprintf(file, "# %s", "Unknown event\n");
+}
+#endif
#ifndef MYSQL_CLIENT
void Slave_log_event::pack_info(Protocol *protocol)
@@ -2359,19 +2342,14 @@ int Slave_log_event::exec_event(struct st_relay_log_info* rli)
#endif // !MYSQL_CLIENT
-/*****************************************************************************
- *****************************************************************************
-
- Stop_log_event methods
-
- *****************************************************************************
- ****************************************************************************/
-
-/*****************************************************************************
+/***************************************************************************/
+ Stop_log_event methods
+****************************************************************************/
+/*
Stop_log_event::print()
+*/
- ****************************************************************************/
#ifdef MYSQL_CLIENT
void Stop_log_event::print(FILE* file, bool short_form, char* last_db)
{
@@ -2384,8 +2362,8 @@ void Stop_log_event::print(FILE* file, bool short_form, char* last_db)
}
#endif // MYSQL_CLIENT
-/*****************************************************************************
+/*
Stop_log_event::exec_event()
The master stopped. Clean up all temporary tables + locks that the
@@ -2393,12 +2371,18 @@ void Stop_log_event::print(FILE* file, bool short_form, char* last_db)
TODO
- Remove all active user locks
+*/
- ****************************************************************************/
#ifndef MYSQL_CLIENT
int Stop_log_event::exec_event(struct st_relay_log_info* rli)
{
- // do not clean up immediately after rotate event
+ /*
+ do not clean up immediately after rotate event;
+ QQ: this should be a useless test: the only case when it is false is when
+ shutdown occurred just after FLUSH LOGS. It has nothing to do with Rotate?
+ By the way, immediately after a Rotate the I/O thread does not write
+ the Stop to the relay log, so we won't come here in that case.
+ */
if (rli->group_master_log_pos > BIN_LOG_HEADER_SIZE)
{
close_temporary_tables(thd);
@@ -2415,23 +2399,18 @@ int Stop_log_event::exec_event(struct st_relay_log_info* rli)
flush_relay_log_info(rli);
return 0;
}
-#endif // !MYSQL_CLIENT
+#endif /* !MYSQL_CLIENT */
#endif /* HAVE_REPLICATION */
-/*****************************************************************************
- *****************************************************************************
-
- Create_file_log_event methods
-
- *****************************************************************************
- ****************************************************************************/
-
-/*****************************************************************************
+/***************************************************************************/
+ Create_file_log_event methods
+****************************************************************************/
+/*
Create_file_log_event ctor
+*/
- ****************************************************************************/
#ifndef MYSQL_CLIENT
Create_file_log_event::
Create_file_log_event(THD* thd_arg, sql_exchange* ex,
@@ -2447,11 +2426,11 @@ Create_file_log_event(THD* thd_arg, sql_exchange* ex,
}
#endif // !MYSQL_CLIENT
-/*****************************************************************************
+/*
Create_file_log_event::write_data_body()
+*/
- ****************************************************************************/
int Create_file_log_event::write_data_body(IO_CACHE* file)
{
int res;
@@ -2461,11 +2440,11 @@ int Create_file_log_event::write_data_body(IO_CACHE* file)
my_b_safe_write(file, (byte*) block, block_len));
}
-/*****************************************************************************
+/*
Create_file_log_event::write_data_header()
+*/
- ****************************************************************************/
int Create_file_log_event::write_data_header(IO_CACHE* file)
{
int res;
@@ -2476,11 +2455,11 @@ int Create_file_log_event::write_data_header(IO_CACHE* file)
return my_b_safe_write(file, buf, CREATE_FILE_HEADER_LEN);
}
-/*****************************************************************************
+/*
Create_file_log_event::write_base()
+*/
- ****************************************************************************/
int Create_file_log_event::write_base(IO_CACHE* file)
{
int res;
@@ -2490,11 +2469,11 @@ int Create_file_log_event::write_base(IO_CACHE* file)
return res;
}
-/*****************************************************************************
+/*
Create_file_log_event ctor
+*/
- ****************************************************************************/
Create_file_log_event::Create_file_log_event(const char* buf, int len,
bool old_format)
:Load_log_event(buf,0,old_format),fake_base(0),block(0),inited_from_old(0)
@@ -2521,11 +2500,11 @@ Create_file_log_event::Create_file_log_event(const char* buf, int len,
}
}
-/*****************************************************************************
+/*
Create_file_log_event::print()
+*/
- ****************************************************************************/
#ifdef MYSQL_CLIENT
void Create_file_log_event::print(FILE* file, bool short_form,
char* last_db, bool enable_local)
@@ -2555,11 +2534,11 @@ void Create_file_log_event::print(FILE* file, bool short_form,
}
#endif // MYSQL_CLIENT
-/*****************************************************************************
+/*
Create_file_log_event::pack_info()
+*/
- ****************************************************************************/
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
void Create_file_log_event::pack_info(Protocol *protocol)
{
@@ -2578,11 +2557,11 @@ void Create_file_log_event::pack_info(Protocol *protocol)
}
#endif
-/*****************************************************************************
+/*
Create_file_log_event::exec_event()
+*/
- ****************************************************************************/
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
int Create_file_log_event::exec_event(struct st_relay_log_info* rli)
{
@@ -2643,19 +2622,14 @@ err:
#endif
-/*****************************************************************************
- *****************************************************************************
-
- Append_block_log_event methods
-
- *****************************************************************************
- ****************************************************************************/
-
-/*****************************************************************************
+/***************************************************************************/
+ Append_block_log_event methods
+****************************************************************************/
+/*
Append_block_log_event ctor
+*/
- ****************************************************************************/
#ifndef MYSQL_CLIENT
Append_block_log_event::Append_block_log_event(THD* thd_arg, char* block_arg,
uint block_len_arg,
@@ -2664,13 +2638,13 @@ Append_block_log_event::Append_block_log_event(THD* thd_arg, char* block_arg,
block_len(block_len_arg), file_id(thd_arg->file_id)
{
}
-#endif // !MYSQL_CLIENT
+#endif
-/*****************************************************************************
+/*
Append_block_log_event ctor
+*/
- ****************************************************************************/
Append_block_log_event::Append_block_log_event(const char* buf, int len)
:Log_event(buf, 0),block(0)
{
@@ -2681,11 +2655,11 @@ Append_block_log_event::Append_block_log_event(const char* buf, int len)
block_len = len - APPEND_BLOCK_EVENT_OVERHEAD;
}
-/*****************************************************************************
+/*
Append_block_log_event::write_data()
+*/
- ****************************************************************************/
int Append_block_log_event::write_data(IO_CACHE* file)
{
byte buf[APPEND_BLOCK_HEADER_LEN];
@@ -2694,11 +2668,11 @@ int Append_block_log_event::write_data(IO_CACHE* file)
my_b_safe_write(file, (byte*) block, block_len));
}
-/*****************************************************************************
+/*
Append_block_log_event::print()
+*/
- ****************************************************************************/
#ifdef MYSQL_CLIENT
void Append_block_log_event::print(FILE* file, bool short_form,
char* last_db)
@@ -2712,11 +2686,11 @@ void Append_block_log_event::print(FILE* file, bool short_form,
}
#endif // MYSQL_CLIENT
-/*****************************************************************************
+/*
Append_block_log_event::pack_info()
+*/
- ****************************************************************************/
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
void Append_block_log_event::pack_info(Protocol *protocol)
{
@@ -2729,11 +2703,11 @@ void Append_block_log_event::pack_info(Protocol *protocol)
}
#endif
-/*****************************************************************************
+/*
Append_block_log_event::exec_event()
+*/
- ****************************************************************************/
#if defined( HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
int Append_block_log_event::exec_event(struct st_relay_log_info* rli)
{
@@ -2765,31 +2739,25 @@ err:
#endif
-/*****************************************************************************
- *****************************************************************************
-
- Delete_file_log_event methods
-
- *****************************************************************************
- ****************************************************************************/
-
-/*****************************************************************************
+/***************************************************************************/
+ Delete_file_log_event methods
+****************************************************************************/
+/*
Delete_file_log_event ctor
+*/
- ****************************************************************************/
#ifndef MYSQL_CLIENT
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
-
-/*****************************************************************************
+#endif
+/*
Delete_file_log_event ctor
+*/
- ****************************************************************************/
Delete_file_log_event::Delete_file_log_event(const char* buf, int len)
:Log_event(buf, 0),file_id(0)
{
@@ -2798,11 +2766,11 @@ Delete_file_log_event::Delete_file_log_event(const char* buf, int len)
file_id = uint4korr(buf + LOG_EVENT_HEADER_LEN + AB_FILE_ID_OFFSET);
}
-/*****************************************************************************
+/*
Delete_file_log_event::write_data()
+*/
- ****************************************************************************/
int Delete_file_log_event::write_data(IO_CACHE* file)
{
byte buf[DELETE_FILE_HEADER_LEN];
@@ -2810,11 +2778,11 @@ int Delete_file_log_event::write_data(IO_CACHE* file)
return my_b_safe_write(file, buf, DELETE_FILE_HEADER_LEN);
}
-/*****************************************************************************
+/*
Delete_file_log_event::print()
+*/
- ****************************************************************************/
#ifdef MYSQL_CLIENT
void Delete_file_log_event::print(FILE* file, bool short_form,
char* last_db)
@@ -2827,11 +2795,10 @@ void Delete_file_log_event::print(FILE* file, bool short_form,
}
#endif // MYSQL_CLIENT
-/*****************************************************************************
-
+/*
Delete_file_log_event::pack_info()
+*/
- ****************************************************************************/
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
void Delete_file_log_event::pack_info(Protocol *protocol)
{
@@ -2842,11 +2809,10 @@ void Delete_file_log_event::pack_info(Protocol *protocol)
}
#endif
-/*****************************************************************************
-
+/*
Delete_file_log_event::exec_event()
+*/
- ****************************************************************************/
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
int Delete_file_log_event::exec_event(struct st_relay_log_info* rli)
{
@@ -2863,31 +2829,26 @@ int Delete_file_log_event::exec_event(struct st_relay_log_info* rli)
#endif
-/*****************************************************************************
- *****************************************************************************
-
- Execute_load_log_event methods
-
- *****************************************************************************
- ****************************************************************************/
-
-/*****************************************************************************
+/**************************************************************************/
+ Execute_load_log_event methods
+***************************************************************************/
+/*
Execute_load_log_event ctor
+*/
- ****************************************************************************/
#ifndef MYSQL_CLIENT
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
+#endif
-/*****************************************************************************
+/*
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)
{
@@ -2896,11 +2857,11 @@ Execute_load_log_event::Execute_load_log_event(const char* buf, int len)
file_id = uint4korr(buf + LOG_EVENT_HEADER_LEN + EL_FILE_ID_OFFSET);
}
-/*****************************************************************************
+/*
Execute_load_log_event::write_data()
+*/
- ****************************************************************************/
int Execute_load_log_event::write_data(IO_CACHE* file)
{
byte buf[EXEC_LOAD_HEADER_LEN];
@@ -2908,11 +2869,11 @@ int Execute_load_log_event::write_data(IO_CACHE* file)
return my_b_safe_write(file, buf, EXEC_LOAD_HEADER_LEN);
}
-/*****************************************************************************
+/*
Execute_load_log_event::print()
+*/
- ****************************************************************************/
#ifdef MYSQL_CLIENT
void Execute_load_log_event::print(FILE* file, bool short_form,
char* last_db)
@@ -2924,13 +2885,12 @@ void Execute_load_log_event::print(FILE* file, bool short_form,
fprintf(file, "#Exec_load: file_id=%d\n",
file_id);
}
-#endif // MYSQL_CLIENT
-
-/*****************************************************************************
+#endif
+/*
Execute_load_log_event::pack_info()
+*/
- ****************************************************************************/
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
void Execute_load_log_event::pack_info(Protocol *protocol)
{
@@ -2940,11 +2900,10 @@ void Execute_load_log_event::pack_info(Protocol *protocol)
protocol->store(buf, (int32) length, &my_charset_bin);
}
-/*****************************************************************************
+/*
Execute_load_log_event::exec_event()
-
- ****************************************************************************/
+*/
int Execute_load_log_event::exec_event(struct st_relay_log_info* rli)
{
@@ -3009,22 +2968,17 @@ err:
return error ? error : Log_event::exec_event(rli);
}
-#endif
-
-
-/*****************************************************************************
- *****************************************************************************
+#endif /* defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) */
- sql_ex_info methods
- *****************************************************************************
- ****************************************************************************/
-
-/*****************************************************************************
+/**************************************************************************/
+ sql_ex_info methods
+***************************************************************************/
+/*
sql_ex_info::write_data()
+*/
- ****************************************************************************/
int sql_ex_info::write_data(IO_CACHE* file)
{
if (new_format())
@@ -3050,11 +3004,11 @@ int sql_ex_info::write_data(IO_CACHE* file)
}
}
-/*****************************************************************************
+/*
sql_ex_info::init()
+*/
- ****************************************************************************/
char* sql_ex_info::init(char* buf,char* buf_end,bool use_new_format)
{
cached_new_format = use_new_format;
diff --git a/sql/log_event.h b/sql/log_event.h
index 62b5873fabb..1d2fc741fa8 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -227,10 +227,11 @@ struct sql_ex_info
enum Log_event_type
{
- START_EVENT = 1, QUERY_EVENT =2, STOP_EVENT=3, ROTATE_EVENT = 4,
- INTVAR_EVENT=5, LOAD_EVENT=6, SLAVE_EVENT=7, CREATE_FILE_EVENT=8,
- APPEND_BLOCK_EVENT=9, EXEC_LOAD_EVENT=10, DELETE_FILE_EVENT=11,
- NEW_LOAD_EVENT=12, RAND_EVENT=13, USER_VAR_EVENT=14
+ UNKNOWN_EVENT= 0, START_EVENT= 1, QUERY_EVENT= 2, STOP_EVENT= 3,
+ ROTATE_EVENT= 4, INTVAR_EVENT= 5, LOAD_EVENT=6, SLAVE_EVENT= 7,
+ CREATE_FILE_EVENT= 8, APPEND_BLOCK_EVENT= 9, EXEC_LOAD_EVENT= 10,
+ DELETE_FILE_EVENT= 11, NEW_LOAD_EVENT= 12, RAND_EVENT= 13,
+ USER_VAR_EVENT= 14
};
enum Int_event_type
@@ -524,14 +525,14 @@ extern char server_version[SERVER_VERSION_LENGTH];
class Start_log_event: public Log_event
{
public:
- uint32 created;
+ time_t created;
uint16 binlog_version;
char server_version[ST_SERVER_VER_LEN];
#ifndef MYSQL_CLIENT
Start_log_event() :Log_event(), binlog_version(BINLOG_VERSION)
{
- created = (uint32) when;
+ created = (time_t) when;
memcpy(server_version, ::server_version, ST_SERVER_VER_LEN);
}
#ifdef HAVE_REPLICATION
@@ -887,4 +888,18 @@ public:
int write_data(IO_CACHE* file);
};
+#ifdef MYSQL_CLIENT
+class Unknown_log_event: public Log_event
+{
+public:
+ Unknown_log_event(const char* buf, bool old_format):
+ Log_event(buf, old_format)
+ {}
+ ~Unknown_log_event() {}
+ void print(FILE* file, bool short_form= 0, char* last_db= 0);
+ Log_event_type get_type_code() { return UNKNOWN_EVENT;}
+ bool is_valid() { return 1; }
+};
+#endif
+
#endif /* _log_event_h */
diff --git a/sql/mini_client.cc b/sql/mini_client.cc
index afcee5fbb02..9bfaa95d9d9 100644
--- a/sql/mini_client.cc
+++ b/sql/mini_client.cc
@@ -247,7 +247,7 @@ static void mc_free_old_query(MYSQL *mysql)
static int mc_sock_connect(my_socket s, const struct sockaddr *name,
uint namelen, uint to)
{
-#if defined(__WIN__) || defined(OS2)
+#if defined(__WIN__) || defined(OS2) || defined(__NETWARE__)
return connect(s, (struct sockaddr*) name, namelen);
#else
int flags, res, s_err;
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index ea6e544a1fd..5caa93115ab 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -368,7 +368,12 @@ void mysql_execute_command(THD *thd);
bool do_command(THD *thd);
bool dispatch_command(enum enum_server_command command, THD *thd,
char* packet, uint packet_length);
+#ifndef EMBEDDED_LIBRARY
bool check_stack_overrun(THD *thd,char *dummy);
+#else
+#define check_stack_overrun(A, B) 0
+#endif
+
bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
bool *write_to_binlog);
void table_cache_init(void);
@@ -624,8 +629,8 @@ bool remove_table_from_cache(THD *thd, const char *db, const char *table,
bool return_if_owned_by_thd=0);
bool close_cached_tables(THD *thd, bool wait_for_refresh, TABLE_LIST *tables);
void copy_field_from_tmp_record(Field *field,int offset);
-int fill_record(List<Item> &fields,List<Item> &values);
-int fill_record(Field **field,List<Item> &values);
+int fill_record(List<Item> &fields,List<Item> &values, bool ignore_errors);
+int fill_record(Field **field,List<Item> &values, bool ignore_errors);
OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *wild);
/* sql_calc.cc */
@@ -690,7 +695,6 @@ extern char language[LIBLEN],reg_ext[FN_EXTLEN];
extern char glob_hostname[FN_REFLEN], mysql_home[FN_REFLEN];
extern char pidfile_name[FN_REFLEN], time_zone[30], *opt_init_file;
extern char log_error_file[FN_REFLEN];
-extern char blob_newline;
extern double log_10[32];
extern ulonglong keybuff_size;
extern ulong refresh_version,flush_version, thread_id,query_id,opened_tables;
@@ -736,11 +740,11 @@ extern uint volatile thread_count, thread_running, global_read_lock;
extern my_bool opt_sql_bin_update, opt_safe_user_create, opt_no_mix_types;
extern my_bool opt_safe_show_db, opt_local_infile, lower_case_table_names;
extern my_bool opt_slave_compressed_protocol, use_temp_pool;
+extern my_bool opt_readonly;
extern my_bool opt_enable_named_pipe;
extern my_bool opt_old_passwords, use_old_passwords;
extern char *shared_memory_base_name;
extern bool opt_enable_shared_memory;
-extern char f_fyllchar;
extern MYSQL_LOG mysql_log,mysql_update_log,mysql_slow_log,mysql_bin_log;
extern FILE *bootstrap_file;
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index f73bd6721f0..c75b1981426 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -46,7 +46,7 @@
#define MAIN_THD
#define SIGNAL_THD
-#ifdef PURIFY
+#ifdef HAVE_purify
#define IF_PURIFY(A,B) (A)
#else
#define IF_PURIFY(A,B) (B)
@@ -208,12 +208,12 @@ static char **opt_argv;
#ifdef __WIN__
#undef MYSQL_SERVER_SUFFIX
#ifdef __NT__
-#if defined(HAVE_INNOBASE_DB) || defined(HAVE_BERKELEY_DB)
+#if defined(HAVE_BERKELEY_DB)
#define MYSQL_SERVER_SUFFIX "-max-nt"
#else
#define MYSQL_SERVER_SUFFIX "-nt"
#endif /* ...DB */
-#elif defined(HAVE_INNOBASE_DB) || defined(HAVE_BERKELEY_DB)
+#elif defined(HAVE_BERKELEY_DB)
#define MYSQL_SERVER_SUFFIX "-max"
#else
#define MYSQL_SERVER_SUFFIX ""
@@ -300,7 +300,7 @@ my_bool opt_enable_named_pipe= 0;
my_bool opt_local_infile, opt_external_locking, opt_slave_compressed_protocol;
uint delay_key_write_options= (uint) DELAY_KEY_WRITE_ON;
-static bool opt_do_pstack = 0;
+static my_bool opt_do_pstack = 0;
static ulong opt_specialflag=SPECIAL_ENGLISH;
static ulong opt_myisam_block_size;
@@ -392,7 +392,7 @@ const char *localhost=LOCAL_HOST;
const char *delayed_user="DELAYED";
uint master_port = MYSQL_PORT, master_connect_retry = 60;
uint report_port = MYSQL_PORT;
-bool master_ssl = 0;
+my_bool master_ssl = 0;
ulong master_retry_count=0;
ulong bytes_sent = 0L, bytes_received = 0L;
@@ -421,8 +421,7 @@ ulong expire_logs_days = 0;
char mysql_real_data_home[FN_REFLEN],
language[LIBLEN],reg_ext[FN_EXTLEN],
mysql_charsets_dir[FN_REFLEN], *charsets_list,
- blob_newline,f_fyllchar,max_sort_char,*mysqld_user,*mysqld_chroot,
- *opt_init_file;
+ max_sort_char,*mysqld_user,*mysqld_chroot, *opt_init_file;
char *language_ptr= language;
char mysql_data_home_buff[2], *mysql_data_home=mysql_real_data_home;
#ifndef EMBEDDED_LIBRARY
@@ -823,9 +822,9 @@ static void __cdecl kill_server(int sig_ptr)
unireg_end();
#ifdef __NETWARE__
pthread_join(select_thread, NULL); // wait for main thread
-#else
- pthread_exit(0); /* purecov: deadcode */
#endif /* __NETWARE__ */
+
+ pthread_exit(0); /* purecov: deadcode */
#endif /* EMBEDDED_LIBRARY */
RETURN_FROM_KILL_SERVER;
@@ -883,13 +882,11 @@ void unireg_end(void)
{
clean_up(1);
my_thread_end();
-#ifndef __NETWARE__
-#ifdef SIGNALS_DONT_BREAK_READ
+#if defined(SIGNALS_DONT_BREAK_READ) && !defined(__NETWARE__)
exit(0);
#else
pthread_exit(0); // Exit is in main thread
#endif
-#endif /* __NETWARE__ */
}
@@ -954,6 +951,8 @@ void clean_up(bool print_message)
end_slave_list();
#endif
#ifdef HAVE_OPENSSL
+ if (ssl_acceptor_fd)
+ my_free((gptr) ssl_acceptor_fd, MYF(MY_ALLOW_ZERO_PTR));
free_des_key_file();
#endif /* HAVE_OPENSSL */
#ifdef USE_REGEX
@@ -1647,6 +1646,7 @@ static void init_signals(void)
sa.sa_handler=handle_segfault;
#endif
sigaction(SIGSEGV, &sa, NULL);
+ sigaction(SIGABRT, &sa, NULL);
#ifdef SIGBUS
sigaction(SIGBUS, &sa, NULL);
#endif
@@ -1732,9 +1732,10 @@ extern "C" void *signal_hand(void *arg __attribute__((unused)))
/*
Setup alarm handler
- The two extra handlers are for slave threads
+ This should actually be '+ max_number_of_slaves' instead of +10,
+ but the +10 should be quite safe.
*/
- init_thr_alarm(max_connections+max_insert_delayed_threads+2);
+ init_thr_alarm(max_connections+max_insert_delayed_threads+10);
#if SIGINT != THR_KILL_SIGNAL
(void) sigemptyset(&set); // Setup up SIGINT for debug
(void) sigaddset(&set,SIGINT); // For debugging
@@ -3468,10 +3469,11 @@ enum options
OPT_QUERY_CACHE_TYPE, OPT_RECORD_BUFFER,
OPT_RECORD_RND_BUFFER, OPT_RELAY_LOG_SPACE_LIMIT, OPT_RELAY_LOG_PURGE,
OPT_SLAVE_NET_TIMEOUT, OPT_SLAVE_COMPRESSED_PROTOCOL, OPT_SLOW_LAUNCH_TIME,
+ OPT_READONLY,
OPT_SORT_BUFFER, OPT_TABLE_CACHE,
OPT_THREAD_CONCURRENCY, OPT_THREAD_CACHE_SIZE,
OPT_TMP_TABLE_SIZE, OPT_THREAD_STACK,
- OPT_WAIT_TIMEOUT,
+ OPT_WAIT_TIMEOUT, OPT_MYISAM_REPAIR_THREADS,
OPT_INNODB_MIRRORED_LOG_GROUPS,
OPT_INNODB_LOG_FILES_IN_GROUP,
OPT_INNODB_LOG_FILE_SIZE,
@@ -3483,6 +3485,7 @@ enum options
OPT_INNODB_LOCK_WAIT_TIMEOUT,
OPT_INNODB_THREAD_CONCURRENCY,
OPT_INNODB_FORCE_RECOVERY,
+ OPT_INNODB_MAX_DIRTY_PAGES_PCT,
OPT_BDB_CACHE_SIZE,
OPT_BDB_LOG_BUFFER_SIZE,
OPT_BDB_MAX_LOCK,
@@ -3649,6 +3652,10 @@ Disable with --skip-bdb (will save memory)",
{"innodb_fast_shutdown", OPT_INNODB_FAST_SHUTDOWN,
"Speeds up server shutdown process", (gptr*) &innobase_fast_shutdown,
(gptr*) &innobase_fast_shutdown, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
+ {"innodb_max_dirty_pages_pct", OPT_INNODB_MAX_DIRTY_PAGES_PCT,
+ "Percentage of dirty pages allowed in bufferpool", (gptr*) &srv_max_buf_pool_modified_pct,
+ (gptr*) &srv_max_buf_pool_modified_pct, 0, GET_ULONG, REQUIRED_ARG, 90, 0, 100, 0, 0, 0},
+
#endif /* End HAVE_INNOBASE_DB */
{"help", '?', "Display this help and exit", 0, 0, 0, GET_NO_ARG, NO_ARG, 0,
0, 0, 0, 0, 0},
@@ -3667,7 +3674,7 @@ Disable with --skip-bdb (will save memory)",
(gptr*) &opt_local_infile, 0, GET_BOOL, OPT_ARG,
1, 0, 0, 0, 0, 0},
{"log-bin", OPT_BIN_LOG,
- "Log queries in new binary format (for replication)",
+ "Log update queries in binary format",
(gptr*) &opt_bin_logname, (gptr*) &opt_bin_logname, 0, GET_STR_ALLOC,
OPT_ARG, 0, 0, 0, 0, 0, 0},
{"log-bin-index", OPT_BIN_LOG_INDEX,
@@ -3721,27 +3728,32 @@ Disable with --skip-bdb (will save memory)",
(gptr*) &master_retry_count, (gptr*) &master_retry_count, 0, GET_ULONG,
REQUIRED_ARG, 3600*24, 0, 0, 0, 0, 0},
{"master-info-file", OPT_MASTER_INFO_FILE,
- "The location of the file that remembers where we left off on the master during the replication process. The default is `master.info' in the data directory. You should not need to change this.",
+ "The location and name of the file that remembers the master and where the I/O replication \
+thread is in the master's binlogs.",
(gptr*) &master_info_file, (gptr*) &master_info_file, 0, GET_STR,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"master-ssl", OPT_MASTER_SSL,
- "Turn SSL on for replication. Be warned that is this is a relatively new feature.",
+ "Planned to enable the slave to connect to the master using SSL. Does nothing yet.",
(gptr*) &master_ssl, (gptr*) &master_ssl, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
0, 0},
{"master-ssl-key", OPT_MASTER_SSL_KEY,
- "Master SSL keyfile name. Only applies if you have enabled master-ssl.",
+ "Master SSL keyfile name. Only applies if you have enabled master-ssl. Does \
+nothing yet.",
(gptr*) &master_ssl_key, (gptr*) &master_ssl_key, 0, GET_STR, OPT_ARG,
0, 0, 0, 0, 0, 0},
{"master-ssl-cert", OPT_MASTER_SSL_CERT,
- "Master SSL certificate file name. Only applies if you have enabled master-ssl.",
+ "Master SSL certificate file name. Only applies if you have enabled \
+master-ssl. Does nothing yet.",
(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.",
+ "Master SSL CA path. Only applies if you have enabled master-ssl. \
+Does nothing yet.",
(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.",
+ "Master SSL cipher. Only applies if you have enabled master-ssl. \
+Does nothing yet.",
(gptr*) &master_ssl_cipher, (gptr*) &master_ssl_capath, 0, GET_STR, OPT_ARG,
0, 0, 0, 0, 0, 0},
{"myisam-recover", OPT_MYISAM_RECOVER,
@@ -3842,10 +3854,13 @@ Disable with --skip-bdb (will save memory)",
{"rpl-recovery-rank", OPT_RPL_RECOVERY_RANK, "Undocumented",
(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",
+ {"relay-log", OPT_RELAY_LOG,
+ "The location and name to use for relay logs",
(gptr*) &opt_relay_logname, (gptr*) &opt_relay_logname, 0,
GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"relay-log-index", OPT_RELAY_LOG_INDEX, "Undocumented",
+ {"relay-log-index", OPT_RELAY_LOG_INDEX,
+ "The location and name to use for the file that keeps a list of the last \
+relay logs",
(gptr*) &opt_relaylog_index_name, (gptr*) &opt_relaylog_index_name, 0,
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"safe-mode", OPT_SAFE, "Skip some optimize stages (for testing).",
@@ -3915,16 +3930,20 @@ Disable with --skip-isam",
{"skip-stack-trace", OPT_SKIP_STACK_TRACE,
"Don't print a stack trace on failure", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0,
0, 0, 0, 0},
- {"skip-symlink", OPT_SKIP_SYMLINKS, "Don't allow symlinking of tables",
+ {"skip-symlink", OPT_SKIP_SYMLINKS, "Don't allow symlinking of tables. Depricated option. Use --skip-symbolic-links instead",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"skip-thread-priority", OPT_SKIP_PRIOR,
"Don't give threads different priorities.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0,
0, 0, 0, 0, 0},
- {"relay-log-info-file", OPT_RELAY_LOG_INFO_FILE, "Undocumented",
+ {"relay-log-info-file", OPT_RELAY_LOG_INFO_FILE,
+ "The location and name of the file that remembers where the SQL replication \
+thread is in the relay logs",
(gptr*) &relay_log_info_file, (gptr*) &relay_log_info_file, 0, GET_STR,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
#ifdef HAVE_REPLICATION
- {"slave-load-tmpdir", OPT_SLAVE_LOAD_TMPDIR, "Undocumented",
+ {"slave-load-tmpdir", OPT_SLAVE_LOAD_TMPDIR,
+ "The location where the slave should put its temporary files when \
+replicating a LOAD DATA INFILE command",
(gptr*) &slave_load_tmpdir, (gptr*) &slave_load_tmpdir, 0, GET_STR_ALLOC,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"slave-skip-errors", OPT_SLAVE_SKIP_ERRORS,
@@ -3965,11 +3984,12 @@ Disable with --skip-isam",
{"external-locking", OPT_USE_LOCKING, "Use system (external) locking. With this option enabled you can run myisamchk to test (not repair) tables while the MySQL server is running",
(gptr*) &opt_external_locking, (gptr*) &opt_external_locking,
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
-#ifdef USE_SYMDIR
- {"use-symbolic-links", 's', "Enable symbolic link support",
+ {"use-symbolic-links", 's', "Enable symbolic link support. Depricated option; Use --symbolic-links instead",
+ (gptr*) &my_use_symdir, (gptr*) &my_use_symdir, 0, GET_BOOL, NO_ARG,
+ IF_PURIFY(0,1), 0, 0, 0, 0, 0},
+ {"--symbolic-links", 's', "Enable symbolic link support",
(gptr*) &my_use_symdir, (gptr*) &my_use_symdir, 0, GET_BOOL, NO_ARG,
IF_PURIFY(0,1), 0, 0, 0, 0, 0},
-#endif
{"user", 'u', "Run mysqld daemon as user", 0, 0, 0, GET_STR, REQUIRED_ARG,
0, 0, 0, 0, 0, 0},
{"version", 'V', "Output version information and exit", 0, 0, 0, GET_NO_ARG,
@@ -4147,7 +4167,7 @@ Disable with --skip-isam",
(gptr*) &max_connect_errors, (gptr*) &max_connect_errors, 0, GET_ULONG,
REQUIRED_ARG, MAX_CONNECT_ERRORS, 1, ~0L, 0, 1, 0},
{"max_delayed_threads", OPT_MAX_DELAYED_THREADS,
- "Don't start more than this number of threads to handle INSERT DELAYED statements. This option does not yet have effect (on TODO), unless it is set to zero, which means INSERT DELAYED is not used.",
+ "Don't start more than this number of threads to handle INSERT DELAYED statements. If set to zero, which means INSERT DELAYED is not used.",
(gptr*) &max_insert_delayed_threads, (gptr*) &max_insert_delayed_threads,
0, GET_ULONG, REQUIRED_ARG, 20, 0, 16384, 0, 1, 0},
{"max_error_count", OPT_MAX_ERROR_COUNT,
@@ -4209,12 +4229,18 @@ Disable with --skip-isam",
(gptr*) &global_system_variables.myisam_max_extra_sort_file_size,
(gptr*) &max_system_variables.myisam_max_extra_sort_file_size,
0, GET_ULL, REQUIRED_ARG, (ulonglong) MI_MAX_TEMP_LENGTH,
- 0, ~0L, 0, 1, 0},
+ 0, (ulonglong) MAX_FILE_SIZE, 0, 1, 0},
{"myisam_max_sort_file_size", OPT_MYISAM_MAX_SORT_FILE_SIZE,
"Don't use the fast sort index method to created index if the temporary file would get bigger than this!",
(gptr*) &global_system_variables.myisam_max_sort_file_size,
(gptr*) &max_system_variables.myisam_max_sort_file_size, 0,
- GET_ULL, REQUIRED_ARG, (longlong) LONG_MAX, 0, ~0L, 0, 1024*1024, 0},
+ GET_ULL, REQUIRED_ARG, (longlong) LONG_MAX, 0, (ulonglong) MAX_FILE_SIZE,
+ 0, 1024*1024, 0},
+ {"myisam_repair_threads", OPT_MYISAM_REPAIR_THREADS,
+ "Number of threads to use when repairing MyISAM tables. The value of 1 disables parallel repair.",
+ (gptr*) &global_system_variables.myisam_repair_threads,
+ (gptr*) &max_system_variables.myisam_repair_threads, 0,
+ GET_ULONG, REQUIRED_ARG, 1, 1, ~0L, 0, 1, 0},
{"myisam_sort_buffer_size", OPT_MYISAM_SORT_BUFFER_SIZE,
"The buffer that is allocated when sorting the index when doing a REPAIR or when creating indexes with CREATE INDEX or ALTER TABLE.",
(gptr*) &global_system_variables.myisam_sort_buff_size,
@@ -4289,7 +4315,7 @@ Disable with --skip-isam",
(gptr*) &relay_log_purge, 0, GET_BOOL, NO_ARG,
1, 0, 1, 0, 1, 0},
{"relay_log_space_limit", OPT_RELAY_LOG_SPACE_LIMIT,
- "Max space to use for all relay logs",
+ "Maximum space to use for all relay logs",
(gptr*) &relay_log_space_limit,
(gptr*) &relay_log_space_limit, 0, GET_ULL, REQUIRED_ARG, 0L, 0L,
(longlong) ULONG_MAX, 0, 1, 0},
@@ -4303,6 +4329,11 @@ Disable with --skip-isam",
(gptr*) &slave_net_timeout, (gptr*) &slave_net_timeout, 0,
GET_ULONG, REQUIRED_ARG, SLAVE_NET_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0},
#endif /* HAVE_REPLICATION */
+ {"read-only", OPT_READONLY,
+ "Make all tables readonly, with the expections for replications (slave) threads and users with the SUPER privilege",
+ (gptr*) &opt_readonly,
+ (gptr*) &opt_readonly,
+ 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 1, 0},
{"slow_launch_time", OPT_SLOW_LAUNCH_TIME,
"If creating the thread takes longer than this value (in seconds), the Slow_launch_threads counter will be incremented.",
(gptr*) &slow_launch_time, (gptr*) &slow_launch_time, 0, GET_ULONG,
@@ -4844,9 +4875,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
delay_key_write_options= (uint) DELAY_KEY_WRITE_NONE;
myisam_concurrent_insert=0;
myisam_recover_options= HA_RECOVER_NONE;
- my_disable_symlinks=1;
my_use_symdir=0;
- have_symlink=SHOW_OPTION_DISABLED;
ha_open_options&= ~(HA_OPEN_ABORT_IF_CRASHED | HA_OPEN_DELAY_KEY_WRITE);
#ifdef HAVE_QUERY_CACHE
query_cache_size=0;
@@ -4893,9 +4922,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
test_flags|=TEST_NO_STACKTRACE;
break;
case (int) OPT_SKIP_SYMLINKS:
- my_disable_symlinks=1;
my_use_symdir=0;
- have_symlink=SHOW_OPTION_DISABLED;
break;
case (int) OPT_BIND_ADDRESS:
if (argument && my_isdigit(mysqld_charset, argument[0]))
@@ -5167,11 +5194,9 @@ static void get_options(int argc,char **argv)
my_disable_locking= myisam_single_user= test(opt_external_locking == 0);
my_default_record_cache_size=global_system_variables.read_buff_size;
myisam_max_temp_length=
- (my_off_t) min(global_system_variables.myisam_max_sort_file_size,
- (ulonglong) MAX_FILE_SIZE);
+ (my_off_t) global_system_variables.myisam_max_sort_file_size;
myisam_max_extra_temp_length=
- (my_off_t) min(global_system_variables.myisam_max_extra_sort_file_size,
- (ulonglong) MAX_FILE_SIZE);
+ (my_off_t) global_system_variables.myisam_max_extra_sort_file_size;
/* Set global variables based on startup options */
myisam_block_size=(uint) 1 << my_bit_log2(opt_myisam_block_size);
diff --git a/sql/net_serv.cc b/sql/net_serv.cc
index 550fb772fce..8271d971782 100644
--- a/sql/net_serv.cc
+++ b/sql/net_serv.cc
@@ -48,13 +48,6 @@
can't normally do this the client should have a bigger max_allowed_packet.
*/
-#ifdef MYSQL_SERVER
-#define USE_QUERY_CACHE
-extern uint test_flags;
-extern void query_cache_insert(NET *net, const char *packet, ulong length);
-#else
-#endif
-
#if defined(__WIN__) || !defined(MYSQL_SERVER)
/* The following is because alarms doesn't work on windows. */
#define NO_ALARM
@@ -63,16 +56,23 @@ extern void query_cache_insert(NET *net, const char *packet, ulong length);
#ifndef NO_ALARM
#include "my_pthread.h"
void sql_print_error(const char *format,...);
-extern ulong bytes_sent, bytes_received;
-extern pthread_mutex_t LOCK_bytes_sent , LOCK_bytes_received;
#else
-#undef statistic_add
-#define statistic_add(A,B,C)
#define DONT_USE_THR_ALARM
#endif /* NO_ALARM */
#include "thr_alarm.h"
+#ifdef MYSQL_SERVER
+#define USE_QUERY_CACHE
+extern uint test_flags;
+extern void query_cache_insert(NET *net, const char *packet, ulong length);
+extern ulong bytes_sent, bytes_received;
+extern pthread_mutex_t LOCK_bytes_sent , LOCK_bytes_received;
+#else
+#undef statistic_add
+#define statistic_add(A,B,C)
+#endif
+
#define TEST_BLOCKING 8
#define MAX_PACKET_LENGTH (256L*256L*256L-1)
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 7526772cd09..d40f2e22ea2 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -283,7 +283,7 @@ typedef struct st_qsel_param {
KEY_PART *key_parts,*key_parts_end,*key[MAX_KEY];
MEM_ROOT *mem_root;
table_map prev_tables,read_tables,current_table;
- uint baseflag,keys,max_key_part;
+ uint baseflag, keys, max_key_part, range_count;
uint real_keynr[MAX_KEY];
char min_key[MAX_KEY_LENGTH+MAX_FIELD_WIDTH],
max_key[MAX_KEY_LENGTH+MAX_FIELD_WIDTH];
@@ -709,8 +709,10 @@ int SQL_SELECT::test_quick_select(key_map keys_to_use, table_map prev_tables,
(double) keys_per_block);
}
else
- found_read_time= head->file->read_time(found_records)+
- (double) found_records / TIME_FOR_COMPARE;
+ found_read_time= (head->file->read_time(keynr,
+ param.range_count,
+ found_records)+
+ (double) found_records / TIME_FOR_COMPARE);
if (read_time > found_read_time)
{
read_time=found_read_time;
@@ -2074,11 +2076,12 @@ check_quick_select(PARAM *param,uint idx,SEL_ARG *tree)
if (!tree)
DBUG_RETURN(HA_POS_ERROR); // Can't use it
+ param->max_key_part=0;
+ param->range_count=0;
if (tree->type == SEL_ARG::IMPOSSIBLE)
DBUG_RETURN(0L); // Impossible select. return
if (tree->type != SEL_ARG::KEY_RANGE || tree->part != 0)
DBUG_RETURN(HA_POS_ERROR); // Don't use tree
- param->max_key_part=0;
records=check_quick_keys(param,idx,tree,param->min_key,0,param->max_key,0);
if (records != HA_POS_ERROR)
{
@@ -2146,6 +2149,7 @@ check_quick_keys(PARAM *param,uint idx,SEL_ARG *key_tree,
}
keynr=param->real_keynr[idx];
+ param->range_count++;
if (!tmp_min_flag && ! tmp_max_flag &&
(uint) key_tree->part+1 == param->table->key_info[keynr].key_parts &&
(param->table->key_info[keynr].flags & HA_NOSAME) &&
diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc
index 1e116518da0..b96c6383bbb 100644
--- a/sql/opt_sum.cc
+++ b/sql/opt_sum.cc
@@ -69,8 +69,10 @@ static int maxmin_in_range(bool max_fl, Field* field, COND *cond);
RETURN VALUES
0 No errors
- 1 if all items was resolved
- -1 on impossible conditions
+ 1 if all items were resolved
+ -1 on impossible conditions
+ OR an error number from my_base.h HA_ERR_... if a deadlock or a lock
+ wait timeout happens, for example
*/
int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
@@ -82,6 +84,7 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
table_map where_tables= 0;
Item *item;
COND *org_conds= conds;
+ int error;
if (conds)
where_tables= conds->used_tables();
@@ -131,7 +134,7 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
if (outer_tables || (table->table->file->table_flags() &
HA_NOT_EXACT_COUNT))
{
- const_result= 0; // Can't optimize left join
+ const_result= 0; // Can't optimize left join
break;
}
tables->table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
@@ -164,6 +167,11 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
Item_field *item_field= ((Item_field*) expr);
TABLE *table= item_field->field->table;
+ if ((table->file->table_flags() & HA_NOT_READ_AFTER_KEY))
+ {
+ const_result=0;
+ break;
+ }
/*
Look for a partial key that can be used for optimization.
If we succeed, ref.key_length will contain the length of
@@ -179,18 +187,21 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
const_result= 0;
break;
}
- bool error= table->file->index_init((uint) ref.key);
+ error= table->file->index_init((uint) ref.key);
if (!ref.key_length)
- error= table->file->index_first(table->record[0]) != 0;
+ error= table->file->index_first(table->record[0]);
else
- error= table->file->index_read(table->record[0],key_buff,
- ref.key_length,
- range_fl & NEAR_MIN ?
- HA_READ_AFTER_KEY :
- HA_READ_KEY_OR_NEXT) ||
- reckey_in_range(0, &ref, item_field->field,
- conds, range_fl, prefix_len);
+ {
+ error= table->file->index_read(table->record[0],key_buff,
+ ref.key_length,
+ range_fl & NEAR_MIN ?
+ HA_READ_AFTER_KEY :
+ HA_READ_KEY_OR_NEXT);
+ if (!error && reckey_in_range(0, &ref, item_field->field,
+ conds, range_fl, prefix_len))
+ error= HA_ERR_KEY_NOT_FOUND;
+ }
if (table->key_read)
{
table->key_read= 0;
@@ -198,10 +209,16 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
}
table->file->index_end();
if (error)
- return -1; // No rows matching where
+ {
+ if (error == HA_ERR_KEY_NOT_FOUND || error == HA_ERR_END_OF_FILE)
+ return -1; // No rows matching WHERE
+ /* HA_ERR_LOCK_DEADLOCK or some other error */
+ table->file->print_error(error, MYF(0));
+ return(error);
+ }
removed_tables|= table->map;
}
- else if (!expr->const_item()) // This is VERY seldom false
+ else if (!expr->const_item()) // This is VERY seldom false
{
const_result= 0;
break;
@@ -249,18 +266,20 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
const_result= 0;
break;
}
- bool error= table->file->index_init((uint) ref.key);
+ error= table->file->index_init((uint) ref.key);
if (!ref.key_length)
- error=table->file->index_last(table->record[0]) != 0;
+ error= table->file->index_last(table->record[0]);
else
- error= table->file->index_read(table->record[0], key_buff,
- ref.key_length,
- range_fl & NEAR_MAX ?
- HA_READ_BEFORE_KEY :
- HA_READ_PREFIX_LAST_OR_PREV) ||
- reckey_in_range(1, &ref, item_field->field,
- conds, range_fl, prefix_len);
+ {
+ error= table->file->index_read(table->record[0], key_buff,
+ ref.key_length,
+ range_fl & NEAR_MAX ?
+ HA_READ_BEFORE_KEY :
+ HA_READ_PREFIX_LAST_OR_PREV);
+ if (!error && reckey_in_range(1, &ref, item_field->field,
+ conds, range_fl, prefix_len))
+ error= HA_ERR_KEY_NOT_FOUND;
if (table->key_read)
{
table->key_read=0;
@@ -268,10 +287,16 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
}
table->file->index_end();
if (error)
- return -1; // Impossible query
+ {
+ if (error == HA_ERR_KEY_NOT_FOUND || error == HA_ERR_END_OF_FILE)
+ return -1; // No rows matching WHERE
+ /* HA_ERR_LOCK_DEADLOCK or some other error */
+ table->file->print_error(error, MYF(0));
+ return(error);
+ }
removed_tables|= table->map;
}
- else if (!expr->const_item()) // This is VERY seldom false
+ else if (!expr->const_item()) // This is VERY seldom false
{
const_result= 0;
break;
@@ -597,6 +622,10 @@ static bool matching_cond(bool max_fl, TABLE_REF *ref, KEY *keyinfo,
(if we have a condition field = const, prefix_len contains the length
of the whole search key)
+ NOTE
+ This function may set table->key_read to 1, which must be reset after
+ index is used! (This can only happen when function returns 1)
+
RETURN
0 Index can not be used to optimize MIN(field)/MAX(field)
1 Can use key to optimize MIN()/MAX()
diff --git a/sql/records.cc b/sql/records.cc
index 9d8627bc1fc..783ca663dfe 100644
--- a/sql/records.cc
+++ b/sql/records.cc
@@ -16,7 +16,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-/* Functions to read, write and lock records */
+/* Functions for easy reading of records, possible through a cache */
#include "mysql_priv.h"
diff --git a/sql/set_var.cc b/sql/set_var.cc
index e4adbb0a318..0071f50f7a0 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -87,6 +87,8 @@ static void fix_max_join_size(THD *thd, enum_var_type type);
static void fix_query_cache_size(THD *thd, enum_var_type type);
static void fix_query_cache_min_res_unit(THD *thd, enum_var_type type);
static void fix_key_buffer_size(THD *thd, enum_var_type type);
+static void fix_myisam_max_extra_sort_file_size(THD *thd, enum_var_type type);
+static void fix_myisam_max_sort_file_size(THD *thd, enum_var_type type);
static byte *get_error_count(THD *thd);
static byte *get_warning_count(THD *thd);
@@ -184,8 +186,9 @@ sys_var_thd_ulong sys_max_tmp_tables("max_tmp_tables",
&SV::max_tmp_tables);
sys_var_long_ptr sys_max_write_lock_count("max_write_lock_count",
&max_write_lock_count);
-sys_var_thd_ulonglong sys_myisam_max_extra_sort_file_size("myisam_max_extra_sort_file_size", &SV::myisam_max_extra_sort_file_size);
-sys_var_thd_ulonglong sys_myisam_max_sort_file_size("myisam_max_sort_file_size", &SV::myisam_max_sort_file_size);
+sys_var_thd_ulonglong sys_myisam_max_extra_sort_file_size("myisam_max_extra_sort_file_size", &SV::myisam_max_extra_sort_file_size, fix_myisam_max_extra_sort_file_size, 1);
+sys_var_thd_ulonglong sys_myisam_max_sort_file_size("myisam_max_sort_file_size", &SV::myisam_max_sort_file_size, fix_myisam_max_sort_file_size, 1);
+sys_var_thd_ulong sys_myisam_repair_threads("myisam_repair_threads", &SV::myisam_repair_threads);
sys_var_thd_ulong sys_myisam_sort_buffer_size("myisam_sort_buffer_size", &SV::myisam_sort_buff_size);
sys_var_thd_ulong sys_net_buffer_length("net_buffer_length",
&SV::net_buffer_length);
@@ -229,6 +232,8 @@ sys_var_bool_ptr sys_slave_compressed_protocol("slave_compressed_protocol",
sys_var_long_ptr sys_slave_net_timeout("slave_net_timeout",
&slave_net_timeout);
#endif
+sys_var_bool_ptr sys_readonly("read_only",
+ &opt_readonly);
sys_var_long_ptr sys_slow_launch_time("slow_launch_time",
&slow_launch_time);
sys_var_thd_ulong sys_sort_buffer("sort_buffer_size",
@@ -249,6 +254,11 @@ sys_var_thd_ulong sys_tmp_table_size("tmp_table_size",
&SV::tmp_table_size);
sys_var_thd_ulong sys_net_wait_timeout("wait_timeout",
&SV::net_wait_timeout);
+
+#ifdef HAVE_INNOBASE_DB
+sys_var_long_ptr sys_innodb_max_dirty_pages_pct("innodb_max_dirty_pages_pct",
+ &srv_max_buf_pool_modified_pct);
+#endif
/*
Variables that are bits in THD
*/
@@ -267,7 +277,7 @@ static sys_var_thd_bit sys_sql_big_tables("sql_big_tables",
#endif
static sys_var_thd_bit sys_big_selects("sql_big_selects",
set_option_bit,
- OPTION_BIG_TABLES);
+ OPTION_BIG_SELECTS);
static sys_var_thd_bit sys_log_off("sql_log_off",
set_option_bit,
OPTION_LOG_OFF);
@@ -395,6 +405,7 @@ sys_var *sys_variables[]=
&sys_max_write_lock_count,
&sys_myisam_max_extra_sort_file_size,
&sys_myisam_max_sort_file_size,
+ &sys_myisam_repair_threads,
&sys_myisam_sort_buffer_size,
&sys_net_buffer_length,
&sys_net_read_timeout,
@@ -426,6 +437,7 @@ sys_var *sys_variables[]=
&sys_slave_net_timeout,
&sys_slave_skip_counter,
#endif
+ &sys_readonly,
&sys_slow_launch_time,
&sys_sort_buffer,
&sys_sql_big_tables,
@@ -439,6 +451,9 @@ sys_var *sys_variables[]=
&sys_timestamp,
&sys_tmp_table_size,
&sys_tx_isolation,
+#ifdef HAVE_INNOBASE_DB
+ &sys_innodb_max_dirty_pages_pct,
+#endif
&sys_unique_checks,
&sys_warning_count
};
@@ -514,6 +529,7 @@ struct show_var_st init_vars[]= {
{"innodb_log_files_in_group", (char*) &innobase_log_files_in_group, SHOW_LONG},
{"innodb_log_group_home_dir", (char*) &innobase_log_group_home_dir, SHOW_CHAR_PTR},
{"innodb_mirrored_log_groups", (char*) &innobase_mirrored_log_groups, SHOW_LONG},
+ {sys_innodb_max_dirty_pages_pct.name, (char*) &sys_innodb_max_dirty_pages_pct, SHOW_SYS},
#endif
{sys_interactive_timeout.name,(char*) &sys_interactive_timeout, SHOW_SYS},
{sys_join_buffer_size.name, (char*) &sys_join_buffer_size, SHOW_SYS},
@@ -550,13 +566,14 @@ struct show_var_st init_vars[]= {
{sys_max_prep_stmt_count.name,(char*) &sys_max_prep_stmt_count, SHOW_SYS},
{sys_max_sort_length.name, (char*) &sys_max_sort_length, SHOW_SYS},
{sys_max_user_connections.name,(char*) &sys_max_user_connections, SHOW_SYS},
- {sys_max_tmp_tables.name, (char*) &sys_max_tmp_tables, SHOW_SYS},
+ {sys_max_tmp_tables.name, (char*) &sys_max_tmp_tables, SHOW_SYS},
{sys_max_write_lock_count.name, (char*) &sys_max_write_lock_count,SHOW_SYS},
{sys_myisam_max_extra_sort_file_size.name,
(char*) &sys_myisam_max_extra_sort_file_size,
SHOW_SYS},
- {sys_myisam_max_sort_file_size.name,
- (char*) &sys_myisam_max_sort_file_size,
+ {sys_myisam_max_sort_file_size.name, (char*) &sys_myisam_max_sort_file_size,
+ SHOW_SYS},
+ {sys_myisam_repair_threads.name, (char*) &sys_myisam_repair_threads,
SHOW_SYS},
{"myisam_recover_options", (char*) &myisam_recover_options_str, SHOW_CHAR_PTR},
{sys_myisam_sort_buffer_size.name, (char*) &sys_myisam_sort_buffer_size, SHOW_SYS},
@@ -595,6 +612,7 @@ struct show_var_st init_vars[]= {
#ifdef HAVE_REPLICATION
{sys_slave_net_timeout.name,(char*) &sys_slave_net_timeout, SHOW_SYS},
#endif
+ {sys_readonly.name, (char*) &sys_readonly, 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},
@@ -661,6 +679,21 @@ static void fix_low_priority_updates(THD *thd, enum_var_type type)
}
+static void
+fix_myisam_max_extra_sort_file_size(THD *thd, enum_var_type type)
+{
+ myisam_max_extra_temp_length=
+ (my_off_t) global_system_variables.myisam_max_extra_sort_file_size;
+}
+
+
+static void
+fix_myisam_max_sort_file_size(THD *thd, enum_var_type type)
+{
+ myisam_max_temp_length=
+ (my_off_t) global_system_variables.myisam_max_sort_file_size;
+}
+
/*
Set the OPTION_BIG_SELECTS flag if max_join_size == HA_POS_ERROR
*/
@@ -911,15 +944,22 @@ byte *sys_var_thd_ha_rows::value_ptr(THD *thd, enum_var_type type)
bool sys_var_thd_ulonglong::update(THD *thd, set_var *var)
{
+ ulonglong tmp= var->value->val_int();
+
+ if ((ulonglong) tmp > max_system_variables.*offset)
+ tmp= max_system_variables.*offset;
+
+ if (option_limits)
+ tmp= (ulong) getopt_ull_limit_value(tmp, option_limits);
if (var->type == OPT_GLOBAL)
{
/* Lock is needed to make things safe on 32 bit systems */
pthread_mutex_lock(&LOCK_global_system_variables);
- global_system_variables.*offset= var->value->val_int();
+ global_system_variables.*offset= (ulonglong) tmp;
pthread_mutex_unlock(&LOCK_global_system_variables);
}
else
- thd->variables.*offset= var->value->val_int();
+ thd->variables.*offset= (ulonglong) tmp;
return 0;
}
diff --git a/sql/set_var.h b/sql/set_var.h
index fbd20228d24..667cb824fca 100644
--- a/sql/set_var.h
+++ b/sql/set_var.h
@@ -235,17 +235,27 @@ class sys_var_thd_ulonglong :public sys_var_thd
{
public:
ulonglong SV::*offset;
+ bool only_global;
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)
+ sys_after_update_func func, bool only_global_arg)
+ :sys_var_thd(name_arg, func), offset(offset_arg),
+ only_global(only_global_arg)
{}
bool update(THD *thd, set_var *var);
void set_default(THD *thd, enum_var_type type);
SHOW_TYPE type() { return SHOW_LONGLONG; }
byte *value_ptr(THD *thd, enum_var_type type);
+ bool check_default(enum_var_type type)
+ {
+ return type == OPT_GLOBAL && !option_limits;
+ }
+ bool check_type(enum_var_type type)
+ {
+ return (only_global && type != OPT_GLOBAL);
+ }
};
diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt
index 5a9d9f2cf29..d48b926ea15 100644
--- a/sql/share/czech/errmsg.txt
+++ b/sql/share/czech/errmsg.txt
@@ -114,7 +114,7 @@ v/*
"Blob polo-B¾ka '%-.64s' nemù¾e mít defaultní hodnotu",
"Nep-Bøípustné jméno databáze '%-.64s'",
"Nep-Bøípustné jméno tabulky '%-.64s'",
-"Zadan-Bý SELECT by procházel pøíli¹ mnoho záznamù a trval velmi dlouho. Zkontrolujte tvar WHERE a je-li SELECT v poøádku, pou¾ijte SET OPTION SQL_BIG_SELECTS=1",
+"Zadan-Bý SELECT by procházel pøíli¹ mnoho záznamù a trval velmi dlouho. Zkontrolujte tvar WHERE a je-li SELECT v poøádku, pou¾ijte SET SQL_BIG_SELECTS=1",
"Nezn-Bámá chyba",
"Nezn-Bámá procedura %s",
"Chybn-Bý poèet parametrù procedury %s",
diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt
index 4515f78d8e9..babdfad72f2 100644
--- a/sql/share/danish/errmsg.txt
+++ b/sql/share/danish/errmsg.txt
@@ -108,7 +108,7 @@
"BLOB feltet '%-.64s' kan ikke have en standard værdi",
"Ugyldigt database navn '%-.64s'",
"Ugyldigt tabel navn '%-.64s'",
-"SELECT ville undersøge for mange poster og ville sandsynligvis tage meget lang tid. Undersøg WHERE delen og brug SET OPTION SQL_BIG_SELECTS=1 hvis udtrykket er korrekt",
+"SELECT ville undersøge for mange poster og ville sandsynligvis tage meget lang tid. Undersøg WHERE delen og brug SET SQL_BIG_SELECTS=1 hvis udtrykket er korrekt",
"Ukendt fejl",
"Ukendt procedure %s",
"Forkert antal parametre til proceduren %s",
diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt
index 4b81f94eb83..1437301b144 100644
--- a/sql/share/dutch/errmsg.txt
+++ b/sql/share/dutch/errmsg.txt
@@ -116,7 +116,7 @@
"Blob veld '%-.64s' can geen standaardwaarde bevatten",
"Databasenaam '%-.64s' is niet getoegestaan",
"Niet toegestane tabelnaam '%-.64s'",
-"Het SELECT-statement zou te veel records analyseren en dus veel tijd in beslagnemen. Kijk het WHERE-gedeelte van de query na en kies SET OPTION SQL_BIG_SELECTS=1 als het stament in orde is.",
+"Het SELECT-statement zou te veel records analyseren en dus veel tijd in beslagnemen. Kijk het WHERE-gedeelte van de query na en kies SET SQL_BIG_SELECTS=1 als het stament in orde is.",
"Onbekende Fout",
"Onbekende procedure %s",
"Foutief aantal parameters doorgegeven aan procedure %s",
diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt
index 85ab7ac5e9f..69cf492e383 100644
--- a/sql/share/english/errmsg.txt
+++ b/sql/share/english/errmsg.txt
@@ -105,7 +105,7 @@
"BLOB column '%-.64s' can't have a default value",
"Incorrect database name '%-.100s'",
"Incorrect table name '%-.100s'",
-"The SELECT would examine too many records and probably take a very long time. Check your WHERE and use SET OPTION SQL_BIG_SELECTS=1 if the SELECT is ok",
+"The SELECT would examine more rows than MAX_JOIN_SIZE. Check your WHERE and use SET SQL_BIG_SELECTS=1 or SET SQL_MAX_JOIN_SIZE=# if the SELECT is ok",
"Unknown error",
"Unknown procedure '%-.64s'",
"Incorrect parameter count to procedure '%-.64s'",
diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt
index 20465266d46..04fb93838a9 100644
--- a/sql/share/estonian/errmsg.txt
+++ b/sql/share/estonian/errmsg.txt
@@ -110,7 +110,7 @@
"BLOB-tüüpi tulp '%-.64s' ei saa omada vaikeväärtust",
"Vigane andmebaasi nimi '%-.100s'",
"Vigane tabeli nimi '%-.100s'",
-"SELECT lause peab läbi vaatama suure hulga kirjeid ja võtaks tõenäoliselt liiga kaua aega. Tasub kontrollida WHERE klauslit ja vajadusel kasutada käsku SET OPTION SQL_BIG_SELECTS=1",
+"SELECT lause peab läbi vaatama suure hulga kirjeid ja võtaks tõenäoliselt liiga kaua aega. Tasub kontrollida WHERE klauslit ja vajadusel kasutada käsku SET SQL_BIG_SELECTS=1",
"Tundmatu viga",
"Tundmatu protseduur '%-.64s'",
"Vale parameetrite hulk protseduurile '%-.64s'",
diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt
index 4af12b8dbbc..e1f49e26ad7 100644
--- a/sql/share/french/errmsg.txt
+++ b/sql/share/french/errmsg.txt
@@ -105,7 +105,7 @@
"BLOB '%-.64s' ne peut avoir de valeur par défaut",
"Nom de base de donnée illégal: '%-.64s'",
"Nom de table illégal: '%-.64s'",
-"SELECT va devoir examiner beaucoup d'enregistrements ce qui va prendre du temps. Vérifiez la clause WHERE et utilisez SET OPTION SQL_BIG_SELECTS=1 si SELECT se passe bien",
+"SELECT va devoir examiner beaucoup d'enregistrements ce qui va prendre du temps. Vérifiez la clause WHERE et utilisez SET SQL_BIG_SELECTS=1 si SELECT se passe bien",
"Erreur inconnue",
"Procédure %s inconnue",
"Mauvais nombre de paramètres pour la procedure %s",
diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt
index 525d59164b0..5831e220e4d 100644
--- a/sql/share/german/errmsg.txt
+++ b/sql/share/german/errmsg.txt
@@ -114,7 +114,7 @@
"BLOB-Feld '%-.64s' kann keinen Vorgabewert (Default-Value) besitzen.",
"Unerlaubter Datenbankname '%-.64s'.",
"Unerlaubter Tabellenname '%-.64s'.",
-"Die Ausführung des SELECT würde zu viele Datensätze untersuchen und wahrscheinlich sehr lange daueren. Bitte WHERE überprüfen oder gegebenenfalls SET OPTION SQL_BIG_SELECTS=1 verwenden.",
+"Die Ausführung des SELECT würde zu viele Datensätze untersuchen und wahrscheinlich sehr lange daueren. Bitte WHERE überprüfen oder gegebenenfalls SET SQL_BIG_SELECTS=1 verwenden.",
"Unbekannter Fehler.",
"Unbekannte Procedure %-.64s.",
"Falsche Parameterzahl für Procedure %-.64s.",
diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt
index 26db2a19561..478a5728e19 100644
--- a/sql/share/greek/errmsg.txt
+++ b/sql/share/greek/errmsg.txt
@@ -105,7 +105,7 @@
"Ôá Blob ðåäßá '%-.64s' äåí ìðïñïýí íá Ý÷ïõí ðñïêáèïñéóìÝíåò ôéìÝò (default value)",
"ËÜèïò üíïìá âÜóçò äåäïìÝíùí '%-.100s'",
"ËÜèïò üíïìá ðßíáêá '%-.100s'",
-"Ôï SELECT èá åîåôÜóåé ìåãÜëï áñéèìü åããñáöþí êáé ðéèáíþò èá êáèõóôåñÞóåé. Ðáñáêáëþ åîåôÜóôå ôéò ðáñáìÝôñïõò ôïõ WHERE êáé ÷ñçóéìïðïéåßóôå SET OPTION SQL_BIG_SELECTS=1 áí ôï SELECT åßíáé óùóôü",
+"Ôï SELECT èá åîåôÜóåé ìåãÜëï áñéèìü åããñáöþí êáé ðéèáíþò èá êáèõóôåñÞóåé. Ðáñáêáëþ åîåôÜóôå ôéò ðáñáìÝôñïõò ôïõ WHERE êáé ÷ñçóéìïðïéåßóôå SET SQL_BIG_SELECTS=1 áí ôï SELECT åßíáé óùóôü",
"ÐñïÝêõøå Üãíùóôï ëÜèïò",
"Áãíùóôç äéáäéêáóßá '%-.64s'",
"ËÜèïò áñéèìüò ðáñáìÝôñùí óôç äéáäéêáóßá '%-.64s'",
diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt
index 7ba86704cb1..8bad9427bc7 100644
--- a/sql/share/hungarian/errmsg.txt
+++ b/sql/share/hungarian/errmsg.txt
@@ -107,7 +107,7 @@
"A(z) '%-.64s' blob objektumnak nem lehet alapertelmezett erteke",
"Hibas adatbazisnev: '%-.100s'",
"Hibas tablanev: '%-.100s'",
-"A SELECT tul sok rekordot fog megvizsgalni es nagyon sokaig fog tartani. Ellenorizze a WHERE-t es hasznalja a SET OPTION SQL_BIG_SELECTS=1 beallitast, ha a SELECT ok",
+"A SELECT tul sok rekordot fog megvizsgalni es nagyon sokaig fog tartani. Ellenorizze a WHERE-t es hasznalja a SET SQL_BIG_SELECTS=1 beallitast, ha a SELECT ok",
"Ismeretlen hiba",
"Ismeretlen eljaras: '%-.64s'",
"Rossz parameter a(z) '%-.64s'eljaras szamitasanal",
diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt
index 30dc00546cd..977d82fbea4 100644
--- a/sql/share/italian/errmsg.txt
+++ b/sql/share/italian/errmsg.txt
@@ -105,7 +105,7 @@
"Il campo BLOB '%-.64s' non puo` avere un valore di default",
"Nome database errato '%-.100s'",
"Nome tabella errato '%-.100s'",
-"La SELECT dovrebbe esaminare troppi record e usare troppo tempo. Controllare la WHERE e usa SET OPTION SQL_BIG_SELECTS=1 se e` tutto a posto.",
+"La SELECT dovrebbe esaminare troppi record e usare troppo tempo. Controllare la WHERE e usa SET SQL_BIG_SELECTS=1 se e` tutto a posto.",
"Errore sconosciuto",
"Procedura '%-.64s' sconosciuta",
"Numero di parametri errato per la procedura '%-.64s'",
diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt
index eb0d085bd28..5ea756c0443 100644
--- a/sql/share/japanese/errmsg.txt
+++ b/sql/share/japanese/errmsg.txt
@@ -107,7 +107,7 @@
"BLOB column '%-.64s' can't have a default value",
"»ØÄꤷ¤¿ database ̾ '%-.100s' ¤¬´Ö°ã¤Ã¤Æ¤¤¤Þ¤¹",
"»ØÄꤷ¤¿ table ̾ '%-.100s' ¤Ï¤Þ¤Á¤¬¤Ã¤Æ¤¤¤Þ¤¹",
-"The SELECT would examine too many records and probably take a very long time. Check your WHERE and use SET OPTION SQL_BIG_SELECTS=1 if the SELECT is ok",
+"The SELECT would examine more rows than MAX_JOIN_SIZE. Check your WHERE and use SET SQL_BIG_SELECTS=1 or SET SQL_MAX_JOIN_SIZE=# if the SELECT is ok",
"Unknown error",
"Unknown procedure '%-.64s'",
"Incorrect parameter count to procedure '%-.64s'",
diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt
index 9747e3cbb3e..ec4971681c3 100644
--- a/sql/share/korean/errmsg.txt
+++ b/sql/share/korean/errmsg.txt
@@ -105,7 +105,7 @@
"BLOB Ä®·³ '%-.64s' ´Â µðÆúÆ® °ªÀ» °¡Áú ¼ö ¾ø½À´Ï´Ù.",
"'%-.100s' µ¥ÀÌŸº£À̽ºÀÇ À̸§ÀÌ ºÎÁ¤È®ÇÕ´Ï´Ù.",
"'%-.100s' Å×À̺í À̸§ÀÌ ºÎÁ¤È®ÇÕ´Ï´Ù.",
-"SELECT ¸í·É¿¡¼­ ³Ê¹« ¸¹Àº ·¹Äڵ带 ã±â ¶§¹®¿¡ ¸¹Àº ½Ã°£ÀÌ ¼Ò¿äµË´Ï´Ù. µû¶ó¼­ WHERE ¹®À» Á¡°ËÇϰųª, ¸¸¾à SELECT°¡ okµÇ¸é SET OPTION SQL_BIG_SELECTS=1 ¿É¼ÇÀ» »ç¿ëÇϼ¼¿ä.",
+"SELECT ¸í·É¿¡¼­ ³Ê¹« ¸¹Àº ·¹Äڵ带 ã±â ¶§¹®¿¡ ¸¹Àº ½Ã°£ÀÌ ¼Ò¿äµË´Ï´Ù. µû¶ó¼­ WHERE ¹®À» Á¡°ËÇϰųª, ¸¸¾à SELECT°¡ okµÇ¸é SET SQL_BIG_SELECTS=1 ¿É¼ÇÀ» »ç¿ëÇϼ¼¿ä.",
"¾Ë¼ö ¾ø´Â ¿¡·¯ÀÔ´Ï´Ù.",
"¾Ë¼ö ¾ø´Â ¼öÇ๮ : '%-.64s'",
"'%-.64s' ¼öÇ๮¿¡ ´ëÇÑ ºÎÁ¤È®ÇÑ ÆĶó¸ÞÅÍ",
diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt
index 46eada87157..b2ff7cf8258 100644
--- a/sql/share/norwegian-ny/errmsg.txt
+++ b/sql/share/norwegian-ny/errmsg.txt
@@ -107,7 +107,7 @@
"Blob feltet '%-.64s' kan ikkje ha ein standard verdi",
"Ugyldig database namn '%-.64s'",
"Ugyldig tabell namn '%-.64s'",
-"SELECT ville undersøkje for mange postar og ville sannsynligvis ta veldig lang tid. Undersøk WHERE klausulen og bruk SET OPTION SQL_BIG_SELECTS=1 om SELECTen er korrekt",
+"SELECT ville undersøkje for mange postar og ville sannsynligvis ta veldig lang tid. Undersøk WHERE klausulen og bruk SET SQL_BIG_SELECTS=1 om SELECTen er korrekt",
"Ukjend feil",
"Ukjend prosedyre %s",
"Feil parameter tal til prosedyra %s",
diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt
index 0f4a0852222..1d3e6f978e0 100644
--- a/sql/share/norwegian/errmsg.txt
+++ b/sql/share/norwegian/errmsg.txt
@@ -107,7 +107,7 @@
"Blob feltet '%-.64s' kan ikke ha en standard verdi",
"Ugyldig database navn '%-.64s'",
"Ugyldig tabell navn '%-.64s'",
-"SELECT ville undersøke for mange poster og ville sannsynligvis ta veldig lang tid. Undersøk WHERE klausulen og bruk SET OPTION SQL_BIG_SELECTS=1 om SELECTen er korrekt",
+"SELECT ville undersøke for mange poster og ville sannsynligvis ta veldig lang tid. Undersøk WHERE klausulen og bruk SET SQL_BIG_SELECTS=1 om SELECTen er korrekt",
"Ukjent feil",
"Ukjent prosedyre %s",
"Feil parameter antall til prosedyren %s",
diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt
index af971e6a6ee..9771a02ce34 100644
--- a/sql/share/portuguese/errmsg.txt
+++ b/sql/share/portuguese/errmsg.txt
@@ -105,7 +105,7 @@
"Coluna BLOB '%-.64s' não pode ter um valor padrão (default)",
"Nome de banco de dados '%-.100s' incorreto",
"Nome de tabela '%-.100s' incorreto",
-"O SELECT examinaria registros demais e provavelmente levaria muito tempo. Cheque sua cláusula WHERE e use SET OPTION SQL_BIG_SELECTS=1, se o SELECT estiver correto",
+"O SELECT examinaria registros demais e provavelmente levaria muito tempo. Cheque sua cláusula WHERE e use SET SQL_BIG_SELECTS=1, se o SELECT estiver correto",
"Erro desconhecido",
"'Procedure' '%-.64s' desconhecida",
"Número de parâmetros incorreto para a 'procedure' '%-.64s'",
diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt
index 49cdad9adb3..2b7cc7824be 100644
--- a/sql/share/romanian/errmsg.txt
+++ b/sql/share/romanian/errmsg.txt
@@ -109,7 +109,7 @@
"Coloana BLOB '%-.64s' nu poate avea o valoare default",
"Numele bazei de date este incorect '%-.100s'",
"Numele tabelei este incorect '%-.100s'",
-"SELECT-ul ar examina prea multe cimpuri si probabil ar lua prea mult timp. Verifica clauza WHERE si foloseste SET OPTION SQL_BIG_SELECTS=1 daca SELECT-ul e ok",
+"SELECT-ul ar examina prea multe cimpuri si probabil ar lua prea mult timp. Verifica clauza WHERE si foloseste SET SQL_BIG_SELECTS=1 daca SELECT-ul e ok",
"Eroare unknown",
"Procedura unknown '%-.64s'",
"Procedura '%-.64s' are un numar incorect de parametri",
diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt
index ef883b38bd3..79389a43c45 100644
--- a/sql/share/russian/errmsg.txt
+++ b/sql/share/russian/errmsg.txt
@@ -107,7 +107,7 @@
"îÅ×ÏÚÍÏÖÎÏ ÕËÁÚÙ×ÁÔØ ÚÎÁÞÅÎÉÅ ÐÏ ÕÍÏÌÞÁÎÉÀ ÄÌÑ ÓÔÏÌÂÃÁ BLOB '%-.64s'",
"îÅËÏÒÒÅËÔÎÏÅ ÉÍÑ ÂÁÚÙ ÄÁÎÎÙÈ '%-.100s'",
"îÅËÏÒÒÅËÔÎÏÅ ÉÍÑ ÔÁÂÌÉÃÙ '%-.100s'",
-"äÌÑ ÔÁËÏÊ ×ÙÂÏÒËÉ SELECT ÄÏÌÖÅÎ ÂÕÄÅÔ ÐÒÏÓÍÏÔÒÅÔØ ÓÌÉÛËÏÍ ÍÎÏÇÏ ÚÁÐÉÓÅÊ É, ×ÉÄÉÍÏ, ÜÔÏ ÚÁÊÍÅÔ ÏÞÅÎØ ÍÎÏÇÏ ×ÒÅÍÅÎÉ. ðÒÏ×ÅÒØÔÅ ×ÁÛÅ ÕËÁÚÁÎÉÅ WHERE, É, ÅÓÌÉ × ÎÅÍ ×ÓÅ × ÐÏÒÑÄËÅ, ÕËÁÖÉÔÅ SET OPTION SQL_BIG_SELECTS=1",
+"äÌÑ ÔÁËÏÊ ×ÙÂÏÒËÉ SELECT ÄÏÌÖÅÎ ÂÕÄÅÔ ÐÒÏÓÍÏÔÒÅÔØ ÓÌÉÛËÏÍ ÍÎÏÇÏ ÚÁÐÉÓÅÊ É, ×ÉÄÉÍÏ, ÜÔÏ ÚÁÊÍÅÔ ÏÞÅÎØ ÍÎÏÇÏ ×ÒÅÍÅÎÉ. ðÒÏ×ÅÒØÔÅ ×ÁÛÅ ÕËÁÚÁÎÉÅ WHERE, É, ÅÓÌÉ × ÎÅÍ ×ÓÅ × ÐÏÒÑÄËÅ, ÕËÁÖÉÔÅ SET SQL_BIG_SELECTS=1",
"îÅÉÚ×ÅÓÔÎÁÑ ÏÛÉÂËÁ",
"îÅÉÚ×ÅÓÔÎÁÑ ÐÒÏÃÅÄÕÒÁ '%-.64s'",
"îÅËÏÒÒÅËÔÎÏÅ ËÏÌÉÞÅÓÔ×Ï ÐÁÒÁÍÅÔÒÏ× ÄÌÑ ÐÒÏÃÅÄÕÒÙ '%-.64s'",
diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt
index a6c42c01e1c..cf0845a6f7a 100644
--- a/sql/share/slovak/errmsg.txt
+++ b/sql/share/slovak/errmsg.txt
@@ -113,7 +113,7 @@
"Pole BLOB '%-.64s' nemô¾e ma» implicitnú hodnotu",
"Neprípustné meno databázy '%-.100s'",
"Neprípustné meno tabuµky '%-.100s'",
-"Zadaná po¾iadavka SELECT by prechádzala príli¹ mnoho záznamov a trvala by príli¹ dlho. Skontrolujte tvar WHERE a ak je v poriadku, pou¾ite SET OPTION SQL_BIG_SELECTS=1",
+"Zadaná po¾iadavka SELECT by prechádzala príli¹ mnoho záznamov a trvala by príli¹ dlho. Skontrolujte tvar WHERE a ak je v poriadku, pou¾ite SET SQL_BIG_SELECTS=1",
"Neznámá chyba",
"Neznámá procedúra '%-.64s'",
"Chybný poèet parametrov procedúry '%-.64s'",
diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt
index 6172524ddc3..96cb7ef3316 100644
--- a/sql/share/spanish/errmsg.txt
+++ b/sql/share/spanish/errmsg.txt
@@ -106,7 +106,7 @@
"Campo Blob '%-.64s' no puede tener valores patron",
"Nombre de base de datos ilegal '%-.64s'",
"Nombre de tabla ilegal '%-.64s'",
-"El SELECT puede examinar muchos registros y probablemente con mucho tiempo. Verifique tu WHERE y usa SET OPTION SQL_BIG_SELECTS=1 si el SELECT esta correcto",
+"El SELECT puede examinar muchos registros y probablemente con mucho tiempo. Verifique tu WHERE y usa SET SQL_BIG_SELECTS=1 si el SELECT esta correcto",
"Error desconocido",
"Procedimiento desconocido %s",
"Equivocado parametro count para procedimiento %s",
diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt
index b3cab964fd4..22147795ec3 100644
--- a/sql/share/swedish/errmsg.txt
+++ b/sql/share/swedish/errmsg.txt
@@ -105,7 +105,7 @@
"BLOB fält '%-.64s' kan inte ha ett DEFAULT-värde",
"Felaktigt databasnamn '%-.64s'",
"Felaktigt tabellnamn '%-.64s'",
-"Den angivna frågan skulle troligen ta mycket lång tid! Kontrollera din WHERE och använd SET OPTION SQL_BIG_SELECTS=1 ifall du vill hantera stora joins",
+"Den angivna frågan skulle läsa mer än MAX_JOIN_SIZE rader. Kontrollera din WHERE och använd SET SQL_BIG_SELECTS=1 eller SET MAX_JOIN_SIZE=# ifall du vill hantera stora joins",
"Oidentifierat fel",
"Okänd procedur: %s",
"Felaktigt antal parametrar till procedur %s",
diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt
index 3c3507c1a2a..84ac581bdb1 100644
--- a/sql/share/ukrainian/errmsg.txt
+++ b/sql/share/ukrainian/errmsg.txt
@@ -110,7 +110,7 @@
"óÔÏ×ÂÅÃØ BLOB '%-.64s' ÎÅ ÍÏÖÅ ÍÁÔÉ ÚÎÁÞÅÎÎÑ ÐÏ ÚÁÍÏ×ÞÕ×ÁÎÎÀ",
"îÅצÒÎÅ ¦Í'Ñ ÂÁÚÉ ÄÁÎÎÉÈ '%-.100s'",
"îÅצÒÎÅ ¦Í'Ñ ÔÁÂÌÉæ '%-.100s'",
-"úÁÐÉÔÕ SELECT ÐÏÔÒ¦ÂÎÏ ÏÂÒÏÂÉÔÉ ÂÁÇÁÔÏ ÚÁÐÉÓ¦×, ÝÏ, ÐÅ×ÎÅ, ÚÁÊÍÅ ÄÕÖÅ ÂÁÇÁÔÏ ÞÁÓÕ. ðÅÒÅצÒÔÅ ×ÁÛÅ WHERE ÔÁ ×ÉËÏÒÉÓÔÏ×ÕÊÔÅ SET OPTION SQL_BIG_SELECTS=1, ÑËÝÏ ÃÅÊ ÚÁÐÉÔ SELECT ¤ צÒÎÉÍ",
+"úÁÐÉÔÕ SELECT ÐÏÔÒ¦ÂÎÏ ÏÂÒÏÂÉÔÉ ÂÁÇÁÔÏ ÚÁÐÉÓ¦×, ÝÏ, ÐÅ×ÎÅ, ÚÁÊÍÅ ÄÕÖÅ ÂÁÇÁÔÏ ÞÁÓÕ. ðÅÒÅצÒÔÅ ×ÁÛÅ WHERE ÔÁ ×ÉËÏÒÉÓÔÏ×ÕÊÔÅ SET SQL_BIG_SELECTS=1, ÑËÝÏ ÃÅÊ ÚÁÐÉÔ SELECT ¤ צÒÎÉÍ",
"îÅצÄÏÍÁ ÐÏÍÉÌËÁ",
"îÅצÄÏÍÁ ÐÒÏÃÅÄÕÒÁ '%-.64s'",
"èÉÂÎÁ ˦ÌØ˦ÓÔØ ÐÁÒÁÍÅÔÒ¦× ÐÒÏÃÅÄÕÒÉ '%-.64s'",
diff --git a/sql/slave.cc b/sql/slave.cc
index eae795ae760..be95cc16d90 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -2429,9 +2429,7 @@ err:
goto slave_begin;
#endif
my_thread_end();
-#ifndef __NETWARE__
pthread_exit(0);
-#endif /* __NETWARE__ */
DBUG_RETURN(0); // Can't return anything here
}
@@ -2573,9 +2571,7 @@ the slave SQL thread with \"SLAVE START\". We stopped at log \
goto slave_begin;
#endif
my_thread_end();
-#ifndef __NETWARE__
pthread_exit(0);
-#endif /* __NETWARE__ */
DBUG_RETURN(0); // Can't return anything here
}
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index b6191b2061e..accbc9cf205 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -70,7 +70,7 @@ static ACL_USER *find_acl_user(const char *host, const char *user);
static bool update_user_table(THD *thd, const char *host, const char *user,
const char *new_password);
static void update_hostname(acl_host_and_ip *host, const char *hostname);
-static bool compare_hostname(const acl_host_and_ip *host, const char *hostname,
+static bool compare_hostname(const acl_host_and_ip *host,const char *hostname,
const char *ip);
/*
@@ -496,8 +496,9 @@ void prepare_scramble(THD *thd, ACL_USER *acl_user,char* prepared_scramble)
ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
const char *password,const char *message,char **priv_user,
- bool old_ver, USER_RESOURCES *mqh, char *prepared_scramble,
- uint *cur_priv_version, ACL_USER **cached_user)
+ char *priv_host, bool old_ver, USER_RESOURCES *mqh,
+ char *prepared_scramble, uint *cur_priv_version,
+ ACL_USER **cached_user)
{
ulong user_access=NO_ACCESS;
*priv_user= (char*) user;
@@ -593,7 +594,7 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
{
Vio *vio=thd->net.vio;
/*
- In this point we know that user is allowed to connect
+ At this point we know that user is allowed to connect
from given host by given username/password pair. Now
we check if SSL is required, if user is using SSL and
if X509 certificate attributes are OK
@@ -611,8 +612,11 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
/*
Connections with non-valid certificates are dropped already
in sslaccept() anyway, so we do not check validity here.
+
+ We need to check for absence of SSL because without SSL
+ we should reject connection.
*/
- if (SSL_get_peer_certificate(vio->ssl_))
+ if (vio_type(vio) == VIO_TYPE_SSL && SSL_get_peer_certificate(vio->ssl_))
user_access=acl_user->access;
break;
case SSL_TYPE_SPECIFIED: /* Client should have specified attrib */
@@ -622,6 +626,8 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
If cipher name is specified, we compare it to actual cipher in
use.
*/
+ if (vio_type(vio) != VIO_TYPE_SSL)
+ break;
if (acl_user->ssl_cipher)
{
DBUG_PRINT("info",("comparing ciphers: '%s' and '%s'",
@@ -630,6 +636,10 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
user_access=acl_user->access;
else
{
+ if (global_system_variables.log_warnings)
+ sql_print_error("X509 ciphers mismatch: should be '%s' but is '%s'",
+ acl_user->ssl_cipher,
+ SSL_get_cipher(vio->ssl_));
user_access=NO_ACCESS;
break;
}
@@ -647,6 +657,9 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
acl_user->x509_issuer, ptr));
if (strcmp(acl_user->x509_issuer, ptr))
{
+ if (global_system_variables.log_warnings)
+ sql_print_error("X509 issuer mismatch: should be '%s' but is '%s'",
+ acl_user->x509_issuer, ptr);
user_access=NO_ACCESS;
free(ptr);
break;
@@ -662,7 +675,12 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
DBUG_PRINT("info",("comparing subjects: '%s' and '%s'",
acl_user->x509_subject, ptr));
if (strcmp(acl_user->x509_subject,ptr))
+ {
+ if (global_system_variables.log_warnings)
+ sql_print_error("X509 subject mismatch: '%s' vs '%s'",
+ acl_user->x509_subject, ptr);
user_access=NO_ACCESS;
+ }
else
user_access=acl_user->access;
free(ptr);
@@ -677,6 +695,11 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
if (!acl_user->user)
*priv_user=(char*) ""; // Change to anonymous user /* purecov: inspected */
+ if (acl_user->host.hostname)
+ strmake(priv_host, acl_user->host.hostname, MAX_HOSTNAME);
+ else
+ *priv_host= 0;
+
unlock_and_exit:
VOID(pthread_mutex_unlock(&acl_cache->lock));
DBUG_RETURN(user_access);
@@ -780,7 +803,7 @@ static void acl_insert_user(const char *user, const char *host,
VOID(push_dynamic(&acl_users,(gptr) &acl_user));
if (!acl_user.host.hostname || acl_user.host.hostname[0] == wild_many
&& !acl_user.host.hostname[1])
- allow_all_hosts=1; // Anyone can connect /* purecov: tested */
+ allow_all_hosts=1; // Anyone can connect /* purecov: tested */
qsort((gptr) dynamic_element(&acl_users,0,ACL_USER*),acl_users.elements,
sizeof(ACL_USER),(qsort_cmp) acl_compare);
@@ -1126,8 +1149,7 @@ bool change_password(THD *thd, const char *host, const char *user,
Simple hack to avoid cracking
*/
length=(uint) strlen(new_password);
-
- if (length!=45)
+ if (length != 45)
new_password[length & 16]=0;
VOID(pthread_mutex_lock(&acl_cache->lock));
@@ -2060,10 +2082,10 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table,
}
-int mysql_table_grant (THD *thd, TABLE_LIST *table_list,
- List <LEX_USER> &user_list,
- List <LEX_COLUMN> &columns, ulong rights,
- bool revoke_grant)
+int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
+ List <LEX_USER> &user_list,
+ List <LEX_COLUMN> &columns, ulong rights,
+ bool revoke_grant)
{
ulong column_priv = 0;
List_iterator <LEX_USER> str_list (user_list);
@@ -2437,7 +2459,7 @@ my_bool grant_init(THD *org_thd)
mem_check->ok() && hash_insert(&column_priv_hash,(byte*) mem_check))
{
/* This could only happen if we are out memory */
- grant_option = FALSE; /* purecov: deadcode */
+ grant_option= FALSE; /* purecov: deadcode */
goto end_unlock;
}
}
@@ -2477,16 +2499,16 @@ void grant_reload(THD *thd)
rw_wrlock(&LOCK_grant);
grant_version++;
old_column_priv_hash= column_priv_hash;
- old_grant_option = grant_option;
- old_mem = memex;
+ old_grant_option= grant_option;
+ old_mem= memex;
if (grant_init(thd))
{ // Error. Revert to old hash
DBUG_PRINT("error",("Reverting to old privileges"));
grant_free(); /* purecov: deadcode */
column_priv_hash= old_column_priv_hash; /* purecov: deadcode */
- grant_option = old_grant_option; /* purecov: deadcode */
- memex = old_mem; /* purecov: deadcode */
+ grant_option= old_grant_option; /* purecov: deadcode */
+ memex= old_mem; /* purecov: deadcode */
}
else
{
@@ -2583,8 +2605,8 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
}
-bool check_grant_column (THD *thd,TABLE *table, const char *name,
- uint length, uint show_tables)
+bool check_grant_column(THD *thd,TABLE *table, const char *name,
+ uint length, uint show_tables)
{
GRANT_TABLE *grant_table;
GRANT_COLUMN *grant_column;
@@ -2651,6 +2673,8 @@ bool check_grant_all_columns(THD *thd, ulong want_access, TABLE *table)
want_access &= ~table->grant.privilege;
if (!want_access)
return 0; // Already checked
+ if (!grant_option)
+ goto err2;
rw_rdlock(&LOCK_grant);
@@ -2679,9 +2703,9 @@ bool check_grant_all_columns(THD *thd, ulong want_access, TABLE *table)
return 0;
/* We must use my_printf_error() here! */
- err:
+err:
rw_unlock(&LOCK_grant);
-
+err2:
const char *command="";
if (want_access & SELECT_ACL)
command ="select";
@@ -3108,11 +3132,11 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
}
}
}
- global.append(" ON ",4);
+ global.append(" ON `",5);
global.append(grant_table->db);
- global.append(".",1);
+ global.append("`.`,3);
global.append(grant_table->tname);
- global.append(" TO '",5);
+ global.append("` TO '",6);
global.append(lex_user->user.str,lex_user->user.length);
global.append("'@'",3);
global.append(lex_user->host.str,lex_user->host.length);
diff --git a/sql/sql_acl.h b/sql/sql_acl.h
index ceb866d809f..d85a281cbb5 100644
--- a/sql/sql_acl.h
+++ b/sql/sql_acl.h
@@ -136,7 +136,8 @@ void acl_free(bool end=0);
ulong acl_get(const char *host, const char *ip, const char *bin_ip,
const char *user, const char *db);
ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
- const char *password,const char *scramble,char **priv_user,
+ const char *password,const char *scramble,
+ char **priv_user, char *priv_host,
bool old_ver, USER_RESOURCES *max,char* prepared_scramble,
uint *cur_priv_version, ACL_USER **cached_user);
bool acl_check_host(const char *host, const char *ip);
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index fc95f5deb40..eeaf560693e 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -423,8 +423,9 @@ bool close_thread_table(THD *thd, TABLE **table_ptr)
{
DBUG_ENTER("close_thread_table");
- bool found_old_table=0;
- TABLE *table=*table_ptr;
+ bool found_old_table= 0;
+ TABLE *table= *table_ptr;
+ DBUG_ASSERT(table->key_read == 0);
*table_ptr=table->next;
if (table->version != refresh_version ||
@@ -1693,7 +1694,7 @@ Field *find_field_in_table(THD *thd,TABLE *table,const char *name,uint length,
else
thd->dupp_field=field;
}
- if (check_grants && check_grant_column(thd,table,name,length))
+ if (check_grants && check_grant_column(thd,table,name,length))
return WRONG_GRANT;
return field;
}
@@ -1743,8 +1744,8 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
{
found_table=1;
Field *find=find_field_in_table(thd,tables->table,name,length,
- grant_option &&
- tables->table->grant.want_privilege,
+ test(tables->table->grant.
+ want_privilege),
1);
if (find)
{
@@ -1801,8 +1802,7 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
}
Field *field=find_field_in_table(thd,tables->table,name,length,
- grant_option &&
- tables->table->grant.want_privilege,
+ test(tables->table->grant.want_privilege),
allow_rowid);
if (field)
{
@@ -2098,9 +2098,10 @@ insert_fields(THD *thd,TABLE_LIST *tables, const char *db_name,
(!db_name || !strcmp(tables->db,db_name))))
{
/* Ensure that we have access right to all columns */
- if (grant_option && !thd->master_access &&
- check_grant_all_columns(thd,SELECT_ACL,table) )
+ if (!(table->grant.privilege & SELECT_ACL) &&
+ check_grant_all_columns(thd,SELECT_ACL,table))
DBUG_RETURN(-1);
+
Field **ptr=table->field,*field;
thd->used_tables|=table->map;
while ((field = *ptr++))
@@ -2227,7 +2228,7 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
******************************************************************************/
int
-fill_record(List<Item> &fields,List<Item> &values)
+fill_record(List<Item> &fields,List<Item> &values, bool ignore_errors)
{
List_iterator_fast<Item> f(fields),v(values);
Item *value;
@@ -2237,7 +2238,7 @@ fill_record(List<Item> &fields,List<Item> &values)
while ((field=(Item_field*) f++))
{
value=v++;
- if (value->save_in_field(field->field, 0) > 0)
+ if (value->save_in_field(field->field, 0) > 0 && !ignore_errors)
DBUG_RETURN(1);
}
DBUG_RETURN(0);
@@ -2245,7 +2246,7 @@ fill_record(List<Item> &fields,List<Item> &values)
int
-fill_record(Field **ptr,List<Item> &values)
+fill_record(Field **ptr,List<Item> &values, bool ignore_errors)
{
List_iterator_fast<Item> v(values);
Item *value;
@@ -2255,7 +2256,7 @@ fill_record(Field **ptr,List<Item> &values)
while ((field = *ptr++))
{
value=v++;
- if (value->save_in_field(field, 0) == 1)
+ if (value->save_in_field(field, 0) == 1 && !ignore_errors)
DBUG_RETURN(1);
}
DBUG_RETURN(0);
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index d8265a1b359..adc3d177fdf 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -761,11 +761,11 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used)
uint8 tables_type= 0;
if ((local_tables = is_cacheable(thd, thd->query_length,
- thd->query, &thd->lex, tables_used,
- &tables_type)))
+ thd->query, &thd->lex, tables_used,
+ &tables_type)))
{
NET *net= &thd->net;
- byte flags = (thd->client_capabilities & CLIENT_LONG_FLAG ? 0x80 : 0);
+ byte flags= (thd->client_capabilities & CLIENT_LONG_FLAG ? 0x80 : 0);
STRUCT_LOCK(&structure_guard_mutex);
if (query_cache_size == 0)
@@ -790,8 +790,10 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used)
*/
flags|= (byte) thd->charset()->number;
DBUG_ASSERT(thd->charset()->number < 128);
- tot_length=thd->query_length+thd->db_length+2;
- thd->query[tot_length-1] = (char) flags;
+ tot_length= thd->query_length+thd->db_length+2+sizeof(ha_rows);
+ thd->query[tot_length-1]= (char) flags;
+ memcpy((void *)(thd->query + (tot_length-sizeof(ha_rows)-1)),
+ (const void *)&thd->variables.select_limit, sizeof(ha_rows));
/* Check if another thread is processing the same query? */
Query_cache_block *competitor = (Query_cache_block *)
@@ -921,7 +923,7 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
}
Query_cache_block *query_block;
- tot_length=query_length+thd->db_length+2;
+ tot_length= query_length+thd->db_length+2+sizeof(ha_rows);
if (thd->db_length)
{
memcpy(sql+query_length+1, thd->db, thd->db_length);
@@ -937,10 +939,12 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
Most significant bit - CLIENT_LONG_FLAG,
Other - charset number (0 no charset convertion)
*/
- flags = (thd->client_capabilities & CLIENT_LONG_FLAG ? 0x80 : 0);
- flags |= (byte) thd->charset()->number;
+ flags= (thd->client_capabilities & CLIENT_LONG_FLAG ? 0x80 : 0);
+ flags|= (byte) thd->charset()->number;
DBUG_ASSERT(thd->charset()->number < 128);
- sql[tot_length-1] = (char) flags;
+ sql[tot_length-1]= (char) flags;
+ memcpy((void *)(sql + (tot_length-sizeof(ha_rows)-1)),
+ (const void *)&thd->variables.select_limit, sizeof(ha_rows));
query_block = (Query_cache_block *) hash_search(&queries, (byte*) sql,
tot_length);
/* Quick abort on unlocked data */
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index f579b02ee50..9f6edd629ca 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -120,6 +120,7 @@ THD::THD():user_time(0), is_fatal_error(0),
net.last_error[0]=0; // If error on boot
ull=0;
system_thread=cleanup_done=0;
+ peer_port= 0; // For SHOW PROCESSLIST
transaction.changed_tables = 0;
#ifdef __WIN__
real_id = 0;
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 925afde2202..b24e28e58ec 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -358,6 +358,7 @@ struct system_variables
ulong max_prep_stmt_count;
ulong max_sort_length;
ulong max_tmp_tables;
+ ulong myisam_repair_threads;
ulong myisam_sort_buff_size;
ulong net_buffer_length;
ulong net_interactive_timeout;
@@ -434,13 +435,14 @@ public:
ip - client IP
*/
char *host,*user,*priv_user,*db,*ip;
+ char priv_host[MAX_HOSTNAME];
/* remote (peer) port */
uint16 peer_port;
/* Points to info-string that will show in SHOW PROCESSLIST */
const char *proc_info;
/* points to host if host is available, otherwise points to ip */
const char *host_or_ip;
-
+
ulong client_capabilities; /* What the client supports */
/* Determines if which non-standard SQL behaviour should be enabled */
ulong max_client_packet_length;
diff --git a/sql/sql_db.cc b/sql/sql_db.cc
index fe8a945bff8..b288dc68b42 100644
--- a/sql/sql_db.cc
+++ b/sql/sql_db.cc
@@ -401,6 +401,8 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db,
ulong found_other_files=0;
char filePath[FN_REFLEN];
TABLE_LIST *tot_list=0, **tot_list_next;
+ List<String> raid_dirs;
+
DBUG_ENTER("mysql_rm_known_files");
DBUG_PRINT("enter",("path: %s", org_path));
@@ -420,6 +422,8 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db,
{
char newpath[FN_REFLEN];
MY_DIR *new_dirp;
+ String *dir;
+
strxmov(newpath,org_path,"/",file->name,NullS);
unpack_filename(newpath,newpath);
if ((new_dirp = my_dir(newpath,MYF(MY_DONT_SORT))))
@@ -430,7 +434,11 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db,
my_dirend(dirp);
DBUG_RETURN(-1);
}
+ raid_dirs.push_back(dir=new String(newpath));
+ dir->copy();
+ continue;
}
+ found_other_files++;
continue;
}
if (find_type(fn_ext(file->name),&deletable_extentions,1+2) <= 0)
@@ -470,12 +478,19 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db,
deleted++;
}
}
- my_dirend(dirp);
-
if (thd->killed ||
(tot_list && mysql_rm_table_part2_with_lock(thd, tot_list, 1, 0, 1)))
+ {
+ my_dirend(dirp);
DBUG_RETURN(-1);
-
+ }
+ List_iterator<String> it(raid_dirs);
+ String *dir;
+ while ((dir= it++))
+ if (rmdir(dir->c_ptr()) < 0)
+ found_other_files++;
+ my_dirend(dirp);
+
/*
If the directory is a symbolic link, remove the link first, then
remove the directory the symbolic link pointed at
@@ -573,11 +588,11 @@ bool mysql_change_db(THD *thd, const char *name)
{
net_printf(thd,ER_DBACCESS_DENIED_ERROR,
thd->priv_user,
- thd->host_or_ip,
+ thd->priv_host,
dbname);
mysql_log.write(thd,COM_INIT_DB,ER(ER_DBACCESS_DENIED_ERROR),
thd->priv_user,
- thd->host_or_ip,
+ thd->priv_host,
dbname);
my_free(dbname,MYF(0));
DBUG_RETURN(1);
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index 6bb336a87a6..a12f6efb006 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -67,7 +67,7 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order,
}
/* Test if the user wants to delete all rows */
- if (!using_limit && const_cond &&
+ if (!using_limit && const_cond && (!conds || conds->val_int()) &&
!(specialflag & (SPECIAL_NO_NEW_FUNC | SPECIAL_SAFE_MODE)))
{
deleted= table->file->records;
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 7418140517c..829300859cf 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -258,7 +258,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
if (fields.elements || !value_count)
{
restore_record(table,default_values); // Get empty record
- if (fill_record(fields,*values)|| thd->net.report_error ||
+ if (fill_record(fields, *values, 0)|| thd->net.report_error ||
check_null_fields(thd,table))
{
if (values_list.elements != 1 && !thd->net.report_error)
@@ -276,7 +276,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
restore_record(table,default_values); // Get empty record
else
table->record[0][0]=table->default_values[0]; // Fix delete marker
- if (fill_record(table->field,*values) || thd->net.report_error)
+ if (fill_record(table->field,*values, 0) || thd->net.report_error)
{
if (values_list.elements != 1 && ! thd->net.report_error)
{
@@ -708,6 +708,9 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list)
/* no match; create a new thread to handle the table */
if (!(tmp=find_handler(thd,table_list)))
{
+ /* Don't create more than max_insert_delayed_threads */
+ if (delayed_insert_threads >= max_insert_delayed_threads)
+ DBUG_RETURN(0);
thd->proc_info="Creating delayed handler";
pthread_mutex_lock(&LOCK_delayed_create);
if (!(tmp=find_handler(thd,table_list))) // Was just created
@@ -1086,12 +1089,12 @@ extern "C" pthread_handler_decl(handle_delayed_insert,arg)
while (!thd->killed)
{
int error;
-#if (defined(HAVE_BROKEN_COND_TIMEDWAIT) || defined(HAVE_LINUXTHREADS))
+#if defined(HAVE_BROKEN_COND_TIMEDWAIT)
error=pthread_cond_wait(&di->cond,&di->mutex);
#else
error=pthread_cond_timedwait(&di->cond,&di->mutex,&abstime);
#ifdef EXTRA_DEBUG
- if (error && error != EINTR)
+ if (error && error != EINTR && error != ETIMEDOUT)
{
fprintf(stderr, "Got error %d from pthread_cond_timedwait\n",error);
DBUG_PRINT("error",("Got error %d from pthread_cond_timedwait",
@@ -1393,9 +1396,9 @@ bool select_insert::send_data(List<Item> &values)
return 0;
}
if (fields->elements)
- fill_record(*fields,values);
+ fill_record(*fields, values, 1);
else
- fill_record(table->field,values);
+ fill_record(table->field, values, 1);
if (thd->net.report_error || write_record(table,&info))
return 1;
if (table->next_number_field) // Clear for next record
@@ -1460,7 +1463,7 @@ bool select_insert::send_eof()
thd->cuted_fields);
if (last_insert_id)
thd->insert_id(last_insert_id); // For update log
- ::send_ok(thd,info.copied,last_insert_id,buff);
+ ::send_ok(thd,info.copied+info.deleted,last_insert_id,buff);
mysql_update_log.write(thd,thd->query,thd->query_length);
return 0;
}
@@ -1510,7 +1513,7 @@ bool select_create::send_data(List<Item> &values)
unit->offset_limit_cnt--;
return 0;
}
- fill_record(field,values);
+ fill_record(field, values, 1);
if (thd->net.report_error ||write_record(table,&info))
return 1;
if (table->next_number_field) // Clear for next record
diff --git a/sql/sql_list.h b/sql/sql_list.h
index f4cca627515..27cdc117267 100644
--- a/sql/sql_list.h
+++ b/sql/sql_list.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+/* Copyright (C) 2000-2003 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index a68eada0025..359209af5ca 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -185,7 +185,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
else
{
unpack_filename(name,ex->file_name);
-#if !defined(__WIN__) && !defined(OS2)
+#if !defined(__WIN__) && !defined(OS2) && ! defined(__NETWARE__)
MY_STAT stat_info;
if (!my_stat(name,&stat_info,MYF(MY_WME)))
DBUG_RETURN(-1);
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 1d2449839d8..45c5ea4d520 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -213,7 +213,15 @@ static int check_user(THD *thd,enum_server_command command, const char *user,
thd->db=0;
thd->db_length=0;
USER_RESOURCES ur;
+ char tmp_passwd[SCRAMBL41_LENGTH];
DBUG_ENTER("check_user");
+
+ /*
+ Move password to temporary buffer as it may be stored in communication
+ buffer
+ */
+ strmake(tmp_passwd, passwd, sizeof(tmp_passwd));
+ passwd= tmp_passwd; // Use local copy
/* We shall avoid dupplicate user allocations here */
if (!thd->user && !(thd->user = my_strdup(user, MYF(0))))
@@ -222,7 +230,8 @@ static int check_user(THD *thd,enum_server_command command, const char *user,
DBUG_RETURN(1);
}
thd->master_access=acl_getroot(thd, thd->host, thd->ip, thd->user,
- passwd, thd->scramble, &thd->priv_user,
+ passwd, thd->scramble,
+ &thd->priv_user, &thd->priv_host,
(protocol_version == 9 ||
!(thd->client_capabilities &
CLIENT_LONG_PASSWORD)),
@@ -230,9 +239,9 @@ static int check_user(THD *thd,enum_server_command command, const char *user,
cur_priv_version,hint_user);
DBUG_PRINT("info",
- ("Capabilities: %d packet_length: %ld Host: '%s' User: '%s' Using password: %s Access: %u db: '%s'",
+ ("Capabilities: %d packet_length: %ld Host: '%s' Login user: '%s' Priv_user: '%s' Using password: %s Access: %u db: '%s'",
thd->client_capabilities, thd->max_client_packet_length,
- thd->host_or_ip, thd->priv_user,
+ thd->host_or_ip, thd->user, thd->priv_user,
had_password ? "yes": "no",
thd->master_access, thd->db ? thd->db : "*none*"));
@@ -307,6 +316,7 @@ static int check_user(THD *thd,enum_server_command command, const char *user,
DBUG_RETURN(error);
}
send_ok(thd); // Ready to handle questions
+ thd->password= test(passwd[0]); // Remember for error messages
DBUG_RETURN(0); // ok
}
@@ -582,7 +592,6 @@ check_connections(THD *thd)
DBUG_PRINT("info",("Host: %s",thd->host));
thd->host_or_ip= thd->host;
thd->ip= 0;
- thd->peer_port= 0;
bzero((char*) &thd->remote,sizeof(struct sockaddr));
}
/* Ensure that wrong hostnames doesn't cause buffer overflows */
@@ -751,7 +760,6 @@ check_connections(THD *thd)
}
else if (res)
return -1; // Error sent from check_user()
- thd->password=using_password;
return 0;
}
@@ -1551,7 +1559,8 @@ bool alloc_query(THD *thd, char *packet, ulong packet_length)
/* We must allocate some extra memory for query cache */
if (!(thd->query= (char*) thd->memdup_w_gap((gptr) (packet),
packet_length,
- thd->db_length+2)))
+ thd->db_length+2+
+ sizeof(ha_rows))))
return 1;
thd->query[packet_length]=0;
thd->query_length= packet_length;
@@ -1648,6 +1657,18 @@ mysql_execute_command(THD *thd)
#endif
)
DBUG_VOID_RETURN;
+
+ /*
+ When option readonly is set deny operations which change tables.
+ Except for the replication thread and the 'super' users.
+ */
+ if (opt_readonly &&
+ !(thd->slave_thread || (thd->master_access & SUPER_ACL)) &&
+ (uc_update_queries[lex->sql_command] > 0))
+ {
+ send_error(&thd->net,ER_CANT_UPDATE_WITH_READLOCK);
+ DBUG_VOID_RETURN;
+ }
statistic_increment(com_stat[lex->sql_command],&LOCK_status);
switch (lex->sql_command) {
@@ -1832,7 +1853,8 @@ mysql_execute_command(THD *thd)
}
case SQLCOM_SHOW_SLAVE_STAT:
{
- if (check_global_access(thd, SUPER_ACL))
+ /* Accept one of two privileges */
+ if (check_global_access(thd, SUPER_ACL | REPL_CLIENT_ACL))
goto error;
LOCK_ACTIVE_MI;
res = show_master_info(thd,active_mi);
@@ -1841,7 +1863,8 @@ mysql_execute_command(THD *thd)
}
case SQLCOM_SHOW_MASTER_STAT:
{
- if (check_global_access(thd, SUPER_ACL))
+ /* Accept one of two privileges */
+ if (check_global_access(thd, SUPER_ACL | REPL_CLIENT_ACL))
goto error;
res = show_binlog_info(thd);
break;
@@ -3058,12 +3081,21 @@ error:
/****************************************************************************
Get the user (global) and database privileges for all used tables
- Returns true (error) if we can't get the privileges and we don't use
- table/column grants.
- The idea of EXTRA_ACL is that one will be granted access to the table if
- one has the asked privilege on any column combination of the table; For
- example to be able to check a table one needs to have SELECT privilege on
- any column of the table.
+
+ NOTES
+ The idea of EXTRA_ACL is that one will be granted access to the table if
+ one has the asked privilege on any column combination of the table; For
+ example to be able to check a table one needs to have SELECT privilege on
+ any column of the table.
+
+ RETURN
+ 0 ok
+ 1 If we can't get the privileges and we don't use table/column grants.
+
+ save_priv In this we store global and db level grants for the table
+ Note that we don't store db level grants if the global grants
+ is enough to satisfy the request and the global grants contains
+ a SELECT grant.
****************************************************************************/
bool
@@ -3088,7 +3120,17 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
if ((thd->master_access & want_access) == want_access)
{
- *save_priv=thd->master_access;
+ /*
+ If we don't have a global SELECT privilege, we have to get the database
+ specific access rights to be able to handle queries of type
+ UPDATE t1 SET a=1 WHERE b > 0
+ */
+ db_access= thd->db_access;
+ if (!(thd->master_access & SELECT_ACL) &&
+ (db && (!thd->db || strcmp(db,thd->db))))
+ db_access=acl_get(thd->host, thd->ip, (char*) &thd->remote.sin_addr,
+ thd->priv_user, db); /* purecov: inspected */
+ *save_priv=thd->master_access | db_access;
DBUG_RETURN(FALSE);
}
if (((want_access & ~thd->master_access) & ~(DB_ACLS | EXTRA_ACL)) ||
@@ -3097,7 +3139,7 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
if (!no_errors)
net_printf(thd,ER_ACCESS_DENIED_ERROR,
thd->priv_user,
- thd->host_or_ip,
+ thd->priv_host,
thd->password ? ER(ER_YES) : ER(ER_NO));/* purecov: tested */
DBUG_RETURN(TRUE); /* purecov: tested */
}
@@ -3122,18 +3164,35 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
if (!no_errors)
net_printf(thd,ER_DBACCESS_DENIED_ERROR,
thd->priv_user,
- thd->host_or_ip,
+ thd->priv_host,
db ? db : thd->db ? thd->db : "unknown"); /* purecov: tested */
DBUG_RETURN(TRUE); /* purecov: tested */
}
-/* check for global access and give descriptive error message if it fails */
+/*
+ check for global access and give descriptive error message if it fails
+
+ SYNOPSIS
+ check_global_access()
+ thd Thread handler
+ want_access Use should have any of these global rights
+
+ WARNING
+ One gets access rigth if one has ANY of the rights in want_access
+ This is useful as one in most cases only need one global right,
+ but in some case we want to check if the user has SUPER or
+ REPL_CLIENT_ACL rights.
+
+ RETURN
+ 0 ok
+ 1 Access denied. In this case an error is sent to the client
+*/
bool check_global_access(THD *thd, ulong want_access)
{
char command[128];
- if ((thd->master_access & want_access) == want_access)
+ if ((thd->master_access & want_access))
return 0;
get_privilege_desc(command, sizeof(command), want_access);
net_printf(thd,ER_SPECIFIC_ACCESS_DENIED_ERROR,
@@ -3237,6 +3296,7 @@ static bool check_merge_table_access(THD *thd, char *db,
#define used_stack(A,B) (long) (B - A)
#endif
+#ifndef EMBEDDED_LIBRARY
bool check_stack_overrun(THD *thd,char *buf __attribute__((unused)))
{
long stack_used;
@@ -3250,6 +3310,7 @@ bool check_stack_overrun(THD *thd,char *buf __attribute__((unused)))
}
return 0;
}
+#endif /* EMBEDDED_LIBRARY */
#define MY_YACC_INIT 1000 // Start with big alloc
#define MY_YACC_MAX 32000 // Because of 'short'
@@ -3548,9 +3609,8 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
new_field->comment.str= (char*) comment->str_value.ptr();
new_field->comment.length=comment->str_value.length();
}
- if (length)
- if (!(new_field->length= (uint) atoi(length)))
- length=0; /* purecov: inspected */
+ if (length && !(new_field->length= (uint) atoi(length)))
+ length=0; /* purecov: inspected */
uint sign_len=type_modifier & UNSIGNED_FLAG ? 0 : 1;
if (new_field->length && new_field->decimals &&
@@ -3583,10 +3643,13 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
break;
case FIELD_TYPE_DECIMAL:
if (!length)
- new_field->length = 10; // Default length for DECIMAL
- new_field->length+=sign_len;
- if (new_field->decimals)
- new_field->length++;
+ new_field->length= 10; // Default length for DECIMAL
+ if (new_field->length < MAX_FIELD_WIDTH) // Skip wrong argument
+ {
+ new_field->length+=sign_len;
+ if (new_field->decimals)
+ new_field->length++;
+ }
break;
case FIELD_TYPE_STRING:
case FIELD_TYPE_VAR_STRING:
@@ -4011,6 +4074,24 @@ void add_join_on(TABLE_LIST *b,Item *expr)
}
+/*
+ Mark that we have a NATURAL JOIN between two tables
+
+ SYNOPSIS
+ add_join_natural()
+ a Table to do normal join with
+ b Do normal join with this table
+
+ IMPLEMENTATION
+ This function just marks that table b should be joined with a.
+ The function setup_cond() will create in b->on_expr a list
+ of equal condition between all fields of the same name.
+
+ SELECT * FROM t1 NATURAL LEFT JOIN t2
+ <=>
+ SELECT * FROM t1 LEFT JOIN t2 ON (t1.i=t2.i and t1.j=t2.j ... )
+*/
+
void add_join_natural(TABLE_LIST *a,TABLE_LIST *b)
{
b->natural_join=a;
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index a39541b0fc5..b8f6de30840 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -1079,6 +1079,9 @@ err:
}
send_eof(thd);
+ pthread_mutex_lock(&LOCK_thread_count);
+ thd->current_linfo = 0;
+ pthread_mutex_unlock(&LOCK_thread_count);
DBUG_RETURN(0);
}
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 85ebb9f207f..4456c631032 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -466,8 +466,17 @@ JOIN::optimize()
if (tables_list && tmp_table_param.sum_func_count && ! group_list)
{
int res;
+ /*
+ opt_sum_query() returns -1 if no rows match to the WHERE conditions,
+ or 1 if all items were resolved, or 0, or an error number HA_ERR_...
+ */
if ((res=opt_sum_query(tables_list, all_fields, conds)))
{
+ if (res > 1)
+ {
+ delete procedure;
+ DBUG_RETURN(-1);
+ }
if (res < 0)
{
zero_result_cause= "No matching min/max row";
@@ -610,7 +619,17 @@ JOIN::optimize()
select_distinct= 0;
no_order= !order;
if (all_order_fields_used)
+ {
+ if (order && skip_sort_order)
+ {
+ /*
+ Force MySQL to read the table in sorted order to get result in
+ ORDER BY order.
+ */
+ join.tmp_table_param.quick_group=0;
+ }
order=0;
+ }
group=1; // For end_write_group
}
else
@@ -2379,7 +2398,10 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
if (table->quick_keys & ((key_map) 1 << key))
records= (double) table->quick_rows[key];
else
- records= (double) s->records/rec; // quick_range couldn't use key!
+ {
+ /* quick_range couldn't use key! */
+ records= (double) s->records/rec;
+ }
}
else
{
@@ -3037,6 +3059,9 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
join->unit->select_limit_cnt)) < 0)
DBUG_RETURN(1); // Impossible range
sel->cond=orig_cond;
+ /* Fix for EXPLAIN */
+ if (sel->quick)
+ join->best_positions[i].records_read= sel->quick->records;
}
else
{
@@ -7249,7 +7274,8 @@ setup_group(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
while ((item=li++))
{
- if (item->type() != Item::SUM_FUNC_ITEM && !item->marker)
+ if (item->type() != Item::SUM_FUNC_ITEM && !item->marker &&
+ !item->const_item())
{
my_printf_error(ER_WRONG_FIELD_WITH_GROUP,
ER(ER_WRONG_FIELD_WITH_GROUP),
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 2b8982f2484..a77987e4806 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -923,7 +923,10 @@ mysqld_show_keys(THD *thd, TABLE_LIST *table_list)
protocol->store((const char*) pos, system_charset_info);
protocol->store(table->file->index_type(i), system_charset_info);
/* Comment */
- protocol->store("", system_charset_info);
+ if (!(table->keys_in_use & ((key_map) 1 << i)))
+ protocol->store("disabled",8, system_charset_info);
+ else
+ protocol->store("", 0, system_charset_info);
if (protocol->write())
DBUG_RETURN(1); /* purecov: inspected */
}
@@ -1591,6 +1594,7 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables,
case SHOW_RPL_STATUS:
end= strmov(buff, rpl_status_type[(int)rpl_status]);
break;
+#ifdef HAVE_REPLICATION
case SHOW_SLAVE_RUNNING:
{
LOCK_ACTIVE_MI;
@@ -1599,7 +1603,7 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables,
UNLOCK_ACTIVE_MI;
break;
}
-#endif /* EMBEDDED_LIBRARY */
+#endif /* HAVE_REPLICATION */
case SHOW_OPENTABLES:
end= int10_to_str((long) cached_tables(), buff, 10);
break;
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 3cac88d05b2..5ff0fea0627 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -23,6 +23,7 @@
#endif
#include <hash.h>
#include <myisam.h>
+#include <my_dir.h>
#ifdef __WIN__
#include <io.h>
@@ -716,6 +717,14 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
column->field_name);
DBUG_RETURN(-1);
}
+ /* for fulltext keys keyseg length is 1 for blobs (it's ignored in
+ ft code anyway, and 0 (set to column width later) for char's.
+ it has to be correct col width for char's, as char data are not
+ prefixed with length (unlike blobs, where ft code takes data length
+ from a data prefix, ignoring column->length).
+ */
+ if (key->type == Key::FULLTEXT)
+ column->length=test(f_is_blob(sql_field->pack_flag));
if (f_is_blob(sql_field->pack_flag))
{
if (!(file->table_flags() & HA_BLOB_KEY))
@@ -726,15 +735,10 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
}
if (!column->length)
{
- if (key->type == Key::FULLTEXT)
- column->length=1; /* ft-code ignores it anyway :-) */
- else
- {
- my_printf_error(ER_BLOB_KEY_WITHOUT_LENGTH,
- ER(ER_BLOB_KEY_WITHOUT_LENGTH),MYF(0),
- column->field_name);
- DBUG_RETURN(-1);
- }
+ my_printf_error(ER_BLOB_KEY_WITHOUT_LENGTH,
+ ER(ER_BLOB_KEY_WITHOUT_LENGTH),MYF(0),
+ column->field_name);
+ DBUG_RETURN(-1);
}
}
if (key->type == Key::SPATIAL)
@@ -752,8 +756,9 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
{
if (key->type == Key::PRIMARY)
{
- my_error(ER_PRIMARY_CANT_HAVE_NULL, MYF(0));
- DBUG_RETURN(-1);
+ /* Implicitly set primary key fields to NOT NULL for ISO conf. */
+ sql_field->flags|= NOT_NULL_FLAG;
+ sql_field->pack_flag&= ~FIELDFLAG_MAYBE_NULL;
}
if (!(file->table_flags() & HA_NULL_KEY))
{
@@ -1081,12 +1086,9 @@ mysql_rename_table(enum db_type base,
Win32 clients must also have a WRITE LOCK on the table !
*/
-bool close_cached_table(THD *thd,TABLE *table)
+static void safe_remove_from_cache(THD *thd,TABLE *table)
{
- bool result=0;
- DBUG_ENTER("close_cached_table");
- safe_mutex_assert_owner(&LOCK_open);
-
+ DBUG_ENTER("safe_remove_from_cache");
if (table)
{
DBUG_PRINT("enter",("table: %s", table->real_name));
@@ -1109,16 +1111,29 @@ bool close_cached_table(THD *thd,TABLE *table)
#endif
/* When lock on LOCK_open is freed other threads can continue */
pthread_cond_broadcast(&COND_refresh);
+ }
+ DBUG_VOID_RETURN;
+}
+
+bool close_cached_table(THD *thd,TABLE *table)
+{
+ DBUG_ENTER("close_cached_table");
+ safe_mutex_assert_owner(&LOCK_open);
+
+ if (table)
+ {
+ safe_remove_from_cache(thd,table);
/* Close lock if this is not got with LOCK TABLES */
if (thd->lock)
{
- mysql_unlock_tables(thd, thd->lock); thd->lock=0; // Start locked threads
+ mysql_unlock_tables(thd, thd->lock);
+ thd->lock=0; // Start locked threads
}
/* Close all copies of 'table'. This also frees all LOCK TABLES lock */
thd->open_tables=unlink_open_table(thd,thd->open_tables,table);
}
- DBUG_RETURN(result);
+ DBUG_RETURN(0);
}
static int send_check_errmsg(THD *thd, TABLE_LIST* table,
@@ -1199,69 +1214,105 @@ static int prepare_for_restore(THD* thd, TABLE_LIST* table,
}
-static int prepare_for_repair(THD* thd, TABLE_LIST* table,
+static int prepare_for_repair(THD* thd, TABLE_LIST *table_list,
HA_CHECK_OPT *check_opt)
{
+ int error= 0;
+ TABLE tmp_table, *table;
DBUG_ENTER("prepare_for_repair");
if (!(check_opt->sql_flags & TT_USEFRM))
- {
DBUG_RETURN(0);
- }
- else
+
+ if (!(table= table_list->table)) /* if open_ltable failed */
{
+ char name[FN_REFLEN];
+ strxmov(name, mysql_data_home, "/", table_list->db, "/",
+ table_list->real_name, NullS);
+ if (openfrm(name, "", 0, 0, 0, &tmp_table))
+ DBUG_RETURN(0); // Can't open frm file
+ table= &tmp_table;
+ }
- char from[FN_REFLEN],tmp[FN_REFLEN];
- char* db = thd->db ? thd->db : table->db;
+ /*
+ User gave us USE_FRM which means that the header in the index file is
+ trashed.
+ In this case we will try to fix the table the following way:
+ - Rename the data file to a temporary name
+ - Truncate the table
+ - Replace the new data file with the old one
+ - Run a normal repair using the new index file and the old data file
+ */
- sprintf(from, "%s/%s/%s", mysql_real_data_home, db, table->real_name);
- fn_format(from, from, "", MI_NAME_DEXT, 4);
- sprintf(tmp,"%s-%lx_%lx", from, current_pid, thd->thread_id);
+ char from[FN_REFLEN],tmp[FN_REFLEN+32];
+ const char **ext= table->file->bas_ext();
+ MY_STAT stat_info;
- pthread_mutex_lock(&LOCK_open);
- close_cached_table(thd,table->table);
- pthread_mutex_unlock(&LOCK_open);
+ /*
+ Check if this is a table type that stores index and data separately,
+ like ISAM or MyISAM
+ */
+ if (!ext[0] || !ext[1])
+ goto end; // No data file
- if (lock_and_wait_for_table_name(thd,table))
- DBUG_RETURN(-1);
+ strxmov(from, table->path, ext[1], NullS); // Name of data file
+ if (!my_stat(from, &stat_info, MYF(0)))
+ goto end; // Can't use USE_FRM flag
- if (my_rename(from, tmp, MYF(MY_WME)))
- {
- pthread_mutex_lock(&LOCK_open);
- unlock_table_name(thd, table);
- pthread_mutex_unlock(&LOCK_open);
- DBUG_RETURN(send_check_errmsg(thd, table, "repair",
- "Failed renaming .MYD file"));
- }
- if (mysql_truncate(thd, table, 1))
- {
- pthread_mutex_lock(&LOCK_open);
- unlock_table_name(thd, table);
- pthread_mutex_unlock(&LOCK_open);
- DBUG_RETURN(send_check_errmsg(thd, table, "repair",
- "Failed generating table from .frm file"));
- }
- if (my_rename(tmp, from, MYF(MY_WME)))
- {
- pthread_mutex_lock(&LOCK_open);
- unlock_table_name(thd, table);
- pthread_mutex_unlock(&LOCK_open);
- DBUG_RETURN(send_check_errmsg(thd, table, "repair",
- "Failed restoring .MYD file"));
- }
+ sprintf(tmp,"%s-%lx_%lx", from, current_pid, thd->thread_id);
+
+ pthread_mutex_lock(&LOCK_open);
+ close_cached_table(thd,table_list->table);
+ pthread_mutex_unlock(&LOCK_open);
+
+ if (lock_and_wait_for_table_name(thd,table_list))
+ {
+ error= -1;
+ goto end;
+ }
+ if (my_rename(from, tmp, MYF(MY_WME)))
+ {
+ pthread_mutex_lock(&LOCK_open);
+ unlock_table_name(thd, table_list);
+ pthread_mutex_unlock(&LOCK_open);
+ error= send_check_errmsg(thd, table_list, "repair",
+ "Failed renaming data file");
+ goto end;
+ }
+ if (mysql_truncate(thd, table_list, 1))
+ {
+ pthread_mutex_lock(&LOCK_open);
+ unlock_table_name(thd, table_list);
+ pthread_mutex_unlock(&LOCK_open);
+ error= send_check_errmsg(thd, table_list, "repair",
+ "Failed generating table from .frm file");
+ goto end;
+ }
+ if (my_rename(tmp, from, MYF(MY_WME)))
+ {
+ pthread_mutex_lock(&LOCK_open);
+ unlock_table_name(thd, table_list);
+ pthread_mutex_unlock(&LOCK_open);
+ error= send_check_errmsg(thd, table_list, "repair",
+ "Failed restoring .MYD file");
+ goto end;
}
/*
Now we should be able to open the partially repaired table
to finish the repair in the handler later on.
*/
- if (!(table->table = reopen_name_locked_table(thd, table)))
+ if (!(table_list->table = reopen_name_locked_table(thd, table_list)))
{
pthread_mutex_lock(&LOCK_open);
- unlock_table_name(thd, table);
+ unlock_table_name(thd, table_list);
pthread_mutex_unlock(&LOCK_open);
}
- DBUG_RETURN(0);
+
+end:
+ if (table == &tmp_table)
+ closefrm(table); // Free allocated memory
+ DBUG_RETURN(error);
}
@@ -1759,9 +1810,11 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
case LEAVE_AS_IS:
break;
case ENABLE:
- error=table->file->activate_all_index(thd);
+ safe_remove_from_cache(thd,table);
+ error= table->file->activate_all_index(thd);
break;
case DISABLE:
+ safe_remove_from_cache(thd,table);
table->file->deactivate_non_unique_index(HA_POS_ERROR);
break;
}
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index fe4ca49da14..1d0f37f0042 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -76,7 +76,7 @@ bool select_union::send_data(List<Item> &values)
unit->offset_limit_cnt--;
return 0;
}
- fill_record(table->field,values);
+ fill_record(table->field, values, 1);
if (thd->net.report_error || write_record(table,&info))
{
if (thd->net.last_errno == ER_RECORD_FILE_FULL)
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 7c5983a0362..1526908f025 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -62,33 +62,46 @@ int mysql_update(THD *thd,
int error=0;
uint used_index, want_privilege;
ulong query_id=thd->query_id, timestamp_query_id;
+ ha_rows updated, found;
key_map old_used_keys;
TABLE *table;
SQL_SELECT *select;
READ_RECORD info;
- TABLE_LIST *update_table_list= (TABLE_LIST*)
- thd->lex.select_lex.table_list.first;
+ TABLE_LIST *update_table_list= ((TABLE_LIST*)
+ thd->lex.select_lex.table_list.first);
+ TABLE_LIST tables;
+ List<Item> all_fields;
DBUG_ENTER("mysql_update");
+
LINT_INIT(used_index);
LINT_INIT(timestamp_query_id);
if ((open_and_lock_tables(thd, table_list)))
DBUG_RETURN(-1);
+ thd->proc_info="init";
fix_tables_pointers(thd->lex.all_selects_list);
table= table_list->table;
-
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
- thd->proc_info="init";
/* Calculate "table->used_keys" based on the WHERE */
table->used_keys=table->keys_in_use;
table->quick_keys=0;
want_privilege=table->grant.want_privilege;
table->grant.want_privilege=(SELECT_ACL & ~table->grant.privilege);
- if (setup_tables(update_table_list) ||
- setup_conds(thd,update_table_list,&conds)
- || setup_ftfuncs(&thd->lex.select_lex))
+
+ bzero((char*) &tables,sizeof(tables)); // For ORDER BY
+ tables.table= table;
+
+ if (setup_tables(update_table_list) ||
+ setup_conds(thd,update_table_list,&conds) ||
+ setup_ref_array(thd, &thd->lex.select_lex.ref_pointer_array,
+ order_num) ||
+ setup_order(thd, thd->lex.select_lex.ref_pointer_array,
+ &tables, fields, all_fields, order) ||
+ setup_ftfuncs(&thd->lex.select_lex))
DBUG_RETURN(-1); /* purecov: inspected */
+
+ /* Check that we are not using table that we are updating in a sub select */
if (find_real_table_in_list(table_list->next,
table_list->db, table_list->real_name))
{
@@ -96,8 +109,7 @@ int mysql_update(THD *thd,
DBUG_RETURN(-1);
}
- old_used_keys=table->used_keys; // Keys used in WHERE
-
+ old_used_keys= table->used_keys; // Keys used in WHERE
/*
Change the query_id for the timestamp column so that we can
check if this is modified directly
@@ -151,10 +163,9 @@ int mysql_update(THD *thd,
thd->lex.select_lex.options|=QUERY_NO_INDEX_USED;
if (safe_update && !using_limit)
{
- delete select;
- free_underlaid_joins(thd, &thd->lex.select_lex);
- send_error(thd,ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE);
- DBUG_RETURN(1);
+ my_message(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE,
+ ER(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE), MYF(0));
+ goto err;
}
}
init_ftfuncs(thd, &thd->lex.select_lex, 1);
@@ -175,14 +186,6 @@ int mysql_update(THD *thd,
matching rows before updating the table!
*/
table->file->extra(HA_EXTRA_DONT_USE_CURSOR_TO_UPDATE);
- IO_CACHE tempfile;
- if (open_cached_file(&tempfile, mysql_tmpdir,TEMP_PREFIX,
- DISK_BUFFER_SIZE, MYF(MY_WME)))
- {
- delete select; /* purecov: inspected */
- free_underlaid_joins(thd, &thd->lex.select_lex);
- DBUG_RETURN(-1);
- }
if (old_used_keys & ((key_map) 1 << used_index))
{
table->key_read=1;
@@ -191,94 +194,102 @@ int mysql_update(THD *thd,
if (order)
{
+ /*
+ Doing an ORDER BY; Let filesort find and sort the rows we are going
+ to update
+ */
uint length;
SORT_FIELD *sortorder;
- TABLE_LIST tables;
List<Item> fields;
- List<Item> all_fields;
ha_rows examined_rows;
- bzero((char*) &tables,sizeof(tables));
- tables.table = table;
-
table->sort.io_cache = (IO_CACHE *) my_malloc(sizeof(IO_CACHE),
- MYF(MY_FAE | MY_ZEROFILL));
- if (setup_ref_array(thd, &thd->lex.select_lex.ref_pointer_array,
- order_num)||
- setup_order(thd, thd->lex.select_lex.ref_pointer_array,
- &tables, fields, all_fields, order) ||
- !(sortorder=make_unireg_sortorder(order, &length)) ||
+ MYF(MY_FAE | MY_ZEROFILL));
+ if (!(sortorder=make_unireg_sortorder(order, &length)) ||
(table->sort.found_records = filesort(thd, table, sortorder, length,
- (SQL_SELECT *) 0,
- HA_POS_ERROR, &examined_rows))
+ select, 0L, limit,
+ &examined_rows))
== HA_POS_ERROR)
{
- delete select;
- free_underlaid_joins(thd, &thd->lex.select_lex);
- DBUG_RETURN(-1);
+ free_io_cache(table);
+ goto err;
}
+ /*
+ Filesort has already found and selected the rows we want to update,
+ so we don't need the where clause
+ */
+ delete select;
+ select= 0;
}
+ else
+ {
+ /*
+ We are doing a search on a key that is updated. In this case
+ we go trough the matching rows, save a pointer to them and
+ update these in a separate loop based on the pointer.
+ */
+
+ IO_CACHE tempfile;
+ if (open_cached_file(&tempfile, mysql_tmpdir,TEMP_PREFIX,
+ DISK_BUFFER_SIZE, MYF(MY_WME)))
+ goto err;
- init_read_record(&info,thd,table,select,0,1);
- thd->proc_info="Searching rows for update";
+ init_read_record(&info,thd,table,select,0,1);
+ thd->proc_info="Searching rows for update";
+ uint tmp_limit= limit;
- while (!(error=info.read_record(&info)) && !thd->killed)
- {
- if (!(select && select->skipp_record()))
+ while (!(error=info.read_record(&info)) && !thd->killed)
{
- table->file->position(table->record[0]);
- if (my_b_write(&tempfile,table->file->ref,
- table->file->ref_length))
+ if (!(select && select->skipp_record()))
{
- error=1; /* purecov: inspected */
- break; /* purecov: inspected */
+ table->file->position(table->record[0]);
+ if (my_b_write(&tempfile,table->file->ref,
+ table->file->ref_length))
+ {
+ error=1; /* purecov: inspected */
+ break; /* purecov: inspected */
+ }
+ if (!--limit && using_limit)
+ {
+ error= -1;
+ break;
+ }
}
}
+ limit= tmp_limit;
+ end_read_record(&info);
+ /* Change select to use tempfile */
+ if (select)
+ {
+ delete select->quick;
+ if (select->free_cond)
+ delete select->cond;
+ select->quick=0;
+ select->cond=0;
+ }
else
{
- if (!(test_flags & 512)) /* For debugging */
- {
- DBUG_DUMP("record",(char*) table->record[0],table->reclength);
- }
+ select= new SQL_SELECT;
+ select->head=table;
}
+ if (reinit_io_cache(&tempfile,READ_CACHE,0L,0,0))
+ error=1; /* purecov: inspected */
+ select->file=tempfile; // Read row ptrs from this file
+ if (error >= 0)
+ goto err;
}
- end_read_record(&info);
-
if (table->key_read)
{
table->key_read=0;
table->file->extra(HA_EXTRA_NO_KEYREAD);
}
- /* Change select to use tempfile */
- if (select)
- {
- delete select->quick;
- if (select->free_cond)
- delete select->cond;
- select->quick=0;
- select->cond=0;
- }
- else
- {
- select= new SQL_SELECT;
- select->head=table;
- }
- if (reinit_io_cache(&tempfile,READ_CACHE,0L,0,0))
- error=1; /* purecov: inspected */
- select->file=tempfile; // Read row ptrs from this file
- if (error >= 0)
- {
- delete select;
- free_underlaid_joins(thd, &thd->lex.select_lex);
- DBUG_RETURN(-1);
- }
}
if (handle_duplicates == DUP_IGNORE)
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
init_read_record(&info,thd,table,select,0,1);
- ha_rows updated=0L,found=0L;
+ updated= found= 0;
thd->count_cuted_fields=1; /* calc cuted fields */
thd->cuted_fields=0L;
thd->proc_info="Updating";
@@ -289,7 +300,7 @@ int mysql_update(THD *thd,
if (!(select && select->skipp_record()))
{
store_record(table,record[1]);
- if (fill_record(fields,values) || thd->net.report_error)
+ if (fill_record(fields,values, 0) || thd->net.report_error)
break; /* purecov: inspected */
found++;
if (compare_record(table, query_id))
@@ -298,11 +309,6 @@ int mysql_update(THD *thd,
(byte*) table->record[0])))
{
updated++;
- if (!--limit && using_limit)
- {
- error= -1;
- break;
- }
}
else if (handle_duplicates != DUP_IGNORE ||
error != HA_ERR_FOUND_DUPP_KEY)
@@ -312,11 +318,17 @@ int mysql_update(THD *thd,
break;
}
}
+ if (!--limit && using_limit)
+ {
+ error= -1; // Simulate end of file
+ break;
+ }
}
else
table->file->unlock_row();
}
end_read_record(&info);
+ free_io_cache(table); // If ORDER BY
thd->proc_info="end";
VOID(table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY));
transactional_table= table->file->has_transactions();
@@ -370,8 +382,17 @@ int mysql_update(THD *thd,
}
thd->count_cuted_fields=0; /* calc cuted fields */
free_io_cache(table);
-
DBUG_RETURN(0);
+
+err:
+ delete select;
+ free_underlaid_joins(thd, &thd->lex.select_lex);
+ if (table->key_read)
+ {
+ table->key_read=0;
+ table->file->extra(HA_EXTRA_NO_KEYREAD);
+ }
+ DBUG_RETURN(-1);
}
@@ -508,6 +529,8 @@ int multi_update::prepare(List<Item> &not_used_values, SELECT_LEX_UNIT *unit)
table->pos_in_table_list= tl;
}
}
+
+
table_count= update.elements;
update_tables= (TABLE_LIST*) update.first;
@@ -732,7 +755,7 @@ bool multi_update::send_data(List<Item> &not_used_values)
{
table->status|= STATUS_UPDATED;
store_record(table,record[1]);
- if (fill_record(*fields_for_table[offset], *values_for_table[offset]))
+ if (fill_record(*fields_for_table[offset], *values_for_table[offset]), 0)
DBUG_RETURN(1);
found++;
if (compare_record(table, thd->query_id))
@@ -760,7 +783,7 @@ bool multi_update::send_data(List<Item> &not_used_values)
{
int error;
TABLE *tmp_table= tmp_tables[offset];
- fill_record(tmp_table->field+1, *values_for_table[offset]);
+ fill_record(tmp_table->field+1, *values_for_table[offset], 1);
found++;
/* Store pointer to row */
memcpy((char*) tmp_table->field[0]->ptr,
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index e3b2c738949..659cddb1090 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -555,11 +555,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%left '^'
%right NOT
%right BINARY COLLATE_SYM
-/* These don't actually affect the way the query is really evaluated, but
- they silence a few warnings for shift/reduce conflicts. */
-%left ','
-%left STRAIGHT_JOIN JOIN_SYM
-%nonassoc CROSS INNER_SYM NATURAL LEFT RIGHT
%type <lex_str>
IDENT TEXT_STRING REAL_NUM FLOAT_NUM NUM LONG_NUM HEX_NUM LEX_HOSTNAME
@@ -1933,7 +1928,10 @@ select_option:
Select->options|= OPTION_FOUND_ROWS;
}
| SQL_NO_CACHE_SYM { Lex->uncacheable(); }
- | SQL_CACHE_SYM { Select->options|= OPTION_TO_QUERY_CACHE; }
+ | SQL_CACHE_SYM
+ {
+ Lex->select_lex.options|= OPTION_TO_QUERY_CACHE;
+ }
| ALL {}
;
@@ -2581,8 +2579,12 @@ sum_expr:
{ $$=new Item_sum_count(new Item_int((int32) 0L,1)); }
| COUNT_SYM '(' in_sum_expr ')'
{ $$=new Item_sum_count($3); }
- | COUNT_SYM '(' DISTINCT expr_list ')'
- { $$=new Item_sum_count_distinct(* $4); }
+ | COUNT_SYM '(' DISTINCT
+ { Select->in_sum_expr++; }
+ expr_list
+ { Select->in_sum_expr--; }
+ ')'
+ { $$=new Item_sum_count_distinct(* $5); }
| GROUP_UNIQUE_USERS '(' text_literal ',' NUM ',' NUM ',' in_sum_expr ')'
{ $$= new Item_sum_unique_users($3,atoi($5.str),atoi($7.str),$9); }
| MIN_SYM '(' in_sum_expr ')'
@@ -2711,7 +2713,7 @@ join_table_list:
| join_table_list ',' join_table_list { $$=$3; }
| join_table_list normal_join join_table_list { $$=$3; }
| join_table_list STRAIGHT_JOIN join_table_list
- { $$=$3 ; $$->straight=1; }
+ { $$=$3 ; $1->next->straight=1; }
| join_table_list normal_join join_table_list ON expr
{ add_join_on($3,$5); $$=$3; }
| join_table_list normal_join join_table_list
@@ -2735,9 +2737,13 @@ join_table_list:
USING '(' using_list ')'
{ add_join_on($5,$9); $5->outer_join|=JOIN_TYPE_LEFT; $$=$5; }
| join_table_list NATURAL LEFT opt_outer JOIN_SYM join_table_list
- { add_join_natural($1,$6); $6->outer_join|=JOIN_TYPE_LEFT; $$=$6; }
+ {
+ add_join_natural($1,$1->next);
+ $1->next->outer_join|=JOIN_TYPE_LEFT;
+ $$=$6;
+ }
| join_table_list RIGHT opt_outer JOIN_SYM join_table_list ON expr
- { add_join_on($1,$7); $1->outer_join|=JOIN_TYPE_RIGHT; $$=$1; }
+ { add_join_on($1,$7); $1->outer_join|=JOIN_TYPE_RIGHT; $$=$5; }
| join_table_list RIGHT opt_outer JOIN_SYM join_table_list
{
SELECT_LEX *sel= Select->select_lex();
@@ -2745,11 +2751,15 @@ join_table_list:
sel->db2=$5->db; sel->table2=$5->alias;
}
USING '(' using_list ')'
- { add_join_on($1,$9); $1->outer_join|=JOIN_TYPE_RIGHT; $$=$1; }
+ { add_join_on($1,$9); $1->outer_join|=JOIN_TYPE_RIGHT; $$=$5; }
| join_table_list NATURAL RIGHT opt_outer JOIN_SYM join_table_list
- { add_join_natural($6,$1); $1->outer_join|=JOIN_TYPE_RIGHT; $$=$1; }
+ {
+ add_join_natural($1->next,$1);
+ $1->outer_join|=JOIN_TYPE_RIGHT;
+ $$=$6;
+ }
| join_table_list NATURAL JOIN_SYM join_table_list
- { add_join_natural($1,$4); $$=$4; };
+ { add_join_natural($1,$1->next); $$=$4; };
normal_join:
JOIN_SYM {}
@@ -3076,7 +3086,7 @@ delete_limit_clause:
ULONG_NUM:
NUM { $$= strtoul($1.str,NULL,10); }
- | LONG_NUM { $$= (ulonglong) strtoll($1.str,NULL,10); }
+ | LONG_NUM { $$= (ulong) strtoll($1.str,NULL,10); }
| ULONGLONG_NUM { $$= (ulong) strtoull($1.str,NULL,10); }
| REAL_NUM { $$= strtoul($1.str,NULL,10); }
| FLOAT_NUM { $$= strtoul($1.str,NULL,10); };
diff --git a/sql/time.cc b/sql/time.cc
index 94f9cb2e5e8..eba664a690d 100644
--- a/sql/time.cc
+++ b/sql/time.cc
@@ -251,145 +251,6 @@ void get_date_from_daynr(long daynr,uint *ret_year,uint *ret_month,
DBUG_VOID_RETURN;
}
-/* find date from string and put it in vektor
- Input: pos = "YYMMDD" OR "YYYYMMDD" in any order or
- "xxxxx YYxxxMMxxxDD xxxx" where xxx is anything exept
- a number. Month or day mustn't exeed 2 digits, year may be 4 digits.
-*/
-
-
-#ifdef NOT_NEEDED
-
-void find_date(string pos,uint *vek,uint flag)
-{
- uint length,value;
- string start;
- DBUG_ENTER("find_date");
- DBUG_PRINT("enter",("pos: '%s' flag: %d",pos,flag));
-
- bzero((char*) vek,sizeof(int)*4);
- while (*pos && !my_isdigit(my_charset_latin1,*pos))
- pos++;
- length=(uint) strlen(pos);
- for (uint i=0 ; i< 3; i++)
- {
- start=pos; value=0;
- while (my_isdigit(my_charset_latin1,pos[0]) &&
- ((pos-start) < 2 || ((pos-start) < 4 && length >= 8 &&
- !(flag & 3))))
- {
- value=value*10 + (uint) (uchar) (*pos - '0');
- pos++;
- }
- vek[flag & 3]=value; flag>>=2;
- while (*pos && (my_ispunct(my_charset_latin1,*pos) ||
- my_isspace(my_charset_latin1,*pos)))
- pos++;
- }
- DBUG_PRINT("exit",("year: %d month: %d day: %d",vek[0],vek[1],vek[2]));
- DBUG_VOID_RETURN;
-} /* find_date */
-
-
- /* Outputs YYMMDD if input year < 100 or YYYYMMDD else */
-
-static long calc_daynr_from_week(uint year,uint week,uint day)
-{
- long daynr;
- int weekday;
-
- daynr=calc_daynr(year,1,1);
- if ((weekday= calc_weekday(daynr,0)) >= 3)
- daynr+= (7-weekday);
- else
- daynr-=weekday;
-
- return (daynr+week*7+day-8);
-}
-
-void convert_week_to_date(string date,uint flag,uint *res_length)
-{
- string format;
- uint year,vek[4];
-
- find_date(date,vek,(uint) (1*4+2*16)); /* YY-WW-DD */
- year=vek[0];
-
- get_date_from_daynr(calc_daynr_from_week(vek[0],vek[1],vek[2]),
- &vek[0],&vek[1],&vek[2]);
- *res_length=8;
- format="%04d%02d%02d";
- if (year < 100)
- {
- vek[0]= vek[0]%100;
- *res_length=6;
- format="%02d%02d%02d";
- }
- sprintf(date,format,vek[flag & 3],vek[(flag >> 2) & 3],
- vek[(flag >> 4) & 3]);
- return;
-}
-
- /* returns YYWWDD or YYYYWWDD according to input year */
- /* flag only reflects format of input date */
-
-void convert_date_to_week(string date,uint flag,uint *res_length)
-{
- uint vek[4],weekday,days,year,week,day;
- long daynr,first_daynr;
- char buff[256],*format;
-
- if (! date[0])
- {
- get_date(buff,0,0L); /* Use current date */
- find_date(buff+2,vek,(uint) (1*4+2*16)); /* YY-MM-DD */
- }
- else
- find_date(date,vek,flag);
-
- year= vek[0];
- daynr= calc_daynr(year,vek[1],vek[2]);
- first_daynr=calc_daynr(year,1,1);
-
- /* Caculate year and first daynr of year */
- if (vek[1] == 1 && (weekday=calc_weekday(first_daynr,0)) >= 3 &&
- vek[2] <= 7-weekday)
- {
- if (!year--)
- year=99;
- first_daynr=first_daynr-calc_days_in_year(year);
- }
- else if (vek[1] == 12 &&
- (weekday=calc_weekday(first_daynr+calc_days_in_year(year)),0) < 3 &&
- vek[2] > 31-weekday)
- {
- first_daynr=first_daynr+calc_days_in_year(year);
- if (year++ == 99)
- year=0;
- }
-
- /* Calulate daynr of first day of week 1 */
- if ((weekday= calc_weekday(first_daynr,0)) >= 3)
- first_daynr+= (7-weekday);
- else
- first_daynr-=weekday;
-
- days=(int) (daynr-first_daynr);
- week=days/7+1 ; day=calc_weekday(daynr,0)+1;
-
- *res_length=8;
- format="%04d%02d%02d";
- if (year < 100)
- {
- *res_length=6;
- format="%02d%02d%02d";
- }
- sprintf(date,format,year,week,day);
- return;
-}
-
-#endif
-
/* Functions to handle periods */
ulong convert_period_to_month(ulong period)
@@ -516,14 +377,14 @@ str_to_TIME(const char *str, uint length, TIME *l_time,bool fuzzy_date)
else
date[6]=0;
- if (year_length == 2)
+ if (year_length == 2 && i >=2 && (date[1] || date[2]))
date[0]+= (date[0] < YY_PART_YEAR ? 2000 : 1900);
number_of_fields=i;
while (i < 6)
date[i++]=0;
if (number_of_fields < 3 || date[1] > 12 ||
date[2] > 31 || date[3] > 23 || date[4] > 59 || date[5] > 59 ||
- !fuzzy_date && (date[1] == 0 || date[2] == 0))
+ (!fuzzy_date && (date[1] == 0 || date[2] == 0)))
{
/* Only give warning for a zero date if there is some garbage after */
if (!not_zero_date) // If zero date
diff --git a/sql/unireg.h b/sql/unireg.h
index ff942f6748a..b3ea6e3fa21 100644
--- a/sql/unireg.h
+++ b/sql/unireg.h
@@ -55,6 +55,7 @@
#else
#define MAX_REFLENGTH 4 /* Max length for record ref */
#endif
+#define MAX_HOSTNAME 61 /* len+1 in mysql.user */
#define MAX_FIELD_WIDTH 256 /* Max column width +1 */
#define MAX_TABLES (sizeof(table_map)*8-2) /* Max tables in join */