diff options
Diffstat (limited to 'sql')
-rw-r--r-- | sql/ha_innodb.cc | 177 | ||||
-rw-r--r-- | sql/ha_innodb.h | 5 | ||||
-rw-r--r-- | sql/handler.cc | 43 | ||||
-rw-r--r-- | sql/my_lock.c | 17 | ||||
-rw-r--r-- | sql/mysql_priv.h | 7 | ||||
-rw-r--r-- | sql/mysqld.cc | 50 | ||||
-rw-r--r-- | sql/sql_lex.cc | 2 | ||||
-rw-r--r-- | sql/sql_lex.h | 1 | ||||
-rw-r--r-- | sql/sql_load.cc | 2 | ||||
-rw-r--r-- | sql/sql_parse.cc | 122 | ||||
-rw-r--r-- | sql/sql_select.cc | 10 | ||||
-rw-r--r-- | sql/sql_table.cc | 33 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 12 | ||||
-rw-r--r-- | sql/unireg.cc | 4 | ||||
-rw-r--r-- | sql/unireg.h | 5 |
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(¤t_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(¤t_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 */ |