summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/ha_innodb.cc177
-rw-r--r--sql/ha_innodb.h5
-rw-r--r--sql/handler.cc43
-rw-r--r--sql/my_lock.c17
-rw-r--r--sql/mysql_priv.h7
-rw-r--r--sql/mysqld.cc50
-rw-r--r--sql/sql_lex.cc2
-rw-r--r--sql/sql_lex.h1
-rw-r--r--sql/sql_load.cc2
-rw-r--r--sql/sql_parse.cc122
-rw-r--r--sql/sql_select.cc10
-rw-r--r--sql/sql_table.cc33
-rw-r--r--sql/sql_yacc.yy12
-rw-r--r--sql/unireg.cc4
-rw-r--r--sql/unireg.h5
15 files changed, 264 insertions, 226 deletions
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index f99e677913e..4cf06dfb731 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & InnoDB Oy
+/* Copyright (C) 2000 MySQL AB & InnoDB Oy
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -85,8 +85,8 @@ long innobase_mirrored_log_groups, innobase_log_files_in_group,
char *innobase_data_home_dir;
char *innobase_log_group_home_dir, *innobase_log_arch_dir;
char *innobase_unix_file_flush_method;
-bool innobase_flush_log_at_trx_commit, innobase_log_archive,
- innobase_use_native_aio, innobase_fast_shutdown;
+my_bool innobase_flush_log_at_trx_commit, innobase_log_archive,
+ innobase_use_native_aio, innobase_fast_shutdown;
/*
Set default InnoDB size to 64M, to let users use InnoDB without having
@@ -235,7 +235,7 @@ convert_error_code_to_mysql(
extern "C" {
/*****************************************************************
Prints info of a THD object (== user session thread) to the
-standatd output. NOTE that mysql/innobase/trx/trx0trx.c must contain
+standard output. NOTE that mysql/innobase/trx/trx0trx.c must contain
the prototype for this function! */
void
@@ -304,6 +304,8 @@ check_trx_exists(
thd->transaction.stmt.innobase_tid =
(void*)&innodb_dummy_stmt_trx_handle;
+ } else {
+ ut_a(trx->magic_n == TRX_MAGIC_N);
}
return(trx);
@@ -841,6 +843,7 @@ innobase_close_connection(
whose transaction should be rolled back */
{
if (NULL != thd->transaction.all.innobase_tid) {
+
trx_rollback_for_mysql((trx_t*)
(thd->transaction.all.innobase_tid));
trx_free_for_mysql((trx_t*)
@@ -984,7 +987,10 @@ ha_innobase::open(
/* Get pointer to a table object in InnoDB dictionary cache */
- if (NULL == (ib_table = dict_table_get(norm_name, NULL))) {
+ ib_table = dict_table_get_and_increment_handle_count(
+ norm_name, NULL);
+
+ if (NULL == ib_table) {
sql_print_error("InnoDB error:\n\
Cannot find table %s from the internal data dictionary\n\
@@ -2465,44 +2471,6 @@ ha_innobase::position(
ref_stored_len = len;
}
-/***********************************************************************
-Tells something additional to the handler about how to do things. */
-
-int
-ha_innobase::extra(
-/*===============*/
- /* out: 0 or error number */
- enum ha_extra_function operation)
- /* in: HA_EXTRA_DONT_USE_CURSOR_TO_UPDATE */
-{
- row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
-
- switch (operation) {
- case HA_EXTRA_RESET:
- case HA_EXTRA_RESET_STATE:
- prebuilt->read_just_key = 0;
- break;
- case HA_EXTRA_NO_KEYREAD:
- prebuilt->read_just_key = 0;
- break;
- case HA_EXTRA_DONT_USE_CURSOR_TO_UPDATE:
- prebuilt->in_update_remember_pos = FALSE;
- break;
- case HA_EXTRA_KEYREAD:
- prebuilt->read_just_key = 1;
- break;
- default:/* Do nothing */
- ;
- }
-
- return(0);
-}
-
-int ha_innobase::reset(void)
-{
- return(0);
-}
-
/*********************************************************************
Creates a table definition to an InnoDB database. */
@@ -2866,7 +2834,9 @@ innobase_drop_database(
memcpy(namebuf, ptr, len);
namebuf[len] = '/';
namebuf[len + 1] = '\0';
-
+#ifdef __WIN__
+ casedn_str(namebuf);
+#endif
trx = trx_allocate_for_mysql();
error = row_drop_database_for_mysql(namebuf, trx);
@@ -2981,9 +2951,9 @@ ha_innobase::records_in_range(
DBUG_ENTER("records_in_range");
- if (prebuilt->trx) {
- prebuilt->trx->op_info = (char*) "estimating range size";
- }
+ /* Warning: since it is not sure that MySQL calls external_lock
+ before calling this function, the trx field in prebuilt can be
+ obsolete! */
active_index = keynr;
@@ -3017,10 +2987,6 @@ ha_innobase::records_in_range(
my_free((char*) key_val_buff2, MYF(0));
- if (prebuilt->trx) {
- prebuilt->trx->op_info = (char*) "";
- }
-
DBUG_RETURN((ha_rows) n_rows);
}
@@ -3041,10 +3007,9 @@ ha_innobase::estimate_number_of_rows(void)
ulonglong estimate;
ulonglong data_file_length;
- if (prebuilt->trx) {
- prebuilt->trx->op_info =
- (char*) "estimating upper bound of table size";
- }
+ /* Warning: since it is not sure that MySQL calls external_lock
+ before calling this function, the trx field in prebuilt can be
+ obsolete! */
DBUG_ENTER("info");
@@ -3061,10 +3026,6 @@ ha_innobase::estimate_number_of_rows(void)
estimate = 2 * data_file_length / dict_index_calc_min_rec_len(index);
- if (prebuilt->trx) {
- prebuilt->trx->op_info = (char*) "";
- }
-
DBUG_RETURN((ha_rows) estimate);
}
@@ -3080,10 +3041,12 @@ ha_innobase::scan_time()
{
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
- /* In the following formula we assume that scanning 10 pages
- takes the same time as a disk seek: */
-
- return((double) (prebuilt->table->stat_clustered_index_size / 10));
+ /* Since MySQL seems to favor table scans too much over index
+ searches, we pretend that a sequential read takes the same time
+ as a random disk read, that is, we do not divide the following
+ by 10, which would be physically realistic. */
+
+ return((double) (prebuilt->table->stat_clustered_index_size));
}
/*************************************************************************
@@ -3104,9 +3067,9 @@ ha_innobase::info(
DBUG_ENTER("info");
- if (prebuilt->trx) {
- prebuilt->trx->op_info = (char*) "calculating table stats";
- }
+ /* Warning: since it is not sure that MySQL calls external_lock
+ before calling this function, the trx field in prebuilt can be
+ obsolete! */
ib_table = prebuilt->table;
@@ -3154,25 +3117,17 @@ ha_innobase::info(
index->stat_n_diff_key_vals[j + 1]);
}
+ /* Since MySQL seems to favor table scans
+ too much over index searches, we pretend
+ index selectivity is 2 times better than
+ our estimate: */
+
+ rec_per_key = rec_per_key / 2;
+
if (rec_per_key == 0) {
rec_per_key = 1;
}
- /* Since the MySQL optimizer is often too
- pessimistic in the assumption that a table
- does not fit in the buffer pool, we
- increase the attractiveness of indexes
- by assuming the selectivity of any prefix
- of an index is 1 / 100 or better.
- (Actually, we should look at the table
- size, and if the table is smaller than
- the buffer pool, we should uniformly
- increase the attractiveness of indexes,
- regardless of the estimated selectivity.) */
-
- if (rec_per_key > records / 100) {
- rec_per_key = records / 100;
- }
table->key_info[i].rec_per_key[j]
= rec_per_key;
}
@@ -3188,15 +3143,13 @@ ha_innobase::info(
pointer and cause a seg fault. */
if (flag & HA_STATUS_ERRKEY) {
+ ut_a(prebuilt->trx && prebuilt->trx->magic_n == TRX_MAGIC_N);
+
errkey = (unsigned int) row_get_mysql_key_number_for_index(
(dict_index_t*)
trx_get_error_info(prebuilt->trx));
}
- if (prebuilt->trx) {
- prebuilt->trx->op_info = (char*) "";
- }
-
DBUG_VOID_RETURN;
}
@@ -3217,6 +3170,8 @@ ha_innobase::check(
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
ulint ret;
+ ut_a(prebuilt->trx && prebuilt->trx->magic_n == TRX_MAGIC_N);
+
if (prebuilt->mysql_template == NULL) {
/* Build the template; we will use a dummy template
in index scans done in checking */
@@ -3250,6 +3205,10 @@ ha_innobase::update_table_comment(
char* str = my_malloc(length + 550, MYF(0));
char* pos;
+ /* Warning: since it is not sure that MySQL calls external_lock
+ before calling this function, the trx field in prebuilt can be
+ obsolete! */
+
if (!str) {
return((char*)comment);
}
@@ -3271,6 +3230,53 @@ ha_innobase::update_table_comment(
return(str);
}
+/***********************************************************************
+Tells something additional to the handler about how to do things. */
+
+int
+ha_innobase::extra(
+/*===============*/
+ /* out: 0 or error number */
+ enum ha_extra_function operation)
+ /* in: HA_EXTRA_DONT_USE_CURSOR_TO_UPDATE */
+{
+ row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
+
+ /* Warning: since it is not sure that MySQL calls external_lock
+ before calling this function, the trx field in prebuilt can be
+ obsolete! */
+
+ switch (operation) {
+ case HA_EXTRA_RESET:
+ case HA_EXTRA_RESET_STATE:
+ prebuilt->read_just_key = 0;
+ break;
+ case HA_EXTRA_NO_KEYREAD:
+ prebuilt->read_just_key = 0;
+ break;
+ case HA_EXTRA_DONT_USE_CURSOR_TO_UPDATE:
+ prebuilt->in_update_remember_pos = FALSE;
+ break;
+ case HA_EXTRA_KEYREAD:
+ prebuilt->read_just_key = 1;
+ break;
+ default:/* Do nothing */
+ ;
+ }
+
+ return(0);
+}
+
+/**********************************************************************
+????????????? */
+
+int
+ha_innobase::reset(void)
+/*====================*/
+{
+ return(0);
+}
+
/**********************************************************************
As MySQL will execute an external lock for every new table it uses when it
starts to process an SQL statement, we can use this function to store the
@@ -3496,5 +3502,4 @@ ha_innobase::get_auto_increment()
return(nr);
}
-
#endif /* HAVE_INNOBASE_DB */
diff --git a/sql/ha_innodb.h b/sql/ha_innodb.h
index f926f303b26..faae42575b5 100644
--- a/sql/ha_innodb.h
+++ b/sql/ha_innodb.h
@@ -178,8 +178,9 @@ extern long innobase_force_recovery, innobase_thread_concurrency;
extern char *innobase_data_home_dir, *innobase_data_file_path;
extern char *innobase_log_group_home_dir, *innobase_log_arch_dir;
extern char *innobase_unix_file_flush_method;
-extern bool innobase_flush_log_at_trx_commit, innobase_log_archive,
- innobase_use_native_aio, innobase_fast_shutdown;
+/* The following variables have to be my_bool for SHOW VARIABLES to work */
+extern my_bool innobase_flush_log_at_trx_commit, innobase_log_archive,
+ innobase_use_native_aio, innobase_fast_shutdown;
extern TYPELIB innobase_lock_typelib;
diff --git a/sql/handler.cc b/sql/handler.cc
index 507b77c977b..8447797442c 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -222,28 +222,31 @@ int ha_autocommit_or_rollback(THD *thd, int error)
DBUG_RETURN(error);
}
-/* This function is called when MySQL writes the log segment of a transaction
-to the binlog. It is called when the LOCK_log mutex is reserved. Here we
-communicate to transactional table handlers whta binlog position corresponds
-to the current transaction. The handler can store it and in recovery print
-to the user, so that the user knows from what position in the binlog to
-start possible roll-forward, for example, if the crashed server was a slave
-in replication. This function also calls the commit of the table handler,
-because the order of trasnactions in the log of the table handler must be
-the same as in the binlog. */
-
-int ha_report_binlog_offset_and_commit(
- THD *thd, /* in: user thread */
- char *log_file_name, /* in: latest binlog file name */
- my_off_t end_offset) /* in: the offset in the binlog file
- up to which we wrote */
+/*
+ This function is called when MySQL writes the log segment of a
+ transaction to the binlog. It is called when the LOCK_log mutex is
+ reserved. Here we communicate to transactional table handlers whta
+ binlog position corresponds to the current transaction. The handler
+ can store it and in recovery print to the user, so that the user
+ knows from what position in the binlog to start possible
+ roll-forward, for example, if the crashed server was a slave in
+ replication. This function also calls the commit of the table
+ handler, because the order of trasnactions in the log of the table
+ handler must be the same as in the binlog.
+
+ arguments:
+ log_file_name: latest binlog file name
+ end_offset: the offset in the binlog file up to which we wrote
+*/
+
+int ha_report_binlog_offset_and_commit(THD *thd,
+ char *log_file_name,
+ my_off_t end_offset)
{
+ int error= 0;
+#ifdef HAVE_INNOBASE_DB
THD_TRANS *trans;
- int error = 0;
-
trans = &thd->transaction.all;
-
-#ifdef HAVE_INNOBASE_DB
if (trans->innobase_tid)
{
if ((error=innobase_report_binlog_offset_and_commit(thd,
@@ -257,10 +260,10 @@ int ha_report_binlog_offset_and_commit(
trans->innodb_active_trans=0;
}
#endif
-
return error;
}
+
int ha_commit_trans(THD *thd, THD_TRANS* trans)
{
int error=0;
diff --git a/sql/my_lock.c b/sql/my_lock.c
index 9b4ac502e57..4d451fcff22 100644
--- a/sql/my_lock.c
+++ b/sql/my_lock.c
@@ -26,10 +26,6 @@
#include <thr_alarm.h>
#include <errno.h>
-#ifdef HAVE_FCNTL
-static struct flock lock; /* Must be static for sun-sparc */
-#endif
-
/* Lock a part of a file */
int my_lock(File fd,int locktype,my_off_t start,my_off_t length,myf MyFlags)
@@ -37,24 +33,25 @@ int my_lock(File fd,int locktype,my_off_t start,my_off_t length,myf MyFlags)
thr_alarm_t alarmed;
ALARM alarm_buff;
uint wait_for_alarm;
+ struct flock m_lock;
DBUG_ENTER("my_lock");
DBUG_PRINT("my",("Fd: %d Op: %d start: %ld Length: %ld MyFlags: %d",
fd,locktype,(ulong) start,(ulong) length,MyFlags));
if (my_disable_locking)
DBUG_RETURN(0); /* purecov: inspected */
- lock.l_type=(short) locktype;
- lock.l_whence=0L;
- lock.l_start=(long) start;
- lock.l_len=(long) length;
+ m_lock.l_type=(short) locktype;
+ m_lock.l_whence=0L;
+ m_lock.l_start=(long) start;
+ m_lock.l_len=(long) length;
wait_for_alarm=(MyFlags & MY_DONT_WAIT ? MY_HOW_OFTEN_TO_ALARM :
(uint) 12*60*60);
- if (fcntl(fd,F_SETLK,&lock) != -1) /* Check if we can lock */
+ if (fcntl(fd,F_SETLK,&m_lock) != -1) /* Check if we can lock */
DBUG_RETURN(0); /* Ok, file locked */
DBUG_PRINT("info",("Was locked, trying with alarm"));
if (!thr_alarm(&alarmed,wait_for_alarm,&alarm_buff))
{
int value;
- while ((value=fcntl(fd,F_SETLKW,&lock)) && !thr_got_alarm(&alarmed) &&
+ while ((value=fcntl(fd,F_SETLKW,&m_lock)) && !thr_got_alarm(&alarmed) &&
errno == EINTR) ;
thr_end_alarm(&alarmed);
if (value != -1)
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index f0f4a369e30..924f85b0a89 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -160,8 +160,8 @@ char* query_table_status(THD *thd,const char *db,const char *table_name);
#define OPTION_LOW_PRIORITY_UPDATES 8192
#define OPTION_WARNINGS 16384
#define OPTION_AUTO_IS_NULL 32768
-#define OPTION_ANSI_MODE 65536L
-#define OPTION_SAFE_UPDATES OPTION_ANSI_MODE*2
+#define OPTION_FOUND_COMMENT 65536L
+#define OPTION_SAFE_UPDATES OPTION_FOUND_COMMENT*2
#define OPTION_BUFFER_RESULT OPTION_SAFE_UPDATES*2
#define OPTION_BIN_LOG OPTION_BUFFER_RESULT*2
#define OPTION_NOT_AUTO_COMMIT OPTION_BIN_LOG*2
@@ -181,7 +181,7 @@ char* query_table_status(THD *thd,const char *db,const char *table_name);
#define SELECT_NO_UNLOCK (QUERY_NO_GOOD_INDEX_USED*2)
#define TMP_TABLE_ALL_COLUMNS (SELECT_NO_UNLOCK*2)
-
+/* Bits for different SQL modes modes (including ANSI mode) */
#define MODE_REAL_AS_FLOAT 1
#define MODE_PIPES_AS_CONCAT 2
#define MODE_ANSI_QUOTES 4
@@ -583,6 +583,7 @@ extern pthread_cond_t COND_refresh,COND_thread_count;
extern pthread_attr_t connection_attrib;
extern bool opt_endinfo, using_udf_functions, locked_in_memory,
opt_using_transactions, use_temp_pool, mysql_embedded;
+extern bool opt_local_infile;
extern char f_fyllchar;
extern ulong ha_read_count, ha_write_count, ha_delete_count, ha_update_count,
ha_read_key_count, ha_read_next_count, ha_read_prev_count,
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index d30d285d0b8..187a4732aa0 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -297,6 +297,7 @@ ulong bytes_sent = 0L, bytes_received = 0L;
bool opt_endinfo,using_udf_functions,low_priority_updates, locked_in_memory;
bool opt_using_transactions, using_update_log, opt_warnings=0;
+bool opt_local_infile=1;
bool volatile abort_loop,select_thread_in_use,grant_option;
bool volatile ready_to_exit,shutdown_in_progress;
ulong refresh_version=1L,flush_version=1L; /* Increments on each reload */
@@ -708,8 +709,9 @@ static pthread_handler_decl(kill_server_thread,arg __attribute__((unused)))
static sig_handler print_signal_warning(int sig)
{
- sql_print_error("Warning: Got signal %d from thread %d",
- sig,my_thread_id());
+ if (opt_warnings)
+ sql_print_error("Warning: Got signal %d from thread %d",
+ sig,my_thread_id());
#ifdef DONT_REMEMBER_SIGNAL
sigset(sig,print_signal_warning); /* int. thread system calls */
#endif
@@ -856,20 +858,33 @@ static void set_user(const char *user)
if (!strcmp(user,"root"))
return; // Avoid problem with dynamic libraries
+ uid_t uid;
if (!(ent = getpwnam(user)))
{
- fprintf(stderr,"Fatal error: Can't change to run as user '%s' ; Please check that the user exists!\n",user);
- unireg_abort(1);
+ // allow a numeric uid to be used
+ const char *pos;
+ for (pos=user; isdigit(*pos); pos++) ;
+ if (*pos) // Not numeric id
+ {
+ fprintf(stderr,"Fatal error: Can't change to run as user '%s' ; Please check that the user exists!\n",user);
+ unireg_abort(1);
+ }
+ uid=atoi(user); // Use numberic uid
}
+ else
+ {
#ifdef HAVE_INITGROUPS
- initgroups((char*) user,ent->pw_gid);
+ initgroups((char*) user,ent->pw_gid);
#endif
- if (setgid(ent->pw_gid) == -1)
- {
- sql_perror("setgid");
- unireg_abort(1);
+ if (setgid(ent->pw_gid) == -1)
+ {
+ sql_perror("setgid");
+ unireg_abort(1);
+ }
+ uid=ent->pw_uid;
}
- if (setuid(ent->pw_uid) == -1)
+
+ if (setuid(uid) == -1)
{
sql_perror("setuid");
unireg_abort(1);
@@ -2673,7 +2688,7 @@ enum options {
OPT_SLAVE_LOAD_TMPDIR, OPT_NO_MIX_TYPE,
OPT_RPL_RECOVERY_RANK,OPT_INIT_RPL_ROLE,
OPT_RELAY_LOG, OPT_RELAY_LOG_INDEX, OPT_RELAY_LOG_INFO_FILE,
- OPT_SLAVE_SKIP_ERRORS, OPT_DES_KEY_FILE
+ OPT_SLAVE_SKIP_ERRORS, OPT_DES_KEY_FILE, OPT_LOCAL_INFILE
};
static struct option long_options[] = {
@@ -2735,6 +2750,7 @@ static struct option long_options[] = {
{"init-file", required_argument, 0, (int) OPT_INIT_FILE},
{"log", optional_argument, 0, 'l'},
{"language", required_argument, 0, 'L'},
+ {"local-infile", optional_argument, 0, (int) OPT_LOCAL_INFILE},
{"log-bin", optional_argument, 0, (int) OPT_BIN_LOG},
{"log-bin-index", required_argument, 0, (int) OPT_BIN_LOG_INDEX},
{"log-isam", optional_argument, 0, (int) OPT_ISAM_LOG},
@@ -3309,10 +3325,11 @@ static void use_help(void)
static void usage(void)
{
print_version();
- puts("Copyright (C) 2000 MySQL AB & MySQL Finland AB, by Monty and others");
- puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,");
- puts("and you are welcome to modify and redistribute it under the GPL license\n");
- puts("Starts the MySQL server\n");
+ puts("\
+Copyright (C) 2000 MySQL AB, by Monty and others\n\
+This software comes with ABSOLUTELY NO WARRANTY. This is free software,\n\
+and you are welcome to modify and redistribute it under the GPL license\n\
+Starts the MySQL server\n");
printf("Usage: %s [OPTIONS]\n", my_progname);
puts("\n\
@@ -3601,6 +3618,9 @@ static void get_options(int argc,char **argv)
case 'P':
mysql_port= (unsigned int) atoi(optarg);
break;
+ case OPT_LOCAL_INFILE:
+ opt_local_infile= test(!optarg || atoi(optarg) != 0);
+ break;
case OPT_SLAVE_SKIP_ERRORS:
init_slave_skip_errors(optarg);
break;
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index d61e47d0883..7995e7701e5 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -768,6 +768,7 @@ int yylex(void *arg)
return(TEXT_STRING);
case STATE_COMMENT: // Comment
+ lex->select_lex.options|= OPTION_FOUND_COMMENT;
while ((c = yyGet()) != '\n' && c) ;
yyUnget(); // Safety against eof
state = STATE_START; // Try again
@@ -779,6 +780,7 @@ int yylex(void *arg)
break;
}
yySkip(); // Skip '*'
+ lex->select_lex.options|= OPTION_FOUND_COMMENT;
if (yyPeek() == '!') // MySQL command in comment
{
ulong version=MYSQL_VERSION_ID;
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 6a966336ad7..c0ede015eb8 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -57,6 +57,7 @@ enum enum_sql_command {
SQLCOM_HA_OPEN, SQLCOM_HA_CLOSE, SQLCOM_HA_READ,
SQLCOM_SHOW_SLAVE_HOSTS, SQLCOM_DELETE_MULTI, SQLCOM_MULTI_UPDATE,
SQLCOM_SHOW_BINLOG_EVENTS, SQLCOM_SHOW_NEW_MASTER, SQLCOM_DO,
+ SQLCOM_EMPTY_QUERY,
SQLCOM_END
};
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index 899f2e20469..419e3fccabd 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -145,7 +145,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
if (read_file_from_client && handle_duplicates == DUP_ERROR)
handle_duplicates=DUP_IGNORE;
- if (read_file_from_client && (thd->client_capabilities & CLIENT_LOCAL_FILES))
+ if (read_file_from_client)
{
(void)net_request_file(&thd->net,ex->file_name);
file = -1;
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 8ebedba13ac..e649f109a0d 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -120,8 +120,9 @@ inline bool end_active_trans(THD *thd)
static HASH hash_user_connections;
extern pthread_mutex_t LOCK_user_conn;
-static int get_or_create_user_conn(THD *thd, const char *user, const char *host,
- uint max_questions)
+static int get_or_create_user_conn(THD *thd, const char *user,
+ const char *host,
+ uint max_questions)
{
int return_val=0;
uint temp_len;
@@ -134,19 +135,18 @@ static int get_or_create_user_conn(THD *thd, const char *user, const char *host,
temp_len= (uint) (strxnmov(temp_user, sizeof(temp_user)-1, user, "@", host,
NullS) - temp_user);
(void) pthread_mutex_lock(&LOCK_user_conn);
- uc = (struct user_conn *) hash_search(&hash_user_connections,
- (byte*) temp_user, temp_len);
- if (!uc)
+ if (!(uc = (struct user_conn *) hash_search(&hash_user_connections,
+ (byte*) temp_user, temp_len)))
{
- uc= ((struct user_conn*)
- my_malloc(sizeof(struct user_conn) + temp_len+1,
- MYF(MY_WME)));
- if (!uc)
+ /* First connection for user; Create a user connection object */
+ if (!(uc= ((struct user_conn*)
+ my_malloc(sizeof(struct user_conn) + temp_len+1,
+ MYF(MY_WME)))))
{
send_error(&current_thd->net, 0, NullS); // Out of memory
return_val=1;
goto end;
- }
+ }
uc->user=(char*) (uc+1);
memcpy(uc->user,temp_user,temp_len+1);
uc->len = temp_len;
@@ -279,9 +279,6 @@ static int check_for_max_user_connections(UC *uc)
{
int error=0;
DBUG_ENTER("check_for_max_user_connections");
-// DBUG_PRINT("enter",("user: '%s' host: '%s'", user, host));
-
- DBUG_ASSERT(uc != 0);
if (max_user_connections <= (uint) uc->connections)
{
@@ -302,8 +299,6 @@ static void decrease_user_connections(UC *uc)
return;
DBUG_ENTER("decrease_user_connections");
- DBUG_ASSERT(uc != 0);
-// DBUG_PRINT("enter",("user: '%s' host: '%s'", user, host));
if (!--uc->connections && !mqh_used)
{
@@ -325,6 +320,10 @@ void free_max_user_conn(void)
/*
Check if maximum queries per hour limit has been reached
returns 0 if OK.
+
+ In theory we would need a mutex in the UC structure for this to be 100 %
+ safe, but as the worst scenario is that we would miss counting a couple of
+ queries, this isn't critical.
*/
static bool check_mqh(THD *thd)
@@ -334,15 +333,14 @@ static bool check_mqh(THD *thd)
UC *uc=thd->user_connect;
DBUG_ASSERT(uc != 0);
- /* TODO: Add username + host to THD for faster execution */
bool my_start = thd->start_time != 0;
time_t check_time = (my_start) ? thd->start_time : time(NULL);
if (check_time - uc->intime >= 3600)
{
-// (void) pthread_mutex_lock(&LOCK_user_conn);
- uc->questions=(uint) my_start;
+ (void) pthread_mutex_lock(&LOCK_user_conn);
+ uc->questions=1;
uc->intime=check_time;
-// (void) pthread_mutex_unlock(&LOCK_user_conn);
+ (void) pthread_mutex_unlock(&LOCK_user_conn);
}
else if (uc->max_questions && ++(uc->questions) > uc->max_questions)
{
@@ -356,27 +354,22 @@ end:
DBUG_RETURN(error);
}
-static void reset_mqh(THD *thd,LEX_USER *lu, uint mq)
+
+static void reset_mqh(THD *thd, LEX_USER *lu, uint mq)
{
- char user[USERNAME_LENGTH+1];
- char host[USERNAME_LENGTH+1];
- char *where;
+ (void) pthread_mutex_lock(&LOCK_user_conn);
if (lu) // for GRANT
{
UC *uc;
- uint temp_len;
+ uint temp_len=lu->user.length+lu->host.length+2;
char temp_user[USERNAME_LENGTH+HOSTNAME_LENGTH+2];
- memcpy(user,lu->user.str,lu->user.length);
- user[lu->user.length]='\0';
- memcpy(host,lu->host.str,lu->host.length);
- host[lu->host.length]='\0';
- temp_len= (uint) (strxnmov(temp_user, sizeof(temp_user)-1, user, "@", host,
- NullS) - temp_user);
- uc = (struct user_conn *) hash_search(&hash_user_connections,
- (byte*) temp_user, temp_len);
- if (uc)
+ memcpy(temp_user,lu->user.str,lu->user.length);
+ memcpy(temp_user+lu->user.length+1,lu->host.str,lu->host.length);
+ temp_user[lu->user.length]=temp_user[temp_len-1]=0;
+ if ((uc = (struct user_conn *) hash_search(&hash_user_connections,
+ (byte*) temp_user, temp_len)))
{
uc->questions=0;
uc->max_questions=mq;
@@ -384,21 +377,20 @@ static void reset_mqh(THD *thd,LEX_USER *lu, uint mq)
}
else // for FLUSH PRIVILEGES
{
- (void) pthread_mutex_lock(&LOCK_user_conn);
- for (uint idx=0;idx<hash_user_connections.records;idx++)
+ for (uint idx=0;idx < hash_user_connections.records; idx++)
{
- HASH_LINK *data=dynamic_element(&hash_user_connections.array,idx,HASH_LINK*);
- UC *uc=(struct user_conn *)data->data;
+ char user[USERNAME_LENGTH+1];
+ char *where;
+ UC *uc=(struct user_conn *) hash_element(&hash_user_connections, idx);
where=strchr(uc->user,'@');
- memcpy(user,uc->user,where - uc->user);
- user[where-uc->user]='\0'; where++;
- strcpy(host,where);
- uc->max_questions=get_mqh(user,host);
+ strmake(user,uc->user,where - uc->user);
+ uc->max_questions=get_mqh(user,where+1);
}
- (void) pthread_mutex_unlock(&LOCK_user_conn);
}
+ (void) pthread_mutex_unlock(&LOCK_user_conn);
}
+
/*
Check connnetion and get priviliges
Returns 0 on ok, -1 < if error is given > 0 on error.
@@ -833,8 +825,10 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
{
NET *net= &thd->net;
bool error=0;
- // commands which will always take a long time should be marked with
- // this so that they will not get logged to the slow query log
+ /*
+ Commands which will always take a long time should be marked with
+ this so that they will not get logged to the slow query log
+ */
bool slow_command=FALSE;
DBUG_ENTER("dispatch_command");
@@ -912,7 +906,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
break;
}
if (max_connections && save_uc)
- decrease_user_connections (save_uc);
+ decrease_user_connections(save_uc);
x_free((gptr) save_db);
x_free((gptr) save_user);
thd->password=test(passwd[0]);
@@ -947,8 +941,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
DBUG_PRINT("query",("%s",thd->query));
if (thd->user_connect && check_mqh(thd))
{
- error = TRUE;
- net->error = 0;
+ error = TRUE; // Abort client
+ net->error = 0; // Don't give abort message
break;
}
/* thd->query_length is set by mysql_parse() */
@@ -1071,11 +1065,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
else
send_eof(net);
if (mqh_used)
- {
- if (hash_user_connections.array.buffer == 0)
- init_max_user_conn();
- reset_mqh(thd,(LEX_USER *)NULL,0);
- }
+ reset_mqh(thd,(LEX_USER *) NULL, 0);
break;
}
case COM_SHUTDOWN:
@@ -1321,6 +1311,10 @@ mysql_execute_command(void)
res=mysql_do(thd, *lex->insert_list);
break;
+ case SQLCOM_EMPTY_QUERY:
+ send_ok(&thd->net);
+ break;
+
case SQLCOM_PURGE:
{
if (check_process_priv(thd))
@@ -2103,13 +2097,20 @@ mysql_execute_command(void)
{
uint privilege= (lex->duplicates == DUP_REPLACE ?
INSERT_ACL | UPDATE_ACL | DELETE_ACL : INSERT_ACL);
- if (!(lex->local_file && (thd->client_capabilities & CLIENT_LOCAL_FILES)))
+
+ if (!lex->local_file)
{
if (check_access(thd,privilege | FILE_ACL,tables->db))
goto error;
}
else
{
+ if (!(thd->client_capabilities & CLIENT_LOCAL_FILES) ||
+ ! opt_local_infile)
+ {
+ send_error(&thd->net,ER_NOT_ALLOWED_COMMAND);
+ goto error;
+ }
if (check_access(thd,privilege,tables->db,&tables->grant.privilege) ||
grant_option && check_grant(thd,privilege,tables))
goto error;
@@ -2305,17 +2306,12 @@ mysql_execute_command(void)
Query_log_event qinfo(thd, thd->query);
mysql_bin_log.write(&qinfo);
}
- if (mqh_used)
+ if (mqh_used && lex->mqh)
{
- if (hash_user_connections.array.buffer == 0)
- init_max_user_conn();
- if (lex->mqh)
- {
- List_iterator <LEX_USER> str_list (lex->users_list);
- LEX_USER *Str;
- str_list.rewind();
- reset_mqh(thd,str_list++,lex->mqh);
- }
+ List_iterator <LEX_USER> str_list(lex->users_list);
+ LEX_USER *user;
+ while ((user=str_list++))
+ reset_mqh(thd,user,lex->mqh);
}
}
}
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index e2e5e4bf55a..69cac90e2be 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -5962,10 +5962,10 @@ SORT_FIELD *make_unireg_sortorder(ORDER *order, uint *length)
/*****************************************************************************
-** Fill join cache with packed records
-** Records are stored in tab->cache.buffer and last record in
-** last record is stored with pointers to blobs to support very big
-** records
+ Fill join cache with packed records
+ Records are stored in tab->cache.buffer and last record in
+ last record is stored with pointers to blobs to support very big
+ records
******************************************************************************/
static int
@@ -6027,7 +6027,7 @@ join_init_cache(THD *thd,JOIN_TAB *tables,uint table_count)
if (null_fields && tables[i].table->null_fields)
{ /* must copy null bits */
copy->str=(char*) tables[i].table->null_flags;
- copy->length=(tables[i].table->null_fields+7)/8;
+ copy->length=tables[i].table->null_bytes;
copy->strip=0;
copy->blob_field=0;
length+=copy->length;
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 0335c6f49cf..8013afa194b 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -825,7 +825,7 @@ bool close_cached_table(THD *thd,TABLE *table)
/* Mark all tables that are in use as 'old' */
mysql_lock_abort(thd,table); // end threads waiting on lock
-#ifdef REMOVE_LOCKS
+#if defined(USING_TRANSACTIONS) || defined( __WIN__) || defined( __EMX__) || !defined(OS2)
/* Wait until all there are no other threads that has this table open */
while (remove_table_from_cache(thd,table->table_cache_key,
table->table_name))
@@ -1674,20 +1674,29 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
}
}
-#if defined( __WIN__) || defined( __EMX__) || defined( OS2)
- // Win32 can't rename an open table, so we must close the org table!
- table_name=thd->strdup(table_name); // must be saved
- if (close_cached_table(thd,table))
- { // Aborted
- VOID(quick_rm_table(new_db_type,new_db,tmp_name));
- VOID(pthread_mutex_unlock(&LOCK_open));
- goto err;
+#if (!defined( __WIN__) && !defined( __EMX__) && !defined( OS2))
+ if (table->file->has_transactions())
+#endif
+ {
+ /*
+ Win32 and InnoDB can't drop a table that is in use, so we must
+ close all the original table at before doing the rename
+ */
+ table_name=thd->strdup(table_name); // must be saved
+ if (close_cached_table(thd,table))
+ { // Aborted
+ VOID(quick_rm_table(new_db_type,new_db,tmp_name));
+ VOID(pthread_mutex_unlock(&LOCK_open));
+ goto err;
+ }
+ table=0; // Marker that table is closed
}
- table=0; // Marker for win32 version
-#else
- table->file->extra(HA_EXTRA_FORCE_REOPEN); // Don't use this file anymore
+#if (!defined( __WIN__) && !defined( __EMX__) && !defined( OS2))
+ else
+ table->file->extra(HA_EXTRA_FORCE_REOPEN); // Don't use this file anymore
#endif
+
error=0;
if (mysql_rename_table(old_db_type,db,table_name,db,old_name))
{
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 91cf0ae5fc9..5c4297bc707 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -596,9 +596,17 @@ END_OF_INPUT
query:
END_OF_INPUT
{
- if (!current_thd->bootstrap)
+ THD *thd=current_thd;
+ if (!thd->bootstrap &&
+ (!(thd->lex.select_lex.options & OPTION_FOUND_COMMENT)))
+ {
send_error(&current_thd->net,ER_EMPTY_QUERY);
- YYABORT;
+ YYABORT;
+ }
+ else
+ {
+ thd->lex.sql_command = SQLCOM_EMPTY_QUERY;
+ }
}
| verb_clause END_OF_INPUT {}
diff --git a/sql/unireg.cc b/sql/unireg.cc
index 8c72dfc2855..16ba8c7d58b 100644
--- a/sql/unireg.cc
+++ b/sql/unireg.cc
@@ -486,11 +486,11 @@ static bool pack_fields(File file,List<create_field> &create_fields)
if (field->interval_id > int_count)
{
int_count=field->interval_id;
- tmp.append('\377');
+ tmp.append(NAMES_SEP_CHAR);
for (const char **pos=field->interval->type_names ; *pos ; pos++)
{
tmp.append(*pos);
- tmp.append('\377');
+ tmp.append(NAMES_SEP_CHAR);
}
tmp.append('\0'); // End of intervall
}
diff --git a/sql/unireg.h b/sql/unireg.h
index 9b220f87918..c4d2052d1da 100644
--- a/sql/unireg.h
+++ b/sql/unireg.h
@@ -70,11 +70,6 @@
#define FERR -1 /* Error from my_functions */
#define CREATE_MODE 0 /* Default mode on new files */
#define NAMES_SEP_CHAR '\377' /* Char to sep. names */
-#ifdef MSDOS
-#define EXTRA_FIELD_CHAR (char) '\234' /* Interchangebly with '#' */
-#else
-#define EXTRA_FIELD_CHAR '#' /* Interchangebly with '#' */
-#endif
#define READ_RECORD_BUFFER (uint) (IO_SIZE*8) /* Pointer_buffer_size */
#define DISK_BUFFER_SIZE (uint) (IO_SIZE*16) /* Size of diskbuffer */