summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <sasha@mysql.sashanet.com>2001-05-10 15:06:35 -0600
committerunknown <sasha@mysql.sashanet.com>2001-05-10 15:06:35 -0600
commit9192600eb7c52f2675a67548849409dec2364165 (patch)
tree32fd0eb2c34334b7806726cf2dc9f8a893ea6fc8 /sql
parent9afb49f53cb7b8da7519f45f588a78b559013de3 (diff)
parentb59b5f4b6ec6bd5b0eb8cee832b6d4f51fa646fc (diff)
downloadmariadb-git-9192600eb7c52f2675a67548849409dec2364165.tar.gz
Merged with 3.23, needs further fix-up
BitKeeper/etc/ignore: auto-union BitKeeper/etc/logging_ok: auto-union acconfig.h: Auto merged acinclude.m4: Auto merged include/myisam.h: Auto merged mysql-test/mysql-test-run.sh: Auto merged BitKeeper/deleted/.del-ib_config.h.in~9e57db8504e55b7: Auto merged BitKeeper/deleted/.del-ib_config.h~7539e26ffc614439: Auto merged client/mysqltest.c: Auto merged sql/lex.h: Auto merged sql/sql_base.cc: Auto merged sql/sql_parse.cc: Auto merged sql/sql_select.h: Auto merged sql/sql_show.cc: Auto merged sql/table.h: Auto merged sql/mysql_priv.h: Auto merged sql/sql_class.h: Auto merged Docs/manual.texi: merged client/errmsg.c: merged configure.in: merged sql/mysqld.cc: merged sql/sql_select.cc: merged, needs manual fixing sql/sql_yacc.yy: merged, needs manual fixing
Diffstat (limited to 'sql')
-rw-r--r--sql/filesort.cc10
-rw-r--r--sql/ha_berkeley.cc27
-rw-r--r--sql/ha_berkeley.h1
-rw-r--r--sql/ha_innobase.cc12
-rw-r--r--sql/ha_innobase.h4
-rw-r--r--sql/ha_myisam.cc22
-rw-r--r--sql/handler.h3
-rw-r--r--sql/item_strfunc.cc10
-rw-r--r--sql/lex.h1
-rw-r--r--sql/lock.cc4
-rw-r--r--sql/log.cc55
-rw-r--r--sql/log_event.cc34
-rw-r--r--sql/log_event.h14
-rw-r--r--sql/mini_client.cc10
-rw-r--r--sql/mysql_priv.h3
-rw-r--r--sql/mysqlbinlog.cc67
-rw-r--r--sql/mysqld.cc291
-rw-r--r--sql/opt_range.cc4
-rw-r--r--sql/share/english/errmsg.txt2
-rw-r--r--sql/slave.cc16
-rw-r--r--sql/sql_base.cc35
-rw-r--r--sql/sql_class.h5
-rw-r--r--sql/sql_parse.cc3
-rw-r--r--sql/sql_repl.cc10
-rw-r--r--sql/sql_repl.h3
-rw-r--r--sql/sql_select.cc144
-rw-r--r--sql/sql_select.h1
-rw-r--r--sql/sql_show.cc5
-rw-r--r--sql/sql_table.cc39
-rw-r--r--sql/sql_yacc.yy364
-rw-r--r--sql/table.h5
31 files changed, 778 insertions, 426 deletions
diff --git a/sql/filesort.cc b/sql/filesort.cc
index e116e2b68e6..610fe2e966f 100644
--- a/sql/filesort.cc
+++ b/sql/filesort.cc
@@ -49,7 +49,7 @@ typedef struct st_sort_param {
uint sort_length; /* Length of sortarg */
uint keys; /* Max antal nycklar / buffert */
uint ref_length; /* Length of record ref. */
- ha_rows max_rows;
+ ha_rows max_rows,examined_rows;
TABLE *sort_form; /* For quicker make_sortkey */
SORT_FIELD *local_sortorder;
SORT_FIELD *end;
@@ -91,7 +91,8 @@ static uint sortlength(SORT_FIELD *sortorder,uint length);
open a new file is opened */
ha_rows filesort(TABLE **table, SORT_FIELD *sortorder, uint s_length,
- SQL_SELECT *select, ha_rows special, ha_rows max_rows)
+ SQL_SELECT *select, ha_rows special, ha_rows max_rows,
+ ha_rows *examined_rows)
{
int error;
uint memavl,old_memavl,maxbuffer,skr;
@@ -113,6 +114,7 @@ ha_rows filesort(TABLE **table, SORT_FIELD *sortorder, uint s_length,
param.ref_length= table[0]->file->ref_length;
param.sort_length=sortlength(sortorder,s_length)+ param.ref_length;
param.max_rows= max_rows;
+ param.examined_rows=0;
if (select && select->quick)
{
@@ -259,7 +261,7 @@ ha_rows filesort(TABLE **table, SORT_FIELD *sortorder, uint s_length,
my_error(ER_FILSORT_ABORT,MYF(ME_ERROR+ME_WAITTANG));
else
statistic_add(filesort_rows, records, &LOCK_status);
-
+ *examined_rows= param.examined_rows;
#ifdef SKIPP_DBUG_IN_FILESORT
DBUG_POP(); /* Ok to DBUG */
#endif
@@ -367,6 +369,8 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
file->rnd_end();
DBUG_RETURN(HA_POS_ERROR); /* purecov: inspected */
}
+ if (error == 0)
+ param->examined_rows++;
if (error == 0 && (!select || select->skipp_record() == 0))
{
if (idx == param->keys)
diff --git a/sql/ha_berkeley.cc b/sql/ha_berkeley.cc
index 9dbd7b6c998..32af39e4a0d 100644
--- a/sql/ha_berkeley.cc
+++ b/sql/ha_berkeley.cc
@@ -41,10 +41,9 @@
from the updated tables.
Testing of:
- - LOCK TABLES
- Mark tables that participate in a transaction so that they are not
closed during the transaction. We need to test what happens if
- MySQL closes a table that is updated by a not commit transaction.
+ MySQL closes a table that is updated by a not commited transaction.
*/
@@ -572,6 +571,7 @@ int ha_berkeley::open(const char *name, int mode, uint test_if_locked)
transaction=0;
cursor=0;
key_read=0;
+ block_size=8192; // Berkeley DB block size
share->fixed_length_row=!(table->db_create_options & HA_OPTION_PACK_RECORD);
get_status();
@@ -1701,12 +1701,35 @@ int ha_berkeley::external_lock(THD *thd, int lock_type)
DBUG_PRINT("trans",("commiting non-updating transaction"));
error=txn_commit((DB_TXN*) thd->transaction.stmt.bdb_tid,0);
thd->transaction.stmt.bdb_tid=0;
+ transaction=0;
}
}
}
DBUG_RETURN(error);
}
+
+/*
+ When using LOCK TABLE's external_lock is only called when the actual
+ TABLE LOCK is done.
+ Under LOCK TABLES, each used tables will force a call to start_stmt.
+*/
+
+int ha_berkeley::start_stmt(THD *thd)
+{
+ int error=0;
+ DBUG_ENTER("ha_berkeley::start_stmt");
+ if (!thd->transaction.stmt.bdb_tid)
+ {
+ error=txn_begin(db_env, (DB_TXN*) thd->transaction.all.bdb_tid,
+ (DB_TXN**) &thd->transaction.stmt.bdb_tid,
+ 0);
+ transaction= (DB_TXN*) thd->transaction.stmt.bdb_tid;
+ }
+ DBUG_RETURN(error);
+}
+
+
/*
The idea with handler::store_lock() is the following:
diff --git a/sql/ha_berkeley.h b/sql/ha_berkeley.h
index 9724d128b1f..9e657d72da1 100644
--- a/sql/ha_berkeley.h
+++ b/sql/ha_berkeley.h
@@ -136,6 +136,7 @@ class ha_berkeley: public handler
int extra(enum ha_extra_function operation);
int reset(void);
int external_lock(THD *thd, int lock_type);
+ int start_stmt(THD *thd);
void position(byte *record);
int analyze(THD* thd,HA_CHECK_OPT* check_opt);
int optimize(THD* thd, HA_CHECK_OPT* check_opt);
diff --git a/sql/ha_innobase.cc b/sql/ha_innobase.cc
index f263f693103..8af9de0eaba 100644
--- a/sql/ha_innobase.cc
+++ b/sql/ha_innobase.cc
@@ -449,7 +449,7 @@ innobase_init(void)
if (!innobase_data_file_path)
{
fprintf(stderr,
- "Can't initialize InnoDB as 'innobase_data_file_path' is not set\n");
+ "Can't initialize InnoDB as 'innodb_data_file_path' is not set\n");
innodb_skip=1;
DBUG_RETURN(FALSE); // Continue without innobase
}
@@ -1868,7 +1868,7 @@ corresponding row to buf. */
int
ha_innobase::index_first(
/*=====================*/
- /* out: 0, HA_ERR_KEY_NOT_FOUND,
+ /* out: 0, HA_ERR_END_OF_FILE,
or error code */
mysql_byte* buf) /* in/out: buffer for the row */
{
@@ -1879,6 +1879,12 @@ ha_innobase::index_first(
error = index_read(buf, NULL, 0, HA_READ_AFTER_KEY);
+ /* MySQL does not seem to allow this to return HA_ERR_KEY_NOT_FOUND */
+
+ if (error == HA_ERR_KEY_NOT_FOUND) {
+ error = HA_ERR_END_OF_FILE;
+ }
+
DBUG_RETURN(error);
}
@@ -1899,7 +1905,7 @@ ha_innobase::index_last(
error = index_read(buf, NULL, 0, HA_READ_BEFORE_KEY);
- /* MySQL does not seem to allow this to return HA_ERR_KEY_NOT_FOUND */
+ /* MySQL does not seem to allow this to return HA_ERR_KEY_NOT_FOUND */
if (error == HA_ERR_KEY_NOT_FOUND) {
error = HA_ERR_END_OF_FILE;
diff --git a/sql/ha_innobase.h b/sql/ha_innobase.h
index e85d73bdae5..429e47523dd 100644
--- a/sql/ha_innobase.h
+++ b/sql/ha_innobase.h
@@ -83,14 +83,14 @@ class ha_innobase: public handler
HA_NO_WRITE_DELAYED |
HA_PRIMARY_KEY_IN_READ_INDEX |
HA_DROP_BEFORE_CREATE |
- HA_NOT_READ_AFTER_KEY),
+ HA_NOT_READ_AFTER_KEY | HA_NO_PREFIX_CHAR_KEYS),
last_dup_key((uint) -1),
start_of_scan(0)
{
}
~ha_innobase() {}
- const char* table_type() const { return("Innobase");}
+ const char* table_type() const { return("InnoDB");}
const char** bas_ext() const;
ulong option_flag() const { return int_option_flag; }
uint max_record_length() const { return HA_MAX_REC_LENGTH; }
diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc
index 1a205e54b9d..6409ec5d019 100644
--- a/sql/ha_myisam.cc
+++ b/sql/ha_myisam.cc
@@ -50,10 +50,12 @@ static void mi_check_print_msg(MI_CHECK *param, const char* msg_type,
{
THD* thd = (THD*)param->thd;
String* packet = &thd->packet;
- packet->length(0);
+ uint length;
char msgbuf[MI_MAX_MSG_BUF];
- msgbuf[0] = 0;
+ char name[NAME_LEN*2+2];
+ packet->length(0);
+ msgbuf[0] = 0; // healthy paranoia ?
my_vsnprintf(msgbuf, sizeof(msgbuf), fmt, args);
msgbuf[sizeof(msgbuf) - 1] = 0; // healthy paranoia
@@ -70,9 +72,12 @@ static void mi_check_print_msg(MI_CHECK *param, const char* msg_type,
my_message(ER_NOT_KEYFILE,msgbuf,MYF(MY_WME));
return;
}
- net_store_data(packet, param->table_name);
+ length=(uint) (strxmov(name, param->db_name,".",param->table_name,NullS) -
+ name);
+ net_store_data(packet, name, length);
net_store_data(packet, param->op_name);
net_store_data(packet, msg_type);
+
net_store_data(packet, msgbuf);
if (my_net_write(&thd->net, (char*)thd->packet.ptr(), thd->packet.length()))
fprintf(stderr,
@@ -245,6 +250,7 @@ int ha_myisam::check(THD* thd, HA_CHECK_OPT* check_opt)
myisamchk_init(&param);
param.thd = thd;
param.op_name = (char*)"check";
+ param.db_name = table->table_cache_key;
param.table_name = table->table_name;
param.testflag = check_opt->flags | T_CHECK | T_SILENT;
@@ -332,6 +338,7 @@ int ha_myisam::analyze(THD *thd, HA_CHECK_OPT* check_opt)
myisamchk_init(&param);
param.thd = thd;
param.op_name = (char*) "analyze";
+ param.db_name = table->table_cache_key;
param.table_name = table->table_name;
param.testflag=(T_FAST | T_CHECK | T_SILENT | T_STATISTICS |
T_DONT_CHECK_CHECKSUM);
@@ -384,6 +391,7 @@ int ha_myisam::restore(THD* thd, HA_CHECK_OPT *check_opt)
myisamchk_init(&param);
param.thd = thd;
param.op_name = (char*)"restore";
+ param.db_name = table->table_cache_key;
param.table_name = table->table_name;
param.testflag = 0;
mi_check_print_error(&param,errmsg, errno );
@@ -438,6 +446,7 @@ int ha_myisam::backup(THD* thd, HA_CHECK_OPT *check_opt)
myisamchk_init(&param);
param.thd = thd;
param.op_name = (char*)"backup";
+ param.db_name = table->table_cache_key;
param.table_name = table->table_name;
param.testflag = 0;
mi_check_print_error(&param,errmsg, errno );
@@ -524,6 +533,7 @@ int ha_myisam::repair(THD *thd, MI_CHECK &param, bool optimize)
ha_rows rows= file->state->records;
DBUG_ENTER("ha_myisam::repair");
+ param.db_name = table->table_cache_key;
param.table_name = table->table_name;
param.tmpfile_createflag = O_RDWR | O_TRUNC;
param.using_global_keycache = 1;
@@ -533,7 +543,8 @@ int ha_myisam::repair(THD *thd, MI_CHECK &param, bool optimize)
VOID(fn_format(fixed_name,file->filename,"",MI_NAME_IEXT,
4+ (param.opt_follow_links ? 16 : 0)));
- if (mi_lock_database(file,F_WRLCK))
+ // Don't lock tables if we have used LOCK TABLE
+ if (!thd->locked_tables && mi_lock_database(file,F_WRLCK))
{
mi_check_print_error(&param,ER(ER_CANT_LOCK),my_errno);
DBUG_RETURN(HA_ADMIN_FAILED);
@@ -615,7 +626,8 @@ int ha_myisam::repair(THD *thd, MI_CHECK &param, bool optimize)
update_state_info(&param, file, 0);
}
thd->proc_info=old_proc_info;
- mi_lock_database(file,F_UNLCK);
+ if (!thd->locked_tables)
+ mi_lock_database(file,F_UNLCK);
DBUG_RETURN(error ? HA_ADMIN_FAILED :
!optimize_done ? HA_ADMIN_ALREADY_DONE : HA_ADMIN_OK);
}
diff --git a/sql/handler.h b/sql/handler.h
index 638529ab882..076bf783f80 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -73,6 +73,7 @@
#define HA_NOT_READ_AFTER_KEY (HA_DROP_BEFORE_CREATE*2)
#define HA_NOT_DELETE_WITH_CACHE (HA_NOT_READ_AFTER_KEY*2)
#define HA_NO_TEMP_TABLES (HA_NOT_DELETE_WITH_CACHE*2)
+#define HA_NO_PREFIX_CHAR_KEYS (HA_NO_TEMP_TABLES*2)
/* Parameters for open() (in register form->filestat) */
/* HA_GET_INFO does a implicit HA_ABORT_IF_LOCKED */
@@ -265,6 +266,7 @@ public:
virtual int extra(enum ha_extra_function operation)=0;
virtual int reset()=0;
virtual int external_lock(THD *thd, int lock_type)=0;
+ virtual int start_stmt(THD *thd) {return 0;}
virtual int delete_all_rows();
virtual longlong get_auto_increment();
virtual void update_create_info(HA_CREATE_INFO *create_info) {}
@@ -344,6 +346,7 @@ int ha_create_table(const char *name, HA_CREATE_INFO *create_info,
bool update_create_info);
int ha_delete_table(enum db_type db_type, const char *path);
void ha_key_cache(void);
+int ha_start_stmt(THD *thd);
int ha_commit_trans(THD *thd, THD_TRANS *trans);
int ha_rollback_trans(THD *thd, THD_TRANS *trans);
int ha_autocommit_or_rollback(THD *thd, int error);
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 82dcb0268b4..80f72c30e57 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -393,12 +393,14 @@ void Item_func_reverse::fix_length_and_dec()
String *Item_func_replace::val_str(String *str)
{
String *res,*res2,*res3;
- int offset=0;
+ int offset;
uint from_length,to_length;
bool alloced=0;
#ifdef USE_MB
const char *ptr,*end,*strend,*search,*search_end;
register uint32 l;
+ bool binary_str = (args[0]->binary || args[1]->binary ||
+ !use_mb(default_charset_info));
#endif
null_value=0;
@@ -415,7 +417,8 @@ String *Item_func_replace::val_str(String *str)
if ((offset=res->strstr(*res2)) < 0)
return res;
#else
- if (!use_mb(default_charset_info) && (offset=res->strstr(*res2)) < 0)
+ offset=0;
+ if (binary_str && (offset=res->strstr(*res2)) < 0)
return res;
#endif
if (!(res3=args[2]->val_str(&tmp_value2)))
@@ -424,7 +427,7 @@ String *Item_func_replace::val_str(String *str)
to_length= res3->length();
#ifdef USE_MB
- if (use_mb(default_charset_info))
+ if (!binary_str)
{
search=res2->ptr();
search_end=search+from_length;
@@ -449,6 +452,7 @@ redo:
res=copy_if_not_alloced(str,res,res->length()+to_length);
}
res->replace((uint) offset,from_length,*res3);
+ offset+=(int) to_length;
goto redo;
}
skipp:
diff --git a/sql/lex.h b/sql/lex.h
index 7f902787223..0e10ff4949c 100644
--- a/sql/lex.h
+++ b/sql/lex.h
@@ -89,6 +89,7 @@ static SYMBOL symbols[] = {
{ "COMMIT", SYM(COMMIT_SYM),0,0},
{ "COMMITTED", SYM(COMMITTED_SYM),0,0},
{ "COMPRESSED", SYM(COMPRESSED_SYM),0,0},
+ { "CONCURRENT", SYM(CONCURRENT),0,0},
{ "CONSTRAINT", SYM(CONSTRAINT),0,0},
{ "CREATE", SYM(CREATE),0,0},
{ "CROSS", SYM(CROSS),0,0},
diff --git a/sql/lock.cc b/sql/lock.cc
index 915f1831245..23f81c9c164 100644
--- a/sql/lock.cc
+++ b/sql/lock.cc
@@ -346,7 +346,7 @@ static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count,
*write_lock_used=0;
for (i=tables=lock_count=0 ; i < count ; i++)
{
- if (!table_ptr[i]->tmp_table)
+ if (table_ptr[i]->tmp_table != TMP_TABLE)
{
tables+=table_ptr[i]->file->lock_count();
lock_count++;
@@ -366,7 +366,7 @@ static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count,
for (i=0 ; i < count ; i++)
{
TABLE *table;
- if ((table=table_ptr[i])->tmp_table)
+ if ((table=table_ptr[i])->tmp_table == TMP_TABLE)
continue;
*to++=table;
enum thr_lock_type lock_type= table->reginfo.lock_type;
diff --git a/sql/log.cc b/sql/log.cc
index 9601d162d28..4cd93261973 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -103,7 +103,7 @@ MYSQL_LOG::~MYSQL_LOG()
void MYSQL_LOG::set_index_file_name(const char* index_file_name)
{
if (index_file_name)
- fn_format(this->index_file_name,index_file_name,mysql_data_home,"-index",
+ fn_format(this->index_file_name,index_file_name,mysql_data_home,".index",
4);
else
this->index_file_name[0] = 0;
@@ -129,6 +129,32 @@ int MYSQL_LOG::generate_new_name(char *new_name, const char *log_name)
return 0;
}
+bool MYSQL_LOG::open_index( int options)
+{
+ return (index_file < 0 &&
+ (index_file = my_open(index_file_name, options | O_BINARY ,
+ MYF(MY_WME))) < 0);
+}
+
+void MYSQL_LOG::init(enum_log_type log_type_arg)
+{
+ log_type = log_type_arg;
+ if (!inited)
+ {
+ inited=1;
+ (void) pthread_mutex_init(&LOCK_log,MY_MUTEX_INIT_SLOW);
+ (void) pthread_mutex_init(&LOCK_index, MY_MUTEX_INIT_SLOW);
+ }
+}
+
+void MYSQL_LOG::close_index()
+{
+ if(index_file >= 0)
+ {
+ my_close(index_file, MYF(0));
+ index_file = -1;
+ }
+}
void MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg,
const char *new_name)
@@ -137,17 +163,11 @@ void MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg,
char buff[512];
File file= -1;
bool do_magic;
-
- if (!inited)
- {
- inited=1;
- (void) pthread_mutex_init(&LOCK_log,MY_MUTEX_INIT_SLOW);
- (void) pthread_mutex_init(&LOCK_index, MY_MUTEX_INIT_SLOW);
- if (log_type_arg == LOG_BIN && *fn_ext(log_name))
+
+ if (!inited && log_type_arg == LOG_BIN && *fn_ext(log_name))
no_rotate = 1;
- }
+ init(log_type_arg);
- log_type=log_type_arg;
if (!(name=my_strdup(log_name,MYF(MY_WME))))
goto err;
if (new_name)
@@ -208,10 +228,7 @@ void MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg,
clean up if failed
*/
if ((do_magic && my_b_write(&log_file, (byte*) BINLOG_MAGIC, 4)) ||
- (index_file < 0 &&
- (index_file = my_open(index_file_name,
- O_APPEND | O_BINARY | O_RDWR | O_CREAT,
- MYF(MY_WME))) < 0))
+ open_index(O_APPEND | O_RDWR | O_CREAT))
goto err;
Start_log_event s;
bool error;
@@ -224,8 +241,7 @@ void MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg,
pthread_mutex_unlock(&LOCK_index);
if (error)
{
- my_close(index_file,MYF(0));
- index_file= -1;
+ close_index();
goto err;
}
}
@@ -825,11 +841,12 @@ bool MYSQL_LOG::write(THD *thd,const char *query, uint query_length,
{
/* For slow query log */
if (my_b_printf(&log_file,
- "# Time: %lu Lock_time: %lu Rows_sent: %lu\n",
+ "# Time: %lu Lock_time: %lu Rows_sent: %lu Rows_examined: %lu\n",
(ulong) (current_time - query_start),
(ulong) (thd->time_after_lock - query_start),
- (ulong) thd->sent_row_count) == (uint) -1)
- tmp_errno=errno;
+ (ulong) thd->sent_row_count,
+ (ulong) thd->examined_row_count) == (uint) -1)
+ tmp_errno=errno;
}
if (thd->db && strcmp(thd->db,db))
{ // Database changed
diff --git a/sql/log_event.cc b/sql/log_event.cc
index d643952c5b0..ac985c266c8 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -280,7 +280,7 @@ void Log_event::print_timestamp(FILE* file, time_t* ts)
}
-void Start_log_event::print(FILE* file, bool short_form)
+void Start_log_event::print(FILE* file, bool short_form, char* last_db)
{
if (short_form)
return;
@@ -293,7 +293,7 @@ void Start_log_event::print(FILE* file, bool short_form)
fflush(file);
}
-void Stop_log_event::print(FILE* file, bool short_form)
+void Stop_log_event::print(FILE* file, bool short_form, char* last_db)
{
if (short_form)
return;
@@ -303,7 +303,7 @@ void Stop_log_event::print(FILE* file, bool short_form)
fflush(file);
}
-void Rotate_log_event::print(FILE* file, bool short_form)
+void Rotate_log_event::print(FILE* file, bool short_form, char* last_db)
{
if (short_form)
return;
@@ -441,7 +441,7 @@ Query_log_event::Query_log_event(const char* buf, int event_len):
*((char*)query+q_len) = 0;
}
-void Query_log_event::print(FILE* file, bool short_form)
+void Query_log_event::print(FILE* file, bool short_form, char* last_db)
{
char buff[40],*end; // Enough for SET TIMESTAMP
if (!short_form)
@@ -451,7 +451,15 @@ void Query_log_event::print(FILE* file, bool short_form)
(ulong) thread_id, (ulong) exec_time, error_code);
}
- if (db && db[0])
+ bool same_db = 0;
+
+ if(db && last_db)
+ {
+ if(!(same_db = !memcmp(last_db, db, db_len + 1)))
+ memcpy(last_db, db, db_len + 1);
+ }
+
+ if (db && db[0] && !same_db)
fprintf(file, "use %s;\n", db);
end=int10_to_str((long) when, strmov(buff,"SET TIMESTAMP="),10);
*end++=';';
@@ -507,7 +515,7 @@ int Intvar_log_event::write_data(IO_CACHE* file)
return my_b_write(file, (byte*) buf, sizeof(buf));
}
-void Intvar_log_event::print(FILE* file, bool short_form)
+void Intvar_log_event::print(FILE* file, bool short_form, char* last_db)
{
char llbuff[22];
if(!short_form)
@@ -625,7 +633,7 @@ void Load_log_event::copy_log_event(const char *buf, ulong data_len)
}
-void Load_log_event::print(FILE* file, bool short_form)
+void Load_log_event::print(FILE* file, bool short_form, char* last_db)
{
if (!short_form)
{
@@ -634,7 +642,15 @@ void Load_log_event::print(FILE* file, bool short_form)
thread_id, exec_time);
}
- if(db && db[0])
+ bool same_db = 0;
+
+ if(db && last_db)
+ {
+ if(!(same_db = !memcmp(last_db, db, db_len + 1)))
+ memcpy(last_db, db, db_len + 1);
+ }
+
+ if(db && db[0] && !same_db)
fprintf(file, "use %s;\n", db);
fprintf(file, "LOAD DATA INFILE '%s' ", fname);
@@ -678,7 +694,7 @@ void Load_log_event::print(FILE* file, bool short_form)
}
if((int)skip_lines > 0)
- fprintf(file, " IGNORE %d LINES ", skip_lines);
+ fprintf(file, " IGNORE %ld LINES ", (long) skip_lines);
if (num_fields)
{
diff --git a/sql/log_event.h b/sql/log_event.h
index 0f4945bae3c..41f847e8d92 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -100,7 +100,7 @@ public:
virtual ~Log_event() {}
virtual int get_data_size() { return 0;}
- virtual void print(FILE* file, bool short_form = 0) = 0;
+ virtual void print(FILE* file, bool short_form = 0, char* last_db = 0) = 0;
void print_timestamp(FILE* file, time_t *ts = 0);
void print_header(FILE* file);
@@ -169,7 +169,7 @@ public:
;
}
- void print(FILE* file, bool short_form = 0);
+ void print(FILE* file, bool short_form = 0, char* last_db = 0);
};
#define DUMPFILE_FLAG 0x1
@@ -312,7 +312,7 @@ public:
;
}
- void print(FILE* file, bool short_form = 0);
+ void print(FILE* file, bool short_form = 0, char* last_db = 0);
};
extern char server_version[SERVER_VERSION_LENGTH];
@@ -350,7 +350,7 @@ public:
// sizeof(binlog_version) + sizeof(server_version) sizeof(created)
return 2 + sizeof(server_version) + 4;
}
- void print(FILE* file, bool short_form = 0);
+ void print(FILE* file, bool short_form = 0, char* last_db = 0);
};
class Intvar_log_event: public Log_event
@@ -369,7 +369,7 @@ public:
int write_data(IO_CACHE* file);
- void print(FILE* file, bool short_form = 0);
+ void print(FILE* file, bool short_form = 0, char* last_db = 0);
};
class Stop_log_event: public Log_event
@@ -388,7 +388,7 @@ public:
}
~Stop_log_event() {}
Log_event_type get_type_code() { return STOP_EVENT;}
- void print(FILE* file, bool short_form = 0);
+ void print(FILE* file, bool short_form = 0, char* last_db = 0);
};
class Rotate_log_event: public Log_event
@@ -416,7 +416,7 @@ public:
int get_data_size() { return ident_len;}
int write_data(IO_CACHE* file);
- void print(FILE* file, bool short_form = 0);
+ void print(FILE* file, bool short_form = 0, char* last_db = 0);
};
#endif
diff --git a/sql/mini_client.cc b/sql/mini_client.cc
index fa1b9da38a8..38180c0c6c8 100644
--- a/sql/mini_client.cc
+++ b/sql/mini_client.cc
@@ -330,8 +330,14 @@ mc_net_safe_read(MYSQL *mysql)
if(errno != EINTR)
{
mc_end_server(mysql);
- net->last_errno=CR_SERVER_LOST;
- strmov(net->last_error,ER(net->last_errno));
+ if(net->last_errno != ER_NET_PACKET_TOO_LARGE)
+ {
+ net->last_errno=CR_SERVER_LOST;
+ strmov(net->last_error,ER(net->last_errno));
+ }
+ else
+ strmov(net->last_error, "Packet too large - increase \
+max_allowed_packet on this server");
}
return(packet_error);
}
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 2c4ad21de95..3fdc50b1521 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -614,7 +614,8 @@ void init_read_record(READ_RECORD *info, THD *thd, TABLE *reg_form,
int use_record_cache, bool print_errors);
void end_read_record(READ_RECORD *info);
ha_rows filesort(TABLE **form,struct st_sort_field *sortorder, uint s_length,
- SQL_SELECT *select, ha_rows special,ha_rows max_rows);
+ SQL_SELECT *select, ha_rows special,ha_rows max_rows,
+ ha_rows *examined_rows);
void change_double_for_sort(double nr,byte *to);
int get_quick_record(SQL_SELECT *select);
int calc_weekday(long daynr,bool sunday_first_day_of_week);
diff --git a/sql/mysqlbinlog.cc b/sql/mysqlbinlog.cc
index 49daa04ffff..f0a9692cc2d 100644
--- a/sql/mysqlbinlog.cc
+++ b/sql/mysqlbinlog.cc
@@ -38,6 +38,7 @@ ulong mysqld_net_retry_count = 10L;
ulong net_read_timeout= NET_READ_TIMEOUT;
ulong net_write_timeout= NET_WRITE_TIMEOUT;
uint test_flags = 0;
+FILE *result_file;
#ifndef DBUG_OFF
static const char* default_dbug_option = "d:t:o,/tmp/mysqlbinlog.trace";
@@ -46,18 +47,19 @@ static const char* default_dbug_option = "d:t:o,/tmp/mysqlbinlog.trace";
static struct option long_options[] =
{
#ifndef DBUG_OFF
- {"debug", optional_argument, 0, '#'},
+ {"debug", optional_argument, 0, '#'},
#endif
- {"help", no_argument, 0, '?'},
- {"host", required_argument, 0, 'h'},
- {"offset", required_argument, 0, 'o'},
- {"password", required_argument, 0, 'p'},
- {"port", required_argument, 0, 'P'},
- {"position", required_argument, 0, 'j'},
- {"short-form", no_argument, 0, 's'},
- {"table", required_argument, 0, 't'},
- {"user", required_argument, 0, 'u'},
- {"version", no_argument, 0, 'V'},
+ {"help", no_argument, 0, '?'},
+ {"host", required_argument, 0, 'h'},
+ {"offset", required_argument, 0, 'o'},
+ {"password", required_argument, 0, 'p'},
+ {"port", required_argument, 0, 'P'},
+ {"position", required_argument, 0, 'j'},
+ {"result-file", required_argument, 0, 'r'},
+ {"short-form", no_argument, 0, 's'},
+ {"table", required_argument, 0, 't'},
+ {"user", required_argument, 0, 'u'},
+ {"version", no_argument, 0, 'V'},
};
void sql_print_error(const char *format,...);
@@ -106,7 +108,7 @@ static void die(const char* fmt, ...)
static void print_version()
{
- printf("%s Ver 1.2 for %s at %s\n",my_progname,SYSTEM_TYPE, MACHINE_TYPE);
+ printf("%s Ver 1.3 for %s at %s\n",my_progname,SYSTEM_TYPE, MACHINE_TYPE);
}
@@ -133,6 +135,7 @@ the mysql command line client\n\n");
-P, --port=port Use port to connect to the remove server\n\
-u, --user=username Connect to the remove server as username\n\
-p, --password=password Password to connect to remote server\n\
+-r, --result-file=file Direct output to a given file\n\
-j, --position=N Start reading the binlog at position N\n\
-t, --table=name Get raw table dump using COM_TABLE_DUMB\n\
-V, --version Print version and exit.\n\
@@ -163,17 +166,18 @@ static void dump_remote_file(NET* net, const char* fname)
die("Failed reading a packet during the dump of %s ", fname);
if(!short_form)
- (void)my_fwrite(stdout, (byte*) net->read_pos, packet_len, MYF(0));
+ (void)my_fwrite(result_file, (byte*) net->read_pos, packet_len,MYF(0));
}
- fflush(stdout);
+ fflush(result_file);
}
static int parse_args(int *argc, char*** argv)
{
int c, opt_index = 0;
- while((c = getopt_long(*argc, *argv, "so:#::h:j:u:p:P:t:?V", long_options,
+ result_file = stdout;
+ while((c = getopt_long(*argc, *argv, "so:#::h:j:u:p:P:r:t:?V", long_options,
&opt_index)) != EOF)
{
switch(c)
@@ -210,6 +214,11 @@ static int parse_args(int *argc, char*** argv)
pass = my_strdup(optarg, MYF(0));
break;
+ case 'r':
+ if (!(result_file = my_fopen(optarg, O_WRONLY | O_BINARY, MYF(MY_WME))))
+ exit(1);
+ break;
+
case 'u':
use_remote = 1;
user = my_strdup(optarg, MYF(0));
@@ -276,20 +285,21 @@ static void dump_remote_table(NET* net, const char* db, const char* table)
die("Error sending the table dump command");
for(;;)
- {
- uint packet_len = my_net_read(net);
- if(packet_len == 0) break; // end of file
- if(packet_len == packet_error)
- die("Error reading packet in table dump");
- my_fwrite(stdout, (byte*)net->read_pos, packet_len, MYF(MY_WME));
- fflush(stdout);
- }
+ {
+ uint packet_len = my_net_read(net);
+ if(packet_len == 0) break; // end of file
+ if(packet_len == packet_error)
+ die("Error reading packet in table dump");
+ my_fwrite(result_file, (byte*)net->read_pos, packet_len, MYF(MY_WME));
+ fflush(result_file);
+ }
}
static void dump_remote_log_entries(const char* logname)
{
char buf[128];
+ char last_db[FN_REFLEN+1] = "";
uint len;
NET* net = &mysql->net;
if(!position) position = 4; // protect the innocent from spam
@@ -323,7 +333,7 @@ Unfortunately, no sweepstakes today, adjusted position to 4\n");
len - 1);
if(ev)
{
- ev->print(stdout, short_form);
+ ev->print(result_file, short_form, last_db);
if(ev->get_type_code() == LOAD_EVENT)
dump_remote_file(net, ((Load_log_event*)ev)->fname);
delete ev;
@@ -338,6 +348,7 @@ static void dump_local_log_entries(const char* logname)
File fd = -1;
IO_CACHE cache,*file= &cache;
ulonglong rec_count = 0;
+ char last_db[FN_REFLEN+1] = "";
if (logname && logname[0] != '-')
{
@@ -349,7 +360,7 @@ static void dump_local_log_entries(const char* logname)
}
else
{
- if (init_io_cache(file, fileno(stdout), 0, READ_CACHE, (my_off_t) 0,
+ if (init_io_cache(file, fileno(result_file), 0, READ_CACHE, (my_off_t) 0,
0, MYF(MY_WME | MY_NABP | MY_DONT_CHECK_FILESIZE)))
exit(1);
if (position)
@@ -395,9 +406,9 @@ Could not read entry at offset %s : Error in log format or read error",
if (rec_count >= offset)
{
if (!short_form)
- printf("# at %s\n",llstr(old_off,llbuff));
+ fprintf(result_file, "# at %s\n",llstr(old_off,llbuff));
- ev->print(stdout, short_form);
+ ev->print(result_file, short_form, last_db);
}
rec_count++;
delete ev;
@@ -445,6 +456,8 @@ int main(int argc, char** argv)
dump_log_entries(*(argv++));
}
}
+ if (result_file != stdout)
+ my_fclose(result_file, MYF(0));
if (use_remote)
mc_mysql_close(mysql);
return 0;
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index bbda3eba1bb..2ed1a30d8f6 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -99,6 +99,11 @@ int deny_severity = LOG_WARNING;
typedef fp_except fp_except_t;
#endif
+#ifdef _AIX41
+extern "C" int initgroups(const char *,int);
+#endif
+
+
/* We can't handle floating point expections with threads, so disable
this on freebsd
*/
@@ -151,7 +156,7 @@ static pthread_cond_t COND_handler_count;
static uint handler_count;
#endif
#ifdef __WIN__
-static bool opt_console=0;
+static bool opt_console=0,start_mode=0;
#endif
#ifdef HAVE_BERKELEY_DB
@@ -1114,9 +1119,12 @@ static void start_signal_handler(void)
#ifdef HAVE_LINUXTHREADS
static sig_handler write_core(int sig);
-#if defined(__i386__) && !defined(HAVE_STACK_TRACE_ON_SEGV)
-#define SIGRETURN_FRAME_COUNT 1
-#define PTR_SANE(p) ((char*)p >= heap_start && (char*)p <= heap_end)
+#if defined (__i386__) || defined(__alpha__)
+#define LINUX_STACK_TRACE
+#endif
+
+#ifdef LINUX_STACK_TRACE
+#define PTR_SANE(p) ((p) && (char*)(p) >= heap_start && (char*)(p) <= heap_end)
extern char* __bss_start;
static char* heap_start, *heap_end;
@@ -1125,43 +1133,101 @@ inline __volatile__ void print_str(const char* name,
const char* val, int max_len)
{
fprintf(stderr, "%s at %p ", name, val);
- if (!PTR_SANE(val))
- {
- fprintf(stderr, " is invalid pointer\n");
- return;
- }
+ if(!PTR_SANE(val))
+ {
+ fprintf(stderr, " is invalid pointer\n");
+ return;
+ }
fprintf(stderr, "= ");
- for (; max_len && PTR_SANE(val) && *val; --max_len)
+ for(; max_len && PTR_SANE(val) && *val; --max_len)
fputc(*val++, stderr);
fputc('\n', stderr);
}
+#endif
+
+
+#ifdef LINUX_STACK_TRACE
+#define SIGRETURN_FRAME_COUNT 1
+
+#ifdef __alpha__
+// The only way to backtrace without a symbol table on alpha
+// to find stq fp,N(sp), and the first byte
+// of the instruction opcode will give us the value of N. From this
+// we can find where the old value of fp is stored
+
+#define MAX_INSTR_IN_FUNC 10000
+
+inline uchar** find_prev_fp(uint32* pc, uchar** fp)
+{
+ int i;
+ for(i = 0; i < MAX_INSTR_IN_FUNC; ++i,--pc)
+ {
+ uchar* p = (uchar*)pc;
+ if(p[2] == 222 && p[3] == 35)
+ {
+ return (uchar**)((uchar*)fp - *(short int*)p);
+ }
+ }
+ return 0;
+}
+
+inline uint32* find_prev_pc(uint32* pc, uchar** fp)
+{
+ int i;
+ for(i = 0; i < MAX_INSTR_IN_FUNC; ++i,--pc)
+ {
+ char* p = (char*)pc;
+ if(p[1] == 0 && p[2] == 94 && p[3] == -73)
+ {
+ uint32* prev_pc = (uint32*)*((fp+p[0]/sizeof(fp)));
+ return prev_pc;
+ }
+ }
+ return 0;
+}
+
+#endif
inline __volatile__ void trace_stack()
{
uchar **stack_bottom;
- uchar** ebp;
- LINT_INIT(ebp);
+ uchar** fp;
+ LINT_INIT(fp);
LINT_INIT(stack_bottom);
fprintf(stderr,
"Attempting backtrace. You can use the following information to find out\n\
-where mysqld died. If you see no messages after this, something went\n\
+where mysqld died. If you see no messages after this, something went\n\
terribly wrong...\n");
THD* thd = current_thd;
uint frame_count = 0;
+#ifdef __i386__
__asm __volatile__ ("movl %%ebp,%0"
- :"=r"(ebp)
- :"r"(ebp));
- if (!ebp)
+ :"=r"(fp)
+ :"r"(fp));
+ if (!fp)
{
fprintf(stderr, "frame pointer (ebp) is NULL, did you compile with\n\
-fomit-frame-pointer? Aborting backtrace!\n");
return;
}
+#endif
+#ifdef __alpha__
+ __asm __volatile__ ("mov $15,%0"
+ :"=r"(fp)
+ :"r"(fp));
+ if (!fp)
+ {
+ fprintf(stderr, "frame pointer (fp) is NULL, did you compile with\n\
+-fomit-frame-pointer? Aborting backtrace!\n");
+ return;
+ }
+#endif
+
if (!thd)
{
- fprintf(stderr, "Cannot determine thread, ebp=%p, backtrace may not be correct.\n", ebp);
+ fprintf(stderr, "Cannot determine thread, fp=%p, backtrace may not be correct.\n", fp);
/* Assume that the stack starts at the previous even 65K */
ulong tmp= min(0x10000,thread_stack);
stack_bottom= (uchar**) (((ulong) &stack_bottom + tmp) &
@@ -1169,32 +1235,77 @@ terribly wrong...\n");
}
else
stack_bottom = (uchar**) thd->thread_stack;
- if (ebp > stack_bottom || ebp < stack_bottom - thread_stack)
+ if (fp > stack_bottom || fp < stack_bottom - thread_stack)
{
- fprintf(stderr,
- "Bogus stack limit or frame pointer, aborting backtrace.\n");
+ fprintf(stderr, "Bogus stack limit or frame pointer,\
+ fp=%p, stack_bottom=%p, thread_stack=%ld, aborting backtrace.\n",
+ fp, stack_bottom, thread_stack);
return;
}
fprintf(stderr, "Stack range sanity check OK, backtrace follows:\n");
+#ifdef __alpha__
+ fprintf(stderr, "Warning: Alpha stacks are difficult -\
+ will be taking some wild guesses, stack trace may be incorrect or \
+ terminate abruptly\n");
+ // On Alpha, we need to get pc
+ uint32* pc;
+ __asm __volatile__ ("bsr %0, do_next; do_next: "
+ :"=r"(pc)
+ :"r"(pc));
+#endif
- while (ebp < stack_bottom)
+ while (fp < stack_bottom)
{
- uchar** new_ebp = (uchar**)*ebp;
+#ifdef __i386__
+ uchar** new_fp = (uchar**)*fp;
fprintf(stderr, "%p\n", frame_count == SIGRETURN_FRAME_COUNT ?
- *(ebp+17) : *(ebp+1));
- if (new_ebp <= ebp )
+ *(fp+17) : *(fp+1));
+#endif
+#ifdef __alpha__
+ uchar** new_fp = find_prev_fp(pc, fp);
+ if(frame_count == SIGRETURN_FRAME_COUNT - 1)
+ {
+ new_fp += 90;
+ }
+
+ if(fp && pc)
+ {
+ pc = find_prev_pc(pc, fp);
+ if(pc)
+ fprintf(stderr, "%p\n", pc);
+ else
+ {
+ fprintf(stderr, "Not smart enough to deal with the rest\
+ of this stack\n");
+ goto print_glob_vars;
+ }
+ }
+ else
+ {
+ fprintf(stderr, "Not smart enough to deal with the rest of \
+ this stack\n");
+ goto print_glob_vars;
+ }
+#endif
+ if (new_fp <= fp )
{
- fprintf(stderr, "\
-New value of ebp failed sanity check, terminating backtrace!\n");
- return;
+ fprintf(stderr, "New value of fp=%p failed sanity check,\
+ terminating stack trace!\n", new_fp);
+ goto print_glob_vars;
}
- ebp = new_ebp;
+ fp = new_fp;
++frame_count;
}
- fprintf(stderr, "Stack trace successful, tryint to get some variables.\n\
+
+ fprintf(stderr, "Stack trace seems successful - bottom reached\n");
+
+ print_glob_vars:
+ fprintf(stderr, "Please read http://www.mysql.com/doc/U/s/Using_stack_trace.html and follow instructions on how to resolve the stack trace. Resolved\n\
+stack trace is much more helpful in diagnosing the problem, so please do \n\
+resolve it\n");
+ fprintf(stderr, "Trying to get some variables.\n\
Some pointers may be invalid and cause the dump to abort...\n");
- heap_start = __bss_start;
heap_end = (char*)sbrk(0);
print_str("thd->query", thd->query, 1024);
fprintf(stderr, "thd->thread_id = %ld\n", thd->thread_id);
@@ -1205,7 +1316,11 @@ In some cases of really bad corruption, this value may be invalid\n",
fprintf(stderr, "Please use the information above to create a repeatable\n\
test case for the crash, and send it to bugs@lists.mysql.com\n");
}
-#endif /* HAVE_LINUXTHREADS */
+#endif
+#endif
+
+#ifdef HAVE_LINUXTHREADS
+#define UNSAFE_DEFAULT_LINUX_THREADS 200
#endif
static sig_handler handle_segfault(int sig)
@@ -1215,18 +1330,50 @@ static sig_handler handle_segfault(int sig)
// so not having the mutex is not as bad as possibly using a buggy
// mutex - so we keep things simple
if (segfaulted)
- return;
+ {
+ fprintf(stderr, "Fatal signal %d while backtracing\n", sig);
+ exit(1);
+ }
+
segfaulted = 1;
fprintf(stderr,"\
mysqld got signal %d;\n\
-The manual section 'Debugging a MySQL server' tells you how to use a\n\
-stack trace and/or the core file to produce a readable backtrace that may\n\
-help in finding out why mysqld died.\n",sig);
+This could be because you hit a bug. It is also possible that \n\
+this binary or one of the libraries it was linked agaist is \n\
+corrupt, improperly built, or misconfigured. This error can also be\n\
+caused by malfunctioning hardware.", sig);
+ fprintf(stderr, "We will try our best to scrape up some info\n\
+that will hopefully help diagnose the problem, but since we have already\n\
+crashed, something is definitely wrong and this may fail\n");
+ fprintf(stderr, "key_buffer_size=%ld\n", keybuff_size);
+ fprintf(stderr, "record_buffer=%ld\n", my_default_record_cache_size);
+ fprintf(stderr, "sort_buffer=%ld\n", sortbuff_size);
+ fprintf(stderr, "max_used_connections=%ld\n", max_used_connections);
+ fprintf(stderr, "max_connections=%ld\n", max_connections);
+ fprintf(stderr, "threads_connected=%d\n", thread_count);
+ fprintf(stderr, "It is possible that mysqld could use up to \n\
+key_buffer_size + (record_buffer + sort_buffer)*max_connections = %ld K\n\
+bytes of memory\n", (keybuff_size + (my_default_record_cache_size +
+ sortbuff_size) * max_connections)/ 1024);
+ fprintf(stderr, "Hope that's ok, if not, decrease some variables in the\n\
+equation\n");
+
#if defined(HAVE_LINUXTHREADS)
-#if defined(__i386__) && !defined(HAVE_STACK_TRACE_ON_SEGV)
- trace_stack();
- fflush(stderr);
-#endif /* __i386__ && !HAVE_STACK_TRACE_ON_SEGV */
+
+ if(sizeof(char*) == 4 && thread_count > UNSAFE_DEFAULT_LINUX_THREADS)
+ {
+ fprintf(stderr, "You seem to be running 32-bit Linux and\n\
+ have %d concurrent connections. If you have not\n\
+changed STACK_SIZE in LinuxThreads and build the binary yourself,\n\
+LinuxThreads is quite likely to steal a part of global heap for a \n\
+thread stack. Please read http://www.mysql.com/doc/L/i/Linux.html\n",
+ thread_count);
+ }
+#ifdef LINUX_STACK_TRACE
+ if(!(test_flags & TEST_NO_STACKTRACE))
+ trace_stack();
+ fflush(stderr);
+#endif /* LINUX_STACK_TRACE */
if (test_flags & TEST_CORE_ON_SIGNAL)
write_core(sig);
#endif /* HAVE_LINUXTHREADS */
@@ -1255,7 +1402,12 @@ static void init_signals(void)
struct sigaction sa; sa.sa_flags = 0;
sigemptyset(&sa.sa_mask);
sigprocmask(SIG_SETMASK,&sa.sa_mask,NULL);
- if (!(test_flags & TEST_NO_STACKTRACE))
+
+#ifdef LINUX_STACK_TRACE
+ heap_start = (char*)&__bss_start;
+#endif
+
+ if (!(test_flags & TEST_NO_STACKTRACE) || (test_flags & TEST_CORE_ON_SIGNAL))
{
sa.sa_handler=handle_segfault;
sigaction(SIGSEGV, &sa, NULL);
@@ -1959,12 +2111,24 @@ The server will not act as a slave.");
sql_print_error("After lock_thread_count");
#endif
#else
- // remove the event, because it will not be valid anymore
- Service.SetShutdownEvent(0);
- if(hEventShutdown) CloseHandle(hEventShutdown);
- // if it was started as service on NT try to stop the service
- if(Service.IsNT())
- Service.Stop();
+ if (Service.IsNT())
+ {
+ if(start_mode)
+ {
+ if (WaitForSingleObject(hEventShutdown,INFINITE)==WAIT_OBJECT_0)
+ Service.Stop();
+ }
+ else
+ {
+ Service.SetShutdownEvent(0);
+ if(hEventShutdown) CloseHandle(hEventShutdown);
+ }
+ }
+ else
+ {
+ Service.SetShutdownEvent(0);
+ if(hEventShutdown) CloseHandle(hEventShutdown);
+ }
#endif
/* Wait until cleanup is done */
@@ -2017,6 +2181,7 @@ int main(int argc, char **argv)
else if (argc == 1) // No arguments; start as a service
{
// init service
+ start_mode = 1;
long tmp=Service.Init(MYSQL_SERVICENAME,mysql_service);
return 0;
}
@@ -2051,7 +2216,7 @@ static int bootstrap(FILE *file)
if (pthread_create(&thd->real_id,&connection_attrib,handle_bootstrap,
(void*) thd))
{
- sql_print_error("Warning: Can't create thread to handle bootstrap");
+ sql_print_error("Warning: Can't create thread to handle bootstrap");
return -1;
}
/* Wait for thread to die */
@@ -2492,6 +2657,7 @@ enum options {
OPT_TEMP_POOL, OPT_DO_PSTACK, OPT_TX_ISOLATION,
OPT_GEMINI_FLUSH_LOG, OPT_GEMINI_RECOVER,
OPT_GEMINI_UNBUFFERED_IO, OPT_SKIP_SAFEMALLOC,
+ OPT_SKIP_STACK_TRACE
};
static struct option long_options[] = {
@@ -2615,11 +2781,12 @@ static struct option long_options[] = {
{"skip-locking", no_argument, 0, (int) OPT_SKIP_LOCK},
{"skip-host-cache", no_argument, 0, (int) OPT_SKIP_HOST_CACHE},
{"skip-name-resolve", no_argument, 0, (int) OPT_SKIP_RESOLVE},
+ {"skip-networking", no_argument, 0, (int) OPT_SKIP_NETWORKING},
{"skip-new", no_argument, 0, (int) OPT_SKIP_NEW},
{"skip-safemalloc", no_argument, 0, (int) OPT_SKIP_SAFEMALLOC},
{"skip-show-database", no_argument, 0, (int) OPT_SKIP_SHOW_DB},
{"skip-slave-start", no_argument, 0, (int) OPT_SKIP_SLAVE_START},
- {"skip-networking", no_argument, 0, (int) OPT_SKIP_NETWORKING},
+ {"skip-stack-trace", no_argument, 0, (int) OPT_SKIP_STACK_TRACE},
{"skip-thread-priority", no_argument, 0, (int) OPT_SKIP_PRIOR},
{"sql-bin-update-same", no_argument, 0, (int) OPT_SQL_BIN_UPDATE_SAME},
#include "sslopt-longopts.h"
@@ -2754,7 +2921,7 @@ CHANGEABLE_VAR changeable_vars[] = {
16384, 1024, 1024*1024L, MALLOC_OVERHEAD, 1024 },
{ "net_retry_count", (long*) &mysqld_net_retry_count,
MYSQLD_NET_RETRY_COUNT, 1, ~0L, 0, 1 },
- { "net_read_timeout", (long*) &net_read_timeout,
+ { "net_read_timeout", (long*) &net_read_timeout,
NET_READ_TIMEOUT, 1, 65535, 0, 1 },
{ "net_write_timeout", (long*) &net_write_timeout,
NET_WRITE_TIMEOUT, 1, 65535, 0, 1 },
@@ -2764,7 +2931,7 @@ CHANGEABLE_VAR changeable_vars[] = {
0, MALLOC_OVERHEAD, (long) ~0, MALLOC_OVERHEAD, IO_SIZE },
{ "record_buffer", (long*) &my_default_record_cache_size,
128*1024L, IO_SIZE*2+MALLOC_OVERHEAD, ~0L, MALLOC_OVERHEAD, IO_SIZE },
- { "slow_launch_time", (long*) &slow_launch_time,
+ { "slow_launch_time", (long*) &slow_launch_time,
2L, 0L, ~0L, 0, 1 },
{ "sort_buffer", (long*) &sortbuff_size,
MAX_SORT_MEMORY, MIN_SORT_MEMORY+MALLOC_OVERHEAD*2, ~0L, MALLOC_OVERHEAD, 1 },
@@ -2842,7 +3009,7 @@ struct show_var_st init_vars[]= {
{"join_buffer_size", (char*) &join_buff_size, SHOW_LONG},
{"key_buffer_size", (char*) &keybuff_size, SHOW_LONG},
{"language", language, SHOW_CHAR},
- {"large_files_support", (char*) &opt_large_files, SHOW_BOOL},
+ {"large_files_support", (char*) &opt_large_files, SHOW_BOOL},
#ifdef HAVE_MLOCKALL
{"locked_in_memory", (char*) &locked_in_memory, SHOW_BOOL},
#endif
@@ -2974,7 +3141,7 @@ static void use_help(void)
{
print_version();
printf("Use '--help' or '--no-defaults --help' for a list of available options\n");
-}
+}
static void usage(void)
{
@@ -3054,15 +3221,16 @@ static void usage(void)
Don't use concurrent insert with MyISAM\n\
--skip-delay-key-write\n\
Ignore the delay_key_write option for all tables\n\
+ --skip-host-cache Don't cache host names\n\
--skip-locking Don't use system locking. To use isamchk one has\n\
to shut down the server.\n\
--skip-name-resolve Don't resolve hostnames.\n\
All hostnames are IP's or 'localhost'\n\
--skip-networking Don't allow connection with TCP/IP.\n\
- --skip-new Don't use new, possible wrong routines.\n\
- --skip-host-cache Don't cache host names\n");
+ --skip-new Don't use new, possible wrong routines.\n");
/* We have to break the string here because of VC++ limits */
puts("\
+ --skip-stack-trace Don't print a stack trace on failure\n\
--skip-show-database Don't allow 'SHOW DATABASE' commands\n\
--skip-thread-priority\n\
Don't give threads different priorities.\n\
@@ -3245,11 +3413,11 @@ static void get_options(int argc,char **argv)
case 'P':
mysql_port= (unsigned int) atoi(optarg);
break;
-#if !defined(DBUG_OFF) && defined(SAFEMALLOC)
+#if !defined(DBUG_OFF) && defined(SAFEMALLOC)
case OPT_SAFEMALLOC_MEM_LIMIT:
safemalloc_mem_limit = atoi(optarg);
break;
-#endif
+#endif
case OPT_SOCKET:
mysql_unix_port= optarg;
break;
@@ -3319,14 +3487,14 @@ static void get_options(int argc,char **argv)
break;
// needs to be handled (as no-op) in non-debugging mode for test suite
case (int)OPT_DISCONNECT_SLAVE_EVENT_COUNT:
-#ifndef DBUG_OFF
+#ifndef DBUG_OFF
disconnect_slave_event_count = atoi(optarg);
-#endif
+#endif
break;
case (int)OPT_ABORT_SLAVE_EVENT_COUNT:
-#ifndef DBUG_OFF
+#ifndef DBUG_OFF
abort_slave_event_count = atoi(optarg);
-#endif
+#endif
break;
case (int) OPT_LOG_SLAVE_UPDATES:
opt_log_slave_updates = 1;
@@ -3508,6 +3676,9 @@ static void get_options(int argc,char **argv)
case (int) OPT_WANT_CORE:
test_flags |= TEST_CORE_ON_SIGNAL;
break;
+ case (int) OPT_SKIP_STACK_TRACE:
+ test_flags|=TEST_NO_STACKTRACE;
+ break;
case (int) OPT_BIND_ADDRESS:
if (optarg && isdigit(optarg[0]))
{
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 98be3639a06..b95b97d670f 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -697,7 +697,9 @@ int SQL_SELECT::test_quick_select(key_map keys_to_use, table_map prev_tables,
** and that all key blocks are half full (normally things are
** much better)
*/
- uint keys_per_block= head->file->block_size/2/head->key_info[param.real_keynr[idx]].key_length+1;
+ uint keys_per_block= head->file->block_size/2/
+ (head->key_info[param.real_keynr[idx]].key_length+
+ head->file->ref_length) + 1;
found_read_time=((double) (found_records+keys_per_block-1)/
(double) keys_per_block);
}
diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt
index 74139b30a85..ff29fffe958 100644
--- a/sql/share/english/errmsg.txt
+++ b/sql/share/english/errmsg.txt
@@ -90,7 +90,7 @@
"File '%-.80s' already exists",
"Records: %ld Deleted: %ld Skipped: %ld Warnings: %ld",
"Records: %ld Duplicates: %ld",
-"Incorrect sub part key. The used key part isn't a string or the used length is longer than the key part",
+"Incorrect sub part key. The used key part isn't a string, the used length is longer than the key part or the table handler doesn't support unique sub keys",
"You can't delete all columns with ALTER TABLE. Use DROP TABLE instead",
"Can't DROP '%-.64s'. Check that column/key exists",
"Records: %ld Duplicates: %ld Warnings: %ld",
diff --git a/sql/slave.cc b/sql/slave.cc
index 0220f574112..6b9c376a625 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -1191,7 +1191,7 @@ pthread_handler_decl(handle_slave,arg __attribute__((unused)))
pthread_cond_broadcast(&COND_slave_start);
pthread_mutex_unlock(&LOCK_slave);
- int error = 1;
+ // int error = 1;
bool retried_once = 0;
ulonglong last_failed_pos = 0;
@@ -1293,9 +1293,19 @@ try again, log '%s' at postion %s", RPL_LOG_NAME,
sql_print_error("Slave thread killed while reading event");
goto err;
}
-
+
+
if (event_len == packet_error)
{
+ if(mc_mysql_errno(mysql) == ER_NET_PACKET_TOO_LARGE)
+ {
+ sql_print_error("Log entry on master is longer than \
+max_allowed_packet on slave. Slave thread will be aborted. If the entry is \
+really supposed to be that long, restart the server with a higher value of \
+max_allowed_packet. The current value is %ld", max_allowed_packet);
+ goto err;
+ }
+
thd->proc_info = "Waiting to reconnect after a failed read";
if(mysql->net.vio)
vio_close(mysql->net.vio);
@@ -1369,7 +1379,7 @@ the slave thread with \"mysqladmin start-slave\". We stopped at log \
}
}
- error = 0;
+ // error = 0;
err:
// print the current replication position
sql_print_error("Slave thread exiting, replication stopped in log '%s' at \
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index a0bb003eeb4..b164242af44 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -1405,6 +1405,7 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type)
&refresh)) && refresh) ;
if (table)
{
+ int error;
table_list->table=table;
table->grant= table_list->grant;
if (thd->locked_tables)
@@ -1416,7 +1417,12 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type)
my_printf_error(ER_TABLE_NOT_LOCKED_FOR_WRITE,
ER(ER_TABLE_NOT_LOCKED_FOR_WRITE),
MYF(0),table_list->name);
- DBUG_RETURN(0);
+ table=0;
+ }
+ else if ((error=table->file->start_stmt(thd)))
+ {
+ table->file->print_error(error,MYF(0));
+ table=0;
}
thd->proc_info=0;
DBUG_RETURN(table);
@@ -1443,10 +1449,10 @@ int open_and_lock_tables(THD *thd,TABLE_LIST *tables)
int lock_tables(THD *thd,TABLE_LIST *tables)
{
+ TABLE_LIST *table;
if (tables && !thd->locked_tables)
{
uint count=0;
- TABLE_LIST *table;
for (table = tables ; table ; table=table->next)
count++;
TABLE **start,**ptr;
@@ -1457,6 +1463,18 @@ int lock_tables(THD *thd,TABLE_LIST *tables)
if (!(thd->lock=mysql_lock_tables(thd,start,count)))
return -1; /* purecov: inspected */
}
+ else
+ {
+ for (table = tables ; table ; table=table->next)
+ {
+ int error;
+ if ((error=table->table->file->start_stmt(thd)))
+ {
+ table->table->file->print_error(error,MYF(0));
+ return -1;
+ }
+ }
+ }
return 0;
}
@@ -1483,8 +1501,7 @@ TABLE *open_temporary_table(THD *thd, const char *path, const char *db,
DBUG_RETURN(0); /* purecov: inspected */
if (openfrm(path, table_name,
- (uint) (HA_OPEN_KEYFILE | HA_OPEN_RNDFILE | HA_GET_INDEX |
- HA_TRY_READ_ONLY),
+ (uint) (HA_OPEN_KEYFILE | HA_OPEN_RNDFILE | HA_GET_INDEX),
READ_KEYINFO | COMPUTE_TYPES | EXTRA_RECORD,
ha_open_options,
tmp_table))
@@ -1493,11 +1510,13 @@ TABLE *open_temporary_table(THD *thd, const char *path, const char *db,
}
tmp_table->file->extra(HA_EXTRA_NO_READCHECK); // Not needed in SQL
- tmp_table->reginfo.lock_type=TL_WRITE; // Simulate locked
- tmp_table->tmp_table = 1;
+ tmp_table->reginfo.lock_type=TL_WRITE; // Simulate locked
+ tmp_table->tmp_table = (tmp_table->file->has_transactions() ?
+ TRANSACTIONAL_TMP_TABLE : TMP_TABLE);
tmp_table->table_cache_key=(char*) (tmp_table+1);
- tmp_table->key_length= (uint) (strmov(strmov(tmp_table->table_cache_key,db)
- +1, table_name)
+ tmp_table->key_length= (uint) (strmov((tmp_table->real_name=
+ strmov(tmp_table->table_cache_key,db)
+ +1), table_name)
- tmp_table->table_cache_key)+1;
int4store(tmp_table->table_cache_key + tmp_table->key_length,
thd->slave_proxy_id);
diff --git a/sql/sql_class.h b/sql/sql_class.h
index fdfa6ec411b..ac6c50d0166 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -71,9 +71,12 @@ public:
~MYSQL_LOG();
pthread_mutex_t* get_log_lock() { return &LOCK_log; }
void set_index_file_name(const char* index_file_name = 0);
+ void init(enum_log_type log_type_arg);
void open(const char *log_name,enum_log_type log_type,
const char *new_name=0);
void new_file(void);
+ bool open_index(int options);
+ void close_index();
bool write(THD *thd, enum enum_server_command command,const char *format,...);
bool write(THD *thd, const char *query, uint query_length,
time_t query_start=0);
@@ -265,7 +268,7 @@ public:
#endif
ulonglong next_insert_id,last_insert_id,current_insert_id, limit_found_rows;
ha_rows select_limit,offset_limit,default_select_limit,cuted_fields,
- max_join_size,sent_row_count;
+ max_join_size, sent_row_count, examined_row_count;
table_map used_tables;
ulong query_id,version, inactive_timeout,options,thread_id;
ulong gemini_spin_retries;
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index b5edf084b53..916af73acae 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -1842,6 +1842,7 @@ mysql_execute_command(void)
{
thd->lock=thd->locked_tables;
thd->locked_tables=0; // Will be automaticly closed
+ end_active_trans(thd);
}
if (thd->global_read_lock)
{
@@ -2293,7 +2294,7 @@ mysql_init_query(THD *thd)
thd->lex.table_list.next= (byte**) &thd->lex.table_list.first;
thd->fatal_error=0; // Safety
thd->last_insert_id_used=thd->query_start_used=thd->insert_id_used=0;
- thd->sent_row_count=0;
+ thd->sent_row_count=thd->examined_row_count=0;
DBUG_VOID_RETURN;
}
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index 05e64670df5..e5039d118be 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -132,7 +132,7 @@ static int send_file(THD *thd)
}
-static File open_log(IO_CACHE *log, const char *log_file_name,
+File open_binlog(IO_CACHE *log, const char *log_file_name,
const char **errmsg)
{
File file;
@@ -294,7 +294,7 @@ void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags)
goto err;
}
- if ((file=open_log(&log, log_file_name, &errmsg)) < 0)
+ if ((file=open_binlog(&log, log_file_name, &errmsg)) < 0)
goto err;
if(pos < 4)
@@ -483,7 +483,7 @@ sweepstakes if you report the bug";
// fake Rotate_log event just in case it did not make it to the log
// otherwise the slave make get confused about the offset
- if ((file=open_log(&log, log_file_name, &errmsg)) < 0 ||
+ if ((file=open_binlog(&log, log_file_name, &errmsg)) < 0 ||
fake_rotate_event(net, packet, log_file_name, &errmsg))
goto err;
@@ -694,7 +694,9 @@ int change_master(THD* thd)
glob_mi.pos = lex_mi->pos;
if(lex_mi->host)
- strmake(glob_mi.host, lex_mi->host, sizeof(glob_mi.host));
+ {
+ strmake(glob_mi.host, lex_mi->host, sizeof(glob_mi.host));
+ }
if(lex_mi->user)
strmake(glob_mi.user, lex_mi->user, sizeof(glob_mi.user));
if(lex_mi->password)
diff --git a/sql/sql_repl.h b/sql/sql_repl.h
index f8a67f51aa2..68f2b4ba6c4 100644
--- a/sql/sql_repl.h
+++ b/sql/sql_repl.h
@@ -9,6 +9,9 @@ extern uint32 server_id;
extern bool server_id_supplied;
extern I_List<i_string> binlog_do_db, binlog_ignore_db;
+File open_binlog(IO_CACHE *log, const char *log_file_name,
+ const char **errmsg);
+
int start_slave(THD* thd = 0, bool net_report = 1);
int stop_slave(THD* thd = 0, bool net_report = 1);
int change_master(THD* thd);
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 2f417fc2618..6262219439d 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -36,7 +36,8 @@ const char *join_type_str[]={ "UNKNOWN","system","const","eq_ref","ref",
static bool make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
DYNAMIC_ARRAY *keyuse,List<Item_func_match> &ftfuncs);
-static bool update_ref_and_keys(DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
+static bool update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,
+ JOIN_TAB *join_tab,
uint tables,COND *conds,table_map table_map,
List<Item_func_match> &ftfuncs);
static int sort_keyuse(KEYUSE *a,KEYUSE *b);
@@ -106,12 +107,14 @@ static uint find_shortest_key(TABLE *table, key_map usable_keys);
static bool test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,
ha_rows select_limit);
static int create_sort_index(JOIN_TAB *tab,ORDER *order,ha_rows select_limit);
-static int remove_duplicates(JOIN *join,TABLE *entry,List<Item> &fields);
+static bool fix_having(JOIN *join, Item **having);
+static int remove_duplicates(JOIN *join,TABLE *entry,List<Item> &fields,
+ Item *having);
static int remove_dup_with_compare(THD *thd, TABLE *entry, Field **field,
- ulong offset);
+ ulong offset,Item *having);
static int remove_dup_with_hash_index(THD *thd, TABLE *table,
uint field_count, Field **first_field,
- ulong key_length);
+ ulong key_length,Item *having);
static int join_init_cache(THD *thd,JOIN_TAB *tables,uint table_count);
static ulong used_blob_length(CACHE_FIELD **ptr);
static bool store_record_in_cache(JOIN_CACHE *cache);
@@ -210,7 +213,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
{
if (item->with_sum_func)
flag|=1;
- else if (!item->const_item())
+ else if (!(flag & 2) && !item->const_item())
flag|=2;
}
if (flag == 3)
@@ -265,7 +268,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
join.join_tab=0;
join.tmp_table_param.copy_field=0;
join.sum_funcs=0;
- join.send_records=join.found_records=0;
+ join.send_records=join.found_records=join.examined_rows=0;
join.tmp_table_param.end_write_records= HA_POS_ERROR;
join.first_record=join.sort_and_group=0;
join.select_options=select_options;
@@ -725,8 +728,11 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
if (select_distinct && ! group)
{
thd->proc_info="Removing duplicates";
- if (remove_duplicates(&join,tmp_table,fields))
- goto err; /* purecov: inspected */
+ if (having)
+ having->update_used_tables();
+ if (remove_duplicates(&join,tmp_table,fields, having))
+ goto err; /* purecov: inspected */
+ having=0;
select_distinct=0;
}
tmp_table->reginfo.lock_type=TL_UNLOCK;
@@ -877,9 +883,9 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
table->reginfo.not_exists_optimize=0;
bzero((char*) table->const_key_parts, sizeof(key_part_map)*table->keys);
all_table_map|= table->map;
+ s->join=join;
if ((s->on_expr=tables->on_expr))
{
- // table->maybe_null=table->outer_join=1; // Mark for send fields
if (!table->file->records)
{ // Empty table
s->key_dependent=s->dependent=0;
@@ -950,7 +956,7 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
}
if (conds || outer_join)
- if (update_ref_and_keys(keyuse_array,stat,join->tables,
+ if (update_ref_and_keys(join->thd,keyuse_array,stat,join->tables,
conds,~outer_join,ftfuncs))
DBUG_RETURN(1);
@@ -1453,8 +1459,9 @@ sort_keyuse(KEYUSE *a,KEYUSE *b)
*/
static bool
-update_ref_and_keys(DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,uint tables,
- COND *cond, table_map normal_tables,List<Item_func_match> &ftfuncs)
+update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
+ uint tables, COND *cond, table_map normal_tables,
+ List<Item_func_match> &ftfuncs)
{
uint and_level,i,found_eq_constant;
@@ -1462,8 +1469,7 @@ update_ref_and_keys(DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,uint tables,
KEY_FIELD *key_fields,*end;
if (!(key_fields=(KEY_FIELD*)
- my_malloc(sizeof(key_fields[0])*
- (current_thd->cond_count+1)*2,MYF(0))))
+ thd->alloc(sizeof(key_fields[0])*(thd->cond_count+1)*2)))
return TRUE; /* purecov: inspected */
and_level=0; end=key_fields;
if (cond)
@@ -1477,14 +1483,10 @@ update_ref_and_keys(DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,uint tables,
}
}
if (init_dynamic_array(keyuse,sizeof(KEYUSE),20,64))
- {
- my_free((gptr) key_fields,MYF(0));
return TRUE;
- }
/* fill keyuse with found key parts */
for (KEY_FIELD *field=key_fields ; field != end ; field++)
add_key_part(keyuse,field);
- my_free((gptr) key_fields,MYF(0));
}
if (ftfuncs.elements)
@@ -1905,7 +1907,7 @@ cache_record_length(JOIN *join,uint idx)
{
uint length;
JOIN_TAB **pos,**end;
- THD *thd=current_thd;
+ THD *thd=join->thd;
length=0;
for (pos=join->best_ref+join->const_tables,end=join->best_ref+idx ;
@@ -2087,7 +2089,7 @@ get_best_combination(JOIN *join)
}
else
{
- THD *thd=current_thd;
+ THD *thd=join->thd;
for (i=0 ; i < keyparts ; keyuse++,i++)
{
while (keyuse->keypart != i ||
@@ -2233,6 +2235,7 @@ make_simple_join(JOIN *join,TABLE *tmp_table)
join_tab->ref.key = -1;
join_tab->not_used_in_distinct=0;
join_tab->read_first_record= join_init_read_record;
+ join_tab->join=join;
bzero((char*) &join_tab->read_record,sizeof(join_tab->read_record));
tmp_table->status=0;
tmp_table->null_row=0;
@@ -2551,8 +2554,11 @@ join_free(JOIN *join)
tab->table->key_read=0;
tab->table->file->extra(HA_EXTRA_NO_KEYREAD);
}
- tab->table->file->index_end();
+ /* Don't free index if we are using read_record */
+ if (!tab->read_record.table)
+ tab->table->file->index_end();
}
+ end_read_record(&tab->read_record);
}
join->table=0;
}
@@ -3390,7 +3396,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
table->db_stat=HA_OPEN_KEYFILE+HA_OPEN_RNDFILE;
table->blob_ptr_size=mi_portable_sizeof_char_ptr;
table->map=1;
- table->tmp_table=1;
+ table->tmp_table= TMP_TABLE;
table->db_low_byte_first=1; // True for HEAP and MyISAM
table->temp_pool_slot = temp_pool_slot;
@@ -3931,8 +3937,8 @@ bool create_myisam_from_heap(TABLE *table, TMP_TABLE_PARAM *param, int error,
table->file=0;
*table =new_table;
table->file->change_table_ptr(table);
-
- thd->proc_info=save_proc_info;
+ thd->proc_info= (!strcmp(save_proc_info,"Copying to tmp table") ?
+ "Copying to tmp table on disk" : save_proc_info);
DBUG_RETURN(0);
err:
@@ -4112,6 +4118,7 @@ sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records)
bool not_used_in_distinct=join_tab->not_used_in_distinct;
ha_rows found_records=join->found_records;
READ_RECORD *info= &join_tab->read_record;
+ join->examined_rows++;
do
{
@@ -4446,7 +4453,8 @@ join_init_read_record(JOIN_TAB *tab)
{
if (tab->select && tab->select->quick)
tab->select->quick->reset();
- init_read_record(&tab->read_record,current_thd, tab->table, tab->select,1,1);
+ init_read_record(&tab->read_record, tab->join->thd, tab->table,
+ tab->select,1,1);
return (*tab->read_record.read_record)(&tab->read_record);
}
@@ -4499,6 +4507,7 @@ join_init_read_next_with_key(READ_RECORD *info)
return 0;
}
+
static int
join_init_read_last_with_key(JOIN_TAB *tab)
{
@@ -4669,7 +4678,11 @@ end_send_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
else
{
if (!join->first_record)
+ {
+ /* No matching rows for group function */
clear_tables(join);
+ copy_fields(&join->tmp_table_param);
+ }
if (join->having && join->having->val_int() == 0)
error= -1; // Didn't satisfy having
else
@@ -4914,7 +4927,11 @@ end_write_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
if (idx < (int) join->send_group_parts)
{
if (!join->first_record)
+ {
+ /* No matching rows for group function */
clear_tables(join);
+ copy_fields(&join->tmp_table_param);
+ }
copy_sum_funcs(join->sum_funcs);
if (!join->having || join->having->val_int())
{
@@ -5235,6 +5252,7 @@ create_sort_index(JOIN_TAB *tab,ORDER *order,ha_rows select_limit)
{
SORT_FIELD *sortorder;
uint length;
+ ha_rows examined_rows;
TABLE *table=tab->table;
SQL_SELECT *select=tab->select;
DBUG_ENTER("create_sort_index");
@@ -5273,12 +5291,13 @@ create_sort_index(JOIN_TAB *tab,ORDER *order,ha_rows select_limit)
}
}
table->found_records=filesort(&table,sortorder,length,
- select, 0L, select_limit);
+ select, 0L, select_limit, &examined_rows);
delete select; // filesort did select
tab->select=0;
tab->select_cond=0;
tab->type=JT_ALL; // Read with normal read_record
tab->read_first_record= join_init_read_record;
+ tab->join->examined_rows+=examined_rows;
if (table->key_read) // Restore if we used indexes
{
table->key_read=0;
@@ -5290,6 +5309,38 @@ err:
}
+/*
+** Add the HAVING criteria to table->select
+*/
+
+static bool fix_having(JOIN *join, Item **having)
+{
+ (*having)->update_used_tables(); // Some tables may have been const
+ JOIN_TAB *table=&join->join_tab[join->const_tables];
+ table_map used_tables= join->const_table_map | table->table->map;
+
+ Item* sort_table_cond=make_cond_for_table(*having,used_tables,used_tables);
+ if (sort_table_cond)
+ {
+ if (!table->select)
+ if (!(table->select=new SQL_SELECT))
+ return 1;
+ if (!table->select->cond)
+ table->select->cond=sort_table_cond;
+ else // This should never happen
+ if (!(table->select->cond=new Item_cond_and(table->select->cond,
+ sort_table_cond)))
+ return 1;
+ table->select_cond=table->select->cond;
+ DBUG_EXECUTE("where",print_where(table->select_cond,
+ "select and having"););
+ *having=make_cond_for_table(*having,~ (table_map) 0,~used_tables);
+ DBUG_EXECUTE("where",print_where(*having,"having after make_cond"););
+ }
+ return 0;
+}
+
+
/*****************************************************************************
** Remove duplicates from tmp table
** This should be recoded to add a uniuqe index to the table and remove
@@ -5330,7 +5381,7 @@ static void free_blobs(Field **ptr)
static int
-remove_duplicates(JOIN *join, TABLE *entry,List<Item> &fields)
+remove_duplicates(JOIN *join, TABLE *entry,List<Item> &fields, Item *having)
{
int error;
ulong reclength,offset;
@@ -5367,9 +5418,10 @@ remove_duplicates(JOIN *join, TABLE *entry,List<Item> &fields)
sortbuff_size)))
error=remove_dup_with_hash_index(join->thd, entry,
field_count, first_field,
- reclength);
+ reclength, having);
else
- error=remove_dup_with_compare(join->thd, entry, first_field, offset);
+ error=remove_dup_with_compare(join->thd, entry, first_field, offset,
+ having);
free_blobs(first_field);
DBUG_RETURN(error);
@@ -5377,19 +5429,19 @@ remove_duplicates(JOIN *join, TABLE *entry,List<Item> &fields)
static int remove_dup_with_compare(THD *thd, TABLE *table, Field **first_field,
- ulong offset)
+ ulong offset, Item *having)
{
handler *file=table->file;
- char *org_record,*new_record;
+ char *org_record,*new_record, *record;
int error;
ulong reclength=table->reclength-offset;
DBUG_ENTER("remove_dup_with_compare");
- org_record=(char*) table->record[0]+offset;
+ org_record=(char*) (record=table->record[0])+offset;
new_record=(char*) table->record[1]+offset;
file->rnd_init();
- error=file->rnd_next(table->record[0]);
+ error=file->rnd_next(record);
for (;;)
{
if (thd->killed)
@@ -5406,6 +5458,12 @@ static int remove_dup_with_compare(THD *thd, TABLE *table, Field **first_field,
break;
goto err;
}
+ if (having && !having->val_int())
+ {
+ if ((error=file->delete_row(record)))
+ goto err;
+ continue;
+ }
if (copy_blobs(first_field))
{
my_error(ER_OUT_OF_SORTMEMORY,MYF(0));
@@ -5418,7 +5476,7 @@ static int remove_dup_with_compare(THD *thd, TABLE *table, Field **first_field,
bool found=0;
for (;;)
{
- if ((error=file->rnd_next(table->record[0])))
+ if ((error=file->rnd_next(record)))
{
if (error == HA_ERR_RECORD_DELETED)
continue;
@@ -5428,19 +5486,19 @@ static int remove_dup_with_compare(THD *thd, TABLE *table, Field **first_field,
}
if (compare_record(table, first_field) == 0)
{
- if ((error=file->delete_row(table->record[0])))
+ if ((error=file->delete_row(record)))
goto err;
}
else if (!found)
{
found=1;
- file->position(table->record[0]); // Remember position
+ file->position(record); // Remember position
}
}
if (!found)
break; // End of file
/* Restart search on next row */
- error=file->restart_rnd_next(table->record[0],file->ref);
+ error=file->restart_rnd_next(record,file->ref);
}
file->extra(HA_EXTRA_NO_CACHE);
@@ -5461,7 +5519,8 @@ err:
static int remove_dup_with_hash_index(THD *thd, TABLE *table,
uint field_count,
Field **first_field,
- ulong key_length)
+ ulong key_length,
+ Item *having)
{
byte *key_buffer, *key_pos, *record=table->record[0];
int error;
@@ -5509,6 +5568,12 @@ static int remove_dup_with_hash_index(THD *thd, TABLE *table,
break;
goto err;
}
+ if (having && !having->val_int())
+ {
+ if ((error=file->delete_row(record)))
+ goto err;
+ continue;
+ }
/* copy fields to key buffer */
field_length=field_lengths;
@@ -5524,7 +5589,8 @@ static int remove_dup_with_hash_index(THD *thd, TABLE *table,
if ((error=file->delete_row(record)))
goto err;
}
- (void) hash_insert(&hash, key_pos-key_length);
+ else
+ (void) hash_insert(&hash, key_pos-key_length);
key_pos+=extra_length;
}
my_free((char*) key_buffer,MYF(0));
diff --git a/sql/sql_select.h b/sql/sql_select.h
index 9539bb14842..87157b1465f 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -102,6 +102,7 @@ typedef struct st_join_table {
bool cached_eq_ref_table,eq_ref_table,not_used_in_distinct;
TABLE_REF ref;
JOIN_CACHE cache;
+ JOIN *join;
} JOIN_TAB;
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index faa899b719f..ac89b7a2782 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -786,7 +786,10 @@ store_create_info(THD *thd, TABLE *table, String *packet)
List<Item> field_list;
char tmp[MAX_FIELD_WIDTH];
String type(tmp, sizeof(tmp));
- packet->append("CREATE TABLE ", 13);
+ if (table->tmp_table)
+ packet->append("CREATE TEMPORARY TABLE ", 23);
+ else
+ packet->append("CREATE TABLE ", 13);
append_identifier(thd,packet,table->real_name);
packet->append(" (\n", 3);
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 77aaf1edae4..ad39b91a5ca 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -479,12 +479,16 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
}
}
else if (column->length > length ||
- (f_is_packed(sql_field->pack_flag) && column->length != length))
+ ((f_is_packed(sql_field->pack_flag) ||
+ ((file->option_flag() & HA_NO_PREFIX_CHAR_KEYS) &&
+ (key_info->flags & HA_NOSAME))) &&
+ column->length != length))
{
my_error(ER_WRONG_SUB_KEY,MYF(0));
DBUG_RETURN(-1);
}
- length=column->length;
+ if (!(file->option_flag() & HA_NO_PREFIX_CHAR_KEYS))
+ length=column->length;
}
else if (length == 0)
{
@@ -1426,21 +1430,20 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
create_info,
create_list,key_list,1,1))) // no logging
DBUG_RETURN(error);
+
+ if (table->tmp_table)
+ new_table=open_table(thd,new_db,tmp_name,tmp_name,0);
+ else
{
- if (table->tmp_table)
- new_table=open_table(thd,new_db,tmp_name,tmp_name,0);
- else
- {
- char path[FN_REFLEN];
- (void) sprintf(path,"%s/%s/%s",mysql_data_home,new_db,tmp_name);
- fn_format(path,path,"","",4);
- new_table=open_temporary_table(thd, path, new_db, tmp_name,0);
- }
- if (!new_table)
- {
- VOID(quick_rm_table(new_db_type,new_db,tmp_name));
- goto err;
- }
+ char path[FN_REFLEN];
+ (void) sprintf(path,"%s/%s/%s",mysql_data_home,new_db,tmp_name);
+ fn_format(path,path,"","",4);
+ new_table=open_temporary_table(thd, path, new_db, tmp_name,0);
+ }
+ if (!new_table)
+ {
+ VOID(quick_rm_table(new_db_type,new_db,tmp_name));
+ goto err;
}
save_time_stamp=new_table->time_stamp;
@@ -1633,6 +1636,7 @@ copy_data_between_tables(TABLE *from,TABLE *to,
TABLE_LIST tables;
List<Item> fields;
List<Item> all_fields;
+ ha_rows examined_rows;
DBUG_ENTER("copy_data_between_tables");
if (!(copy= new Copy_field[to->fields]))
@@ -1668,7 +1672,8 @@ copy_data_between_tables(TABLE *from,TABLE *to,
if (setup_order(thd, &tables, fields, all_fields, order) ||
!(sortorder=make_unireg_sortorder(order, &length)) ||
(from->found_records = filesort(&from, sortorder, length,
- (SQL_SELECT *) 0, 0L, HA_POS_ERROR))
+ (SQL_SELECT *) 0, 0L, HA_POS_ERROR,
+ &examined_rows))
== HA_POS_ERROR)
goto err;
};
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 357ba41046c..33c0a4d1758 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -72,339 +72,220 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token END_OF_INPUT
-%token ACTION
+%token EQ
+%token EQUAL_SYM
+%token GE
+%token GT_SYM
+%token LE
+%token LT
+%token NE
+%token IS
+%token SHIFT_LEFT
+%token SHIFT_RIGHT
+%token SET_VAR
+
+%token AVG_SYM
+%token COUNT_SYM
+%token MAX_SYM
+%token MIN_SYM
+%token SUM_SYM
+%token STD_SYM
+
%token ADD
+%token ALTER
%token AFTER_SYM
-%token AGAINST
+%token ANALYZE_SYM
+%token BEGIN_SYM
+%token CHANGE
+%token COMMENT_SYM
+%token COMMIT_SYM
+%token CREATE
+%token CROSS
+%token DELETE_SYM
+%token DROP
+%token INSERT
+%token FLUSH_SYM
+%token SELECT_SYM
+%token MASTER_SYM
+%token REPAIR
+%token RESET_SYM
+%token PURGE
+%token SLAVE
+%token START_SYM
+%token STOP_SYM
+%token TRUNCATE_SYM
+%token ROLLBACK_SYM
+%token OPTIMIZE
+%token SHOW
+%token UPDATE_SYM
+%token KILL_SYM
+%token LOAD
+%token LOCK_SYM
+%token UNLOCK_SYM
+
+%token ACTION
%token AGGREGATE_SYM
%token ALL
-%token ALTER
-%token ANALYZE_SYM
%token AND
%token AS
%token ASC
-%token ATAN
-%token AUTOCOMMIT
%token AUTO_INC
+%token AUTOCOMMIT
%token AVG_ROW_LENGTH
-%token AVG_SYM
-%token BACKUP_SYM
-%token BEGIN_SYM
-%token BENCHMARK_SYM
+%token BACKUP_SYM
%token BERKELEY_DB_SYM
-%token BETWEEN_SYM
-%token BIGINT
%token BINARY
-%token BIT_AND
-%token BIT_OR
%token BIT_SYM
-%token BLOB_SYM
%token BOOL_SYM
%token BOTH
%token BY
%token CASCADE
-%token CASE_SYM
-%token CHANGE
-%token CHANGED
-%token CHAR_SYM
%token CHECKSUM_SYM
%token CHECK_SYM
-%token COALESCE
-%token CLOSE_SYM
+%token COMMITTED_SYM
%token COLUMNS
%token COLUMN_SYM
-%token COMMENT_SYM
-%token COMMITTED_SYM
-%token COMMIT_SYM
-%token COMPRESSED_SYM
-%token CONCAT
-%token CONCAT_WS
+%token CONCURRENT
%token CONSTRAINT
-%token COUNT_SYM
-%token CREATE
-%token CROSS
-%token CURDATE
-%token CURTIME
-%token DATABASE
%token DATABASES
%token DATA_SYM
-%token DATETIME
-%token DATE_ADD_INTERVAL
-%token DATE_SUB_INTERVAL
-%token DATE_SYM
-%token DAY_HOUR_SYM
-%token DAY_MINUTE_SYM
-%token DAY_SECOND_SYM
-%token DAY_SYM
-%token DECIMAL_SYM
-%token DECODE_SYM
%token DEFAULT
%token DELAYED_SYM
%token DELAY_KEY_WRITE_SYM
-%token DELETE_SYM
%token DESC
%token DESCRIBE
%token DISTINCT
-%token DOUBLE_SYM
-%token DROP
-%token DUMPFILE
%token DYNAMIC_SYM
-%token ELSE
-%token ELT_FUNC
%token ENCLOSED
-%token ENCODE_SYM
-%token ENCRYPT
-%token END
-%token ENUM
-%token EQ
-%token EQUAL_SYM
%token ESCAPED
%token ESCAPE_SYM
%token EXISTS
-%token EXPORT_SET
%token EXTENDED_SYM
-%token EXTRACT_SYM
-%token FAST_SYM
-%token FIELD_FUNC
%token FILE_SYM
%token FIRST_SYM
%token FIXED_SYM
%token FLOAT_NUM
-%token FLOAT_SYM
-%token FLUSH_SYM
%token FOREIGN
-%token FORMAT_SYM
-%token FOR_SYM
%token FROM
-%token FROM_UNIXTIME
%token FULL
-%token FULLTEXT_SYM
-%token FUNC_ARG0
-%token FUNC_ARG1
-%token FUNC_ARG2
-%token FUNC_ARG3
-%token GE
+%token FULLTEXT_SYM
+%token GEMINI_SYM
%token GEMINI_SPIN_RETRIES
-%token GEMINI_SYM
-%token GLOBAL_SYM
+%token GLOBAL_SYM
%token GRANT
%token GRANTS
%token GREATEST_SYM
%token GROUP
-%token GROUP_UNIQUE_USERS
-%token GT_SYM
%token HAVING
-%token HANDLER_SYM
%token HEAP_SYM
%token HEX_NUM
%token HIGH_PRIORITY
%token HOSTS_SYM
-%token HOUR_MINUTE_SYM
-%token HOUR_SECOND_SYM
-%token HOUR_SYM
%token IDENT
-%token IDENTIFIED_SYM
-%token IF
%token IGNORE_SYM
%token INDEX
%token INFILE
%token INNER_SYM
%token INNOBASE_SYM
-%token INSERT
-%token INSERT_ID
-%token INTERVAL_SYM
%token INTO
-%token INT_SYM
%token IN_SYM
-%token IS
+%token ISOLATION
%token ISAM_SYM
-%token ISOLATION
%token JOIN_SYM
%token KEYS
%token KEY_SYM
-%token KILL_SYM
-%token LAST_INSERT_ID
-%token LAST_SYM
-%token LE
%token LEADING
%token LEAST_SYM
-%token LEFT
-%token LEVEL_SYM
+%token LEVEL_SYM
%token LEX_HOSTNAME
%token LIKE
-%token LIMIT
%token LINES
-%token LOAD
%token LOCAL_SYM
-%token LOCATE
-%token LOCK_SYM
%token LOGS_SYM
-%token LONGBLOB
-%token LONGTEXT
%token LONG_NUM
%token LONG_SYM
%token LOW_PRIORITY
-%token LT
-%token MAKE_SET_SYM
-%token MASTER_CONNECT_RETRY_SYM
-%token MASTER_HOST_SYM
-%token MASTER_LOG_FILE_SYM
-%token MASTER_LOG_POS_SYM
-%token MASTER_PASSWORD_SYM
-%token MASTER_PORT_SYM
-%token MASTER_SYM
-%token MASTER_USER_SYM
+%token MASTER_HOST_SYM
+%token MASTER_USER_SYM
+%token MASTER_LOG_FILE_SYM
+%token MASTER_LOG_POS_SYM
+%token MASTER_PASSWORD_SYM
+%token MASTER_PORT_SYM
+%token MASTER_CONNECT_RETRY_SYM
%token MATCH
%token MAX_ROWS
-%token MAX_SYM
-%token MEDIUMBLOB
-%token MEDIUMINT
-%token MEDIUMTEXT
%token MEDIUM_SYM
%token MERGE_SYM
-%token MINUTE_SECOND_SYM
-%token MINUTE_SYM
%token MIN_ROWS
-%token MIN_SYM
-%token MODE_SYM
-%token MODIFY_SYM
-%token MONTH_SYM
%token MYISAM_SYM
%token NATIONAL_SYM
%token NATURAL
%token NCHAR_SYM
-%token NE
-%token NEXT_SYM
%token NOT
-%token NOW_SYM
%token NO_SYM
%token NULL_SYM
%token NUM
-%token NUMERIC_SYM
%token ON
%token OPEN_SYM
-%token OPTIMIZE
%token OPTION
%token OPTIONALLY
%token OR
-%token ORDER_SYM
%token OR_OR_CONCAT
+%token ORDER_SYM
%token OUTER
%token OUTFILE
+%token DUMPFILE
%token PACK_KEYS_SYM
%token PARTIAL
-%token PASSWORD
-%token POSITION_SYM
-%token PRECISION
-%token PREV_SYM
%token PRIMARY_SYM
%token PRIVILEGES
-%token PROCEDURE
%token PROCESS
%token PROCESSLIST_SYM
-%token PURGE
-%token QUICK
%token RAID_0_SYM
-%token RAID_CHUNKS
-%token RAID_CHUNKSIZE
%token RAID_STRIPED_SYM
%token RAID_TYPE
-%token RAND
+%token RAID_CHUNKS
+%token RAID_CHUNKSIZE
%token READ_SYM
-%token REAL
%token REAL_NUM
%token REFERENCES
%token REGEXP
%token RELOAD
%token RENAME
-%token REPAIR
%token REPEATABLE_SYM
-%token REPLACE
-%token RESET_SYM
-%token RESTORE_SYM
+%token RESTORE_SYM
%token RESTRICT
%token REVOKE
-%token RIGHT
-%token ROLLBACK_SYM
-%token ROUND
%token ROWS_SYM
%token ROW_FORMAT_SYM
%token ROW_SYM
-%token SECOND_SYM
-%token SELECT_SYM
+%token SET
%token SERIALIZABLE_SYM
%token SESSION_SYM
-%token SET
-%token SET_VAR
-%token SHARE_SYM
-%token SHIFT_LEFT
-%token SHIFT_RIGHT
-%token SHOW
%token SHUTDOWN
-%token SLAVE
-%token SMALLINT
-%token SQL_AUTO_IS_NULL
-%token SQL_BIG_RESULT
-%token SQL_BIG_SELECTS
-%token SQL_BIG_TABLES
-%token SQL_BUFFER_RESULT
-%token SQL_LOG_BIN
-%token SQL_LOG_OFF
-%token SQL_LOG_UPDATE
-%token SQL_LOW_PRIORITY_UPDATES
-%token SQL_MAX_JOIN_SIZE
-%token SQL_QUOTE_SHOW_CREATE
-%token SQL_SAFE_UPDATES
-%token SQL_SELECT_LIMIT
-%token SQL_SMALL_RESULT
-%token SQL_WARNINGS
%token STARTING
-%token START_SYM
%token STATUS_SYM
-%token STD_SYM
-%token STOP_SYM
%token STRAIGHT_JOIN
-%token STRING_SYM
-%token SUBSTRING
-%token SUBSTRING_INDEX
-%token SUM_SYM
%token TABLES
%token TABLE_SYM
%token TEMPORARY
%token TERMINATED
%token TEXT_STRING
-%token TEXT_SYM
-%token THEN_SYM
-%token TIMESTAMP
-%token TIME_SYM
-%token TINYBLOB
-%token TINYINT
-%token TINYTEXT
%token TO_SYM
%token TRAILING
%token TRANSACTION_SYM
-%token TRIM
-%token TRUNCATE_SYM
%token TYPE_SYM
-%token UDA_CHAR_SUM
-%token UDA_FLOAT_SUM
-%token UDA_INT_SUM
-%token UDF_CHAR_FUNC
-%token UDF_FLOAT_FUNC
-%token UDF_INT_FUNC
+%token FUNC_ARG0
+%token FUNC_ARG1
+%token FUNC_ARG2
+%token FUNC_ARG3
%token UDF_RETURNS_SYM
%token UDF_SONAME_SYM
%token UDF_SYM
-%token UNCOMMITTED_SYM
+%token UNCOMMITTED_SYM
%token UNION_SYM
%token UNIQUE_SYM
-%token UNIQUE_USERS
-%token UNIX_TIMESTAMP
-%token UNLOCK_SYM
-%token UNSIGNED
-%token UPDATE_SYM
%token USAGE
-%token USER
%token USE_SYM
%token USING
%token VALUES
@@ -418,6 +299,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token BLOB_SYM
%token CHAR_SYM
%token CHANGED
+%token COALESCE
%token DATETIME
%token DATE_SYM
%token DECIMAL_SYM
@@ -426,6 +308,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token FAST_SYM
%token FLOAT_SYM
%token INT_SYM
+%token LIMIT
%token LONGBLOB
%token LONGTEXT
%token MEDIUMBLOB
@@ -446,18 +329,85 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token UNSIGNED
%token VARBINARY
%token VARCHAR
-%token VARIABLES
%token VARYING
+%token ZEROFILL
+
+%token AGAINST
+%token ATAN
+%token BETWEEN_SYM
+%token BIT_AND
+%token BIT_OR
+%token CASE_SYM
+%token CONCAT
+%token CONCAT_WS
+%token CURDATE
+%token CURTIME
+%token DATABASE
+%token DATE_ADD_INTERVAL
+%token DATE_SUB_INTERVAL
+%token DAY_HOUR_SYM
+%token DAY_MINUTE_SYM
+%token DAY_SECOND_SYM
+%token DAY_SYM
+%token DECODE_SYM
+%token ELSE
+%token ELT_FUNC
+%token ENCODE_SYM
+%token ENCRYPT
+%token EXPORT_SET
+%token EXTRACT_SYM
+%token FIELD_FUNC
+%token FORMAT_SYM
+%token FOR_SYM
+%token FROM_UNIXTIME
+%token GROUP_UNIQUE_USERS
+%token HOUR_MINUTE_SYM
+%token HOUR_SECOND_SYM
+%token HOUR_SYM
+%token IDENTIFIED_SYM
+%token IF
+%token INSERT_ID
+%token INTERVAL_SYM
+%token LAST_INSERT_ID
+%token LEFT
+%token LOCATE
+%token MAKE_SET_SYM
+%token MINUTE_SECOND_SYM
+%token MINUTE_SYM
+%token MODE_SYM
+%token MODIFY_SYM
+%token MONTH_SYM
+%token NOW_SYM
+%token PASSWORD
+%token POSITION_SYM
+%token PROCEDURE
+%token RAND
+%token REPLACE
+%token RIGHT
+%token ROUND
+%token SECOND_SYM
+%token SHARE_SYM
+%token SUBSTRING
+%token SUBSTRING_INDEX
+%token TRIM
+%token UDA_CHAR_SUM
+%token UDA_FLOAT_SUM
+%token UDA_INT_SUM
+%token UDF_CHAR_FUNC
+%token UDF_FLOAT_FUNC
+%token UDF_INT_FUNC
+%token UNIQUE_USERS
+%token UNIX_TIMESTAMP
+%token USER
%token WEEK_SYM
%token WHEN_SYM
-%token WHERE
-%token WITH
-%token WORK_SYM
-%token WRITE_SYM
-%token YEARWEEK
+%token WORK_SYM
%token YEAR_MONTH_SYM
%token YEAR_SYM
-%token ZEROFILL
+%token YEARWEEK
+%token BENCHMARK_SYM
+%token END
+%token THEN_SYM
%token SQL_BIG_TABLES
%token SQL_BIG_SELECTS
@@ -472,7 +422,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token SQL_BUFFER_RESULT
%token SQL_WARNINGS
%token SQL_AUTO_IS_NULL
-%token SQL_CALC_FOUND_ROWS
%token SQL_SAFE_UPDATES
%token SQL_QUOTE_SHOW_CREATE
%token SQL_SLAVE_SKIP_COUNTER
@@ -2441,6 +2390,12 @@ opt_local:
/* empty */ { $$=0;}
| LOCAL_SYM { $$=1;}
+load_data_lock:
+ /* empty */ { Lex->lock_option= current_thd->update_lock_default; }
+ | CONCURRENT { Lex->lock_option= TL_WRITE_CONCURRENT_INSERT ; }
+ | LOW_PRIORITY { Lex->lock_option= TL_WRITE_LOW_PRIORITY; }
+
+
opt_duplicate:
/* empty */ { Lex->duplicates=DUP_ERROR; }
| REPLACE { Lex->duplicates=DUP_REPLACE; }
@@ -2599,6 +2554,7 @@ keyword:
| COMMIT_SYM {}
| COMMITTED_SYM {}
| COMPRESSED_SYM {}
+ | CONCURRENT {}
| DATA_SYM {}
| DATETIME {}
| DATE_SYM {}
diff --git a/sql/table.h b/sql/table.h
index a0e037222dc..706c499d852 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -41,6 +41,8 @@ typedef struct st_grant_info
uint want_privilege;
} GRANT_INFO;
+enum tmp_table_type {NO_TMP_TABLE=0, TMP_TABLE=1, TRANSACTIONAL_TMP_TABLE=2};
+
/* Table cache entry struct */
class Field_timestamp;
@@ -83,10 +85,11 @@ struct st_table {
uint blob_ptr_size; /* 4 or 8 */
uint next_number_key_offset;
int current_lock; /* Type of lock on table */
+ enum tmp_table_type tmp_table;
my_bool copy_blobs; /* copy_blobs when storing */
my_bool null_row; /* All columns are null */
my_bool maybe_null,outer_join; /* Used with OUTER JOIN */
- my_bool distinct,tmp_table,const_table;
+ my_bool distinct,const_table;
my_bool key_read;
my_bool crypted;
my_bool db_low_byte_first; /* Portable row format */