diff options
Diffstat (limited to 'sql')
-rw-r--r-- | sql/field.cc | 42 | ||||
-rw-r--r-- | sql/field.h | 17 | ||||
-rw-r--r-- | sql/ha_berkeley.cc | 14 | ||||
-rw-r--r-- | sql/ha_innobase.cc | 259 | ||||
-rw-r--r-- | sql/ha_innobase.h | 10 | ||||
-rw-r--r-- | sql/ha_myisammrg.cc | 4 | ||||
-rw-r--r-- | sql/handler.cc | 9 | ||||
-rw-r--r-- | sql/item.h | 1 | ||||
-rw-r--r-- | sql/item_timefunc.cc | 4 | ||||
-rw-r--r-- | sql/log.cc | 58 | ||||
-rw-r--r-- | sql/mysqld.cc | 52 | ||||
-rw-r--r-- | sql/nt_servc.cc | 380 | ||||
-rw-r--r-- | sql/nt_servc.h | 3 | ||||
-rwxr-xr-x | sql/share/norwegian-ny/.cvsignore | 1 | ||||
-rwxr-xr-x | sql/share/norwegian/.cvsignore | 1 | ||||
-rw-r--r-- | sql/sql_lex.cc | 27 | ||||
-rw-r--r-- | sql/sql_select.cc | 51 | ||||
-rw-r--r-- | sql/time.cc | 6 |
18 files changed, 634 insertions, 305 deletions
diff --git a/sql/field.cc b/sql/field.cc index 07f521abf3e..df6c2a80424 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -2412,8 +2412,7 @@ String *Field_timestamp::val_str(String *val_buffer, return val_buffer; } -bool Field_timestamp::get_date(TIME *ltime, - bool fuzzydate __attribute__((unused))) +bool Field_timestamp::get_date(TIME *ltime, bool fuzzydate) { long temp; #ifdef WORDS_BIGENDIAN @@ -2424,6 +2423,8 @@ bool Field_timestamp::get_date(TIME *ltime, longget(temp,ptr); if (temp == 0L) { /* Zero time is "000000" */ + if (!fuzzydate) + return 1; bzero((char*) ltime,sizeof(*ltime)); } else @@ -2447,8 +2448,7 @@ bool Field_timestamp::get_date(TIME *ltime, bool Field_timestamp::get_time(TIME *ltime) { - Field_timestamp::get_date(ltime,0); - return 0; + return Field_timestamp::get_date(ltime,0); } int Field_timestamp::cmp(const char *a_ptr, const char *b_ptr) @@ -3029,13 +3029,12 @@ bool Field_newdate::get_date(TIME *ltime,bool fuzzydate) ltime->month= (tmp >> 5) & 15; ltime->year= (tmp >> 9); ltime->time_type=TIMESTAMP_DATE; - return (!fuzzydate && (!ltime->month || !ltime->day) && ltime->year) ? 1 : 0; + return (!fuzzydate && (!ltime->month || !ltime->day)) ? 1 : 0; } bool Field_newdate::get_time(TIME *ltime) { - Field_newdate::get_date(ltime,0); - return 0; + return Field_newdate::get_date(ltime,0); } int Field_newdate::cmp(const char *a_ptr, const char *b_ptr) @@ -3214,13 +3213,12 @@ bool Field_datetime::get_date(TIME *ltime,bool fuzzydate) ltime->day= part1%100; ltime->month= part1/100%100; ltime->year= part1/10000; - return (!fuzzydate && (!ltime->month || !ltime->day) && ltime->year) ? 1 : 0; + return (!fuzzydate && (!ltime->month || !ltime->day)) ? 1 : 0; } bool Field_datetime::get_time(TIME *ltime) { - Field_datetime::get_date(ltime,0); - return 0; + return Field_datetime::get_date(ltime,0); } int Field_datetime::cmp(const char *a_ptr, const char *b_ptr) @@ -3468,9 +3466,9 @@ int Field_string::pack_cmp(const char *b, uint length) } -uint Field_string::packed_col_length(const char *ptr) +uint Field_string::packed_col_length(const char *ptr, uint length) { - if (field_length > 255) + if (length > 255) return uint2korr(ptr)+2; else return (uint) ((uchar) *ptr)+1; @@ -3478,7 +3476,7 @@ uint Field_string::packed_col_length(const char *ptr) uint Field_string::max_packed_col_length(uint max_length) { - return (field_length > 255 ? 2 : 1)+max_length; + return (max_length > 255 ? 2 : 1)+max_length; } @@ -3687,9 +3685,9 @@ int Field_varstring::pack_cmp(const char *b, uint key_length) return my_sortncmp(a,a_length, b,b_length); } -uint Field_varstring::packed_col_length(const char *ptr) +uint Field_varstring::packed_col_length(const char *ptr, uint length) { - if (field_length > 255) + if (length > 255) return uint2korr(ptr)+2; else return (uint) ((uchar) *ptr)+1; @@ -3697,7 +3695,7 @@ uint Field_varstring::packed_col_length(const char *ptr) uint Field_varstring::max_packed_col_length(uint max_length) { - return (field_length > 255 ? 2 : 1)+max_length; + return (max_length > 255 ? 2 : 1)+max_length; } /**************************************************************************** @@ -4173,6 +4171,18 @@ char *Field_blob::pack_key_from_key_image(char *to, const char *from, return to+length; } +uint Field_blob::packed_col_length(const char *ptr, uint length) +{ + if (length > 255) + return uint2korr(ptr)+2; + else + return (uint) ((uchar) *ptr)+1; +} + +uint Field_blob::max_packed_col_length(uint max_length) +{ + return (max_length > 255 ? 2 : 1)+max_length; +} /**************************************************************************** ** enum type. diff --git a/sql/field.h b/sql/field.h index ddcc281d0c8..777e4388850 100644 --- a/sql/field.h +++ b/sql/field.h @@ -176,10 +176,10 @@ public: { return pack(to,from,max_length); } - virtual uint packed_col_length(const char *to) - { return pack_length();} + virtual uint packed_col_length(const char *to, uint length) + { return length;} virtual uint max_packed_col_length(uint max_length) - { return pack_length();} + { return max_length;} virtual int pack_cmp(const char *a,const char *b, uint key_length_arg) { return cmp(a,b); } @@ -749,7 +749,7 @@ public: const char *unpack(char* to, const char *from); int pack_cmp(const char *a,const char *b,uint key_length); int pack_cmp(const char *b,uint key_length); - uint packed_col_length(const char *to); + uint packed_col_length(const char *to, uint length); uint max_packed_col_length(uint max_length); uint size_of() const { return sizeof(*this); } enum_field_types real_type() const { return FIELD_TYPE_STRING; } @@ -801,7 +801,7 @@ public: const char *unpack(char* to, const char *from); int pack_cmp(const char *a, const char *b, uint key_length); int pack_cmp(const char *b, uint key_length); - uint packed_col_length(const char *to); + uint packed_col_length(const char *to, uint length); uint max_packed_col_length(uint max_length); uint size_of() const { return sizeof(*this); } enum_field_types real_type() const { return FIELD_TYPE_VAR_STRING; } @@ -887,11 +887,8 @@ public: char *pack_key_from_key_image(char* to, const char *from, uint max_length); int pack_cmp(const char *a, const char *b, uint key_length); int pack_cmp(const char *b, uint key_length); - uint packed_col_length(const char *col_ptr) - { return get_length(col_ptr)+packlength;} - virtual uint max_packed_col_length(uint max_length) - { return packlength+max_length; } - + uint packed_col_length(const char *col_ptr, uint length); + uint max_packed_col_length(uint max_length); inline void free() { value.free(); } inline void clear_temporary() { bzero((char*) &value,sizeof(value)); } friend void field_conv(Field *to,Field *from); diff --git a/sql/ha_berkeley.cc b/sql/ha_berkeley.cc index b10939227ff..f52b99f5a12 100644 --- a/sql/ha_berkeley.cc +++ b/sql/ha_berkeley.cc @@ -28,8 +28,8 @@ - Get a more accurate count of the number of rows (estimate_number_of_rows()). We could store the found number of rows when the table is scanned and then increment the counter for each attempted write. - - We will need a manager thread that calls flush_logs, removes old - logs and makes checkpoints at given intervals. + - We will need to extend the manager thread to makes checkpoints at + given intervals. - When not using UPDATE IGNORE, don't make a sub transaction but abort the main transaction on errors. - Handling of drop table during autocommit=0 ? @@ -372,10 +372,12 @@ berkeley_cmp_packed_key(DB *file, const DBT *new_key, const DBT *saved_key) if ((cmp=key_part->field->pack_cmp(new_key_ptr,saved_key_ptr, key_part->length))) return cmp; - uint length=key_part->field->packed_col_length(new_key_ptr); + uint length=key_part->field->packed_col_length(new_key_ptr, + key_part->length); new_key_ptr+=length; key_length-=length; - saved_key_ptr+=key_part->field->packed_col_length(saved_key_ptr); + saved_key_ptr+=key_part->field->packed_col_length(saved_key_ptr, + key_part->length); } return key->handler.bdb_return_if_eq; } @@ -433,7 +435,7 @@ berkeley_key_cmp(TABLE *table, KEY *key_info, const char *key, uint key_length) } if ((cmp=key_part->field->pack_cmp(key,key_part->length))) return cmp; - uint length=key_part->field->packed_col_length(key); + uint length=key_part->field->packed_col_length(key,key_part->length); key+=length; key_length-=length; } @@ -1552,7 +1554,7 @@ DBT *ha_berkeley::get_pos(DBT *to, byte *pos) KEY_PART_INFO *end=key_part+table->key_info[primary_key].key_parts; for ( ; key_part != end ; key_part++) - pos+=key_part->field->packed_col_length((char*) pos); + pos+=key_part->field->packed_col_length((char*) pos,key_part->length); to->size= (uint) (pos- (byte*) to->data); } return to; diff --git a/sql/ha_innobase.cc b/sql/ha_innobase.cc index 7e11fbe46d1..dd72bb15473 100644 --- a/sql/ha_innobase.cc +++ b/sql/ha_innobase.cc @@ -79,13 +79,14 @@ ulong innobase_cache_size = 0; long innobase_mirrored_log_groups, innobase_log_files_in_group, innobase_log_file_size, innobase_log_buffer_size, innobase_buffer_pool_size, innobase_additional_mem_pool_size, - innobase_file_io_threads, innobase_lock_wait_timeout; + innobase_file_io_threads, innobase_lock_wait_timeout, + innobase_thread_concurrency, innobase_force_recovery; 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_use_native_aio, innobase_fast_shutdown; /* Set default InnoDB size to 64M, to let users use InnoDB without having @@ -165,19 +166,19 @@ convert_error_code_to_mysql( } else if (error == (int) DB_LOCK_WAIT_TIMEOUT) { - return(1000001); + return(HA_ERR_LOCK_WAIT_TIMEOUT); } else if (error == (int) DB_NO_REFERENCED_ROW) { - return(1000010); + return(HA_ERR_NO_REFERENCED_ROW); } else if (error == (int) DB_ROW_IS_REFERENCED) { - return(1000011); + return(HA_ERR_ROW_IS_REFERENCED); } else if (error == (int) DB_CANNOT_ADD_CONSTRAINT) { - return(1000012); + return(HA_ERR_CANNOT_ADD_FOREIGN); } else if (error == (int) DB_OUT_OF_FILE_SPACE) { @@ -354,12 +355,6 @@ innobase_parse_data_file_paths_and_sizes(void) str++; } - if (size >= 4096) { - fprintf(stderr, - "InnoDB: error: data file size must not be >= 4096M\n"); - return(FALSE); - } - if (strlen(str) >= 6 && *str == 'n' && *(str + 1) == 'e' @@ -566,8 +561,10 @@ innobase_init(void) srv_query_thread_priority = QUERY_PRIOR; } - /* Set InnoDB initialization parameters according to the values - read from MySQL .cnf file */ + /* + Set InnoDB initialization parameters according to the values + read from MySQL .cnf file + */ // Make a copy of innobase_data_file_path to not modify the original internal_innobase_data_file_path=my_strdup(innobase_data_file_path, @@ -604,7 +601,7 @@ innobase_init(void) srv_log_archive_on = (ulint) innobase_log_archive; srv_log_buffer_size = (ulint) innobase_log_buffer_size; - srv_flush_log_at_trx_commit = (ulint) innobase_flush_log_at_trx_commit; + srv_flush_log_at_trx_commit = (ibool) innobase_flush_log_at_trx_commit; srv_use_native_aio = 0; @@ -614,6 +611,10 @@ innobase_init(void) srv_n_file_io_threads = (ulint) innobase_file_io_threads; srv_lock_wait_timeout = (ulint) innobase_lock_wait_timeout; + srv_thread_concurrency = (ulint) innobase_thread_concurrency; + srv_force_recovery = (ulint) innobase_force_recovery; + + srv_fast_shutdown = (ibool) innobase_fast_shutdown; srv_print_verbose_log = mysql_embedded ? 0 : 1; if (strcmp(default_charset_info->name, "latin1") == 0) { @@ -713,12 +714,15 @@ innobase_commit( trx = check_trx_exists(thd); if (trx_handle != (void*)&innodb_dummy_stmt_trx_handle) { + srv_conc_enter_innodb(trx); + trx_commit_for_mysql(trx); - trx_mark_sql_stat_end_do_not_start_new(trx); - } else { - trx_mark_sql_stat_end(trx); + + srv_conc_exit_innodb(); } + trx_mark_sql_stat_end(trx); + #ifndef DBUG_OFF if (error) { DBUG_PRINT("error", ("error: %d", error)); @@ -751,14 +755,18 @@ innobase_rollback( trx = check_trx_exists(thd); + srv_conc_enter_innodb(trx); + if (trx_handle != (void*)&innodb_dummy_stmt_trx_handle) { error = trx_rollback_for_mysql(trx); - trx_mark_sql_stat_end_do_not_start_new(trx); } else { error = trx_rollback_last_sql_stat_for_mysql(trx); - trx_mark_sql_stat_end(trx); } + srv_conc_exit_innodb(); + + trx_mark_sql_stat_end(trx); + DBUG_RETURN(convert_error_code_to_mysql(error)); } @@ -908,10 +916,11 @@ ha_innobase::open( if (NULL == (ib_table = dict_table_get(norm_name, NULL))) { fprintf(stderr, -"InnoDB: Cannot find table %s from the internal data dictionary\n" +"InnoDB: Error: cannot find table %s from the internal data dictionary\n" "InnoDB: of InnoDB though the .frm file for the table exists. Maybe you\n" "InnoDB: have deleted and recreated InnoDB data files but have forgotten\n" -"InnoDB: to delete the corresponding .frm files of InnoDB tables?\n", +"InnoDB: to delete the corresponding .frm files of InnoDB tables, or you\n" +"InnoDB: have moved .frm files to another database?\n", norm_name); free_share(share); @@ -956,7 +965,9 @@ ha_innobase::open( dbug_assert(key_used_on_scan == MAX_KEY); } - /* Init table lock structure */ + auto_inc_counter_for_this_stat = 0; + + /* Init table lock structure */ thr_lock_data_init(&share->lock,&lock,(void*) 0); info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST); @@ -1253,14 +1264,20 @@ build_template( Field* field; ulint n_fields; ulint n_requested_fields = 0; + ibool fetch_all_in_key = FALSE; ulint i; clust_index = dict_table_get_first_index_noninline(prebuilt->table); if (!prebuilt->in_update_remember_pos) { - /* We are building a temporary table: fetch all columns */ - - templ_type = ROW_MYSQL_WHOLE_ROW; + if (prebuilt->read_just_key) { + fetch_all_in_key = TRUE; + } else { + /* We are building a temporary table: fetch all + columns */ + + templ_type = ROW_MYSQL_WHOLE_ROW; + } } if (prebuilt->select_lock_type == LOCK_X) { @@ -1270,7 +1287,6 @@ build_template( templ_type = ROW_MYSQL_WHOLE_ROW; } - if (templ_type == ROW_MYSQL_REC_FIELDS) { if (prebuilt->select_lock_type != LOCK_NONE) { @@ -1310,6 +1326,9 @@ build_template( field = table->field[i]; if (templ_type == ROW_MYSQL_REC_FIELDS + && !(fetch_all_in_key && + ULINT_UNDEFINED != dict_index_get_nth_col_pos( + index, i)) && thd->query_id != field->query_id && thd->query_id != (field->query_id ^ MAX_ULONG_BIT) && thd->query_id != @@ -1408,9 +1427,6 @@ ha_innobase::write_row( } if (table->next_number_field && record == table->record[0]) { - /* Set the 'in_update_remember_pos' flag to FALSE to - make sure all columns are fetched in the select done by - update_auto_increment */ /* Fetch the value the user possibly has set in the autoincrement field */ @@ -1420,12 +1436,29 @@ ha_innobase::write_row( /* In replication and also otherwise the auto-inc column can be set with SET INSERT_ID. Then we must look at user_thd->next_insert_id. If it is nonzero and the user - has not supplied a value, we must use it. */ + has not supplied a value, we must use it, and use values + incremented by 1 in all subsequent inserts within the + same SQL statement! */ if (auto_inc == 0 && user_thd->next_insert_id != 0) { auto_inc = user_thd->next_insert_id; + auto_inc_counter_for_this_stat = auto_inc; } + if (auto_inc == 0 && auto_inc_counter_for_this_stat) { + /* The user set the auto-inc counter for + this SQL statement with SET INSERT_ID. We must + assign sequential values from the counter. */ + + auto_inc_counter_for_this_stat++; + + auto_inc = auto_inc_counter_for_this_stat; + + /* We give MySQL a new value to place in the + auto-inc column */ + user_thd->next_insert_id = auto_inc; + } + if (auto_inc != 0) { /* This call will calculate the max of the current value and the value supplied by the user, if @@ -1449,11 +1482,14 @@ ha_innobase::write_row( dict_table_autoinc_update(prebuilt->table, auto_inc); } else { + srv_conc_enter_innodb(prebuilt->trx); + if (!prebuilt->trx->auto_inc_lock) { error = row_lock_table_autoinc_for_mysql( prebuilt); if (error != DB_SUCCESS) { + srv_conc_exit_innodb(); error = convert_error_code_to_mysql( error); @@ -1462,6 +1498,7 @@ ha_innobase::write_row( } auto_inc = dict_table_autoinc_get(prebuilt->table); + srv_conc_exit_innodb(); /* If auto_inc is now != 0 the autoinc counter was already initialized for the table: we can give @@ -1472,6 +1509,10 @@ ha_innobase::write_row( } } + /* Set the 'in_update_remember_pos' flag to FALSE to + make sure all columns are fetched in the select done by + update_auto_increment */ + prebuilt->in_update_remember_pos = FALSE; update_auto_increment(); @@ -1482,6 +1523,14 @@ ha_innobase::write_row( auto_inc = table->next_number_field->val_int(); + error = row_lock_table_autoinc_for_mysql(prebuilt); + + if (error != DB_SUCCESS) { + + error = convert_error_code_to_mysql(error); + goto func_exit; + } + dict_table_autoinc_initialize(prebuilt->table, auto_inc); } @@ -1510,8 +1559,12 @@ ha_innobase::write_row( prebuilt->trx->ignore_duplicates_in_insert = FALSE; } + srv_conc_enter_innodb(prebuilt->trx); + error = row_insert_for_mysql((byte*) record, prebuilt); + srv_conc_exit_innodb(); + prebuilt->trx->ignore_duplicates_in_insert = FALSE; error = convert_error_code_to_mysql(error); @@ -1725,8 +1778,12 @@ ha_innobase::update_row( assert(prebuilt->template_type == ROW_MYSQL_WHOLE_ROW); } + srv_conc_enter_innodb(prebuilt->trx); + error = row_update_for_mysql((byte*) old_row, prebuilt); + srv_conc_exit_innodb(); + error = convert_error_code_to_mysql(error); /* Tell InnoDB server that there might be work for @@ -1765,8 +1822,12 @@ ha_innobase::delete_row( prebuilt->upd_node->is_delete = TRUE; prebuilt->in_update_remember_pos = TRUE; + srv_conc_enter_innodb(prebuilt->trx); + error = row_update_for_mysql((byte*) record, prebuilt); + srv_conc_exit_innodb(); + error = convert_error_code_to_mysql(error); /* Tell the InnoDB server that there might be work for @@ -1789,7 +1850,7 @@ ha_innobase::index_init( int error = 0; DBUG_ENTER("index_init"); - change_active_index(keynr); + error = change_active_index(keynr); DBUG_RETURN(error); } @@ -1905,8 +1966,12 @@ ha_innobase::index_read( last_match_mode = match_mode; + srv_conc_enter_innodb(prebuilt->trx); + ret = row_search_for_mysql((byte*) buf, mode, prebuilt, match_mode, 0); + srv_conc_exit_innodb(); + if (ret == DB_SUCCESS) { error = 0; table->status = 0; @@ -1956,11 +2021,20 @@ ha_innobase::change_active_index( prebuilt->table); } + if (!prebuilt->index) { + fprintf(stderr, + "InnoDB: Could not find key n:o %u with name %s from dict cache\n" + "InnoDB: for table %s\n", keynr, key->name, prebuilt->table->name); + + return(1); + } + + assert(prebuilt->search_tuple); + dtuple_set_n_fields(prebuilt->search_tuple, prebuilt->index->n_fields); dict_index_copy_types(prebuilt->search_tuple, prebuilt->index, prebuilt->index->n_fields); - assert(prebuilt->index); /* Maybe MySQL changes the active index for a handle also during some queries, we do not know: then it is safest to build @@ -1989,7 +2063,10 @@ ha_innobase::index_read_idx( uint key_len, /* in: key value length */ enum ha_rkey_function find_flag)/* in: search flags from my_base.h */ { - change_active_index(keynr); + if (change_active_index(keynr)) { + + return(1); + } return(index_read(buf, key, key_len, find_flag)); } @@ -2015,8 +2092,11 @@ ha_innobase::general_fetch( DBUG_ENTER("general_fetch"); - ret = row_search_for_mysql((byte*)buf, 0, prebuilt, - match_mode, direction); + srv_conc_enter_innodb(prebuilt->trx); + + ret = row_search_for_mysql((byte*)buf, 0, prebuilt, match_mode, + direction); + srv_conc_exit_innodb(); if (ret == DB_SUCCESS) { error = 0; @@ -2148,17 +2228,19 @@ ha_innobase::rnd_init( /* out: 0 or error number */ bool scan) /* in: ???????? */ { + int err; + row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt; if (prebuilt->clust_index_was_generated) { - change_active_index(MAX_KEY); + err = change_active_index(MAX_KEY); } else { - change_active_index(primary_key); + err = change_active_index(primary_key); } start_of_scan = 1; - return(0); + return(err); } /********************************************************************* @@ -2226,11 +2308,15 @@ ha_innobase::rnd_pos( row reference is the row id, not any key value that MySQL knows */ - change_active_index(MAX_KEY); + error = change_active_index(MAX_KEY); } else { - change_active_index(primary_key); + error = change_active_index(primary_key); } + if (error) { + DBUG_RETURN(error); + } + error = index_read(buf, pos, ref_stored_len, HA_READ_KEY_EXACT); change_active_index(keynr); @@ -2285,11 +2371,21 @@ ha_innobase::extra( 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; - default: /* Do nothing */ - ; + prebuilt->in_update_remember_pos = FALSE; + break; + case HA_EXTRA_KEYREAD: + prebuilt->read_just_key = 1; + break; + default:/* Do nothing */ + ; } return(0); @@ -2327,6 +2423,8 @@ ha_innobase::external_lock( prebuilt->sql_stat_start = TRUE; prebuilt->in_update_remember_pos = TRUE; + prebuilt->read_just_key = 0; + if (lock_type == F_WRLCK) { /* If this is a SELECT, then it is in UPDATE TABLE ... @@ -2338,6 +2436,7 @@ ha_innobase::external_lock( if (trx->n_mysql_tables_in_use == 0) { trx_mark_sql_stat_end(trx); } + thd->transaction.all.innodb_active_trans = 1; trx->n_mysql_tables_in_use++; @@ -2347,6 +2446,7 @@ ha_innobase::external_lock( } } else { trx->n_mysql_tables_in_use--; + auto_inc_counter_for_this_stat = 0; if (trx->n_mysql_tables_in_use == 0) { @@ -2363,11 +2463,14 @@ ha_innobase::external_lock( some table in this SQL statement, we release it now */ + srv_conc_enter_innodb(trx); row_unlock_table_autoinc_for_mysql(trx); + srv_conc_exit_innodb(); } if (!(thd->options & (OPTION_NOT_AUTO_COMMIT | OPTION_BEGIN))) { + innobase_commit(thd, trx); } } @@ -2636,6 +2739,12 @@ ha_innobase::create( trx_commit_for_mysql(trx); + /* Flush the log to reduce probability that the .frm files and + the InnoDB data dictionary get out-of-sync if the user runs + with innodb_flush_log_at_trx_commit = 0 */ + + log_flush_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP); + innobase_table = dict_table_get(norm_name, NULL); assert(innobase_table); @@ -2685,6 +2794,12 @@ ha_innobase::delete_table( error = row_drop_table_for_mysql(norm_name, trx, FALSE); + /* Flush the log to reduce probability that the .frm files and + the InnoDB data dictionary get out-of-sync if the user runs + with innodb_flush_log_at_trx_commit = 0 */ + + log_flush_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP); + /* Tell the InnoDB server that there might be work for utility threads: */ @@ -2732,6 +2847,12 @@ innobase_drop_database( error = row_drop_database_for_mysql(namebuf, trx); + /* Flush the log to reduce probability that the .frm files and + the InnoDB data dictionary get out-of-sync if the user runs + with innodb_flush_log_at_trx_commit = 0 */ + + log_flush_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP); + /* Tell the InnoDB server that there might be work for utility threads: */ @@ -2778,6 +2899,12 @@ ha_innobase::rename_table( error = row_rename_table_for_mysql(norm_from, norm_to, trx); + /* Flush the log to reduce probability that the .frm files and + the InnoDB data dictionary get out-of-sync if the user runs + with innodb_flush_log_at_trx_commit = 0 */ + + log_flush_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP); + /* Tell the InnoDB server that there might be work for utility threads: */ @@ -3062,31 +3189,41 @@ ha_innobase::check( } /***************************************************************** -Adds information about free space in the InnoDB tablespace to a -table comment which is printed out when a user calls SHOW TABLE STATUS. */ +Adds information about free space in the InnoDB tablespace to a table comment +which is printed out when a user calls SHOW TABLE STATUS. Adds also info on +foreign keys. */ char* ha_innobase::update_table_comment( /*==============================*/ - const char* comment) + /* out: table comment + InnoDB free space + + info on foreign keys */ + const char* comment)/* in: table comment defined by user */ { - uint length=strlen(comment); + row_prebuilt_t* prebuilt = (row_prebuilt_t*)innobase_prebuilt; + uint length = strlen(comment); + char* str = my_malloc(length + 200, MYF(0)); + char* pos; - char *str=my_malloc(length + 100,MYF(0)), *pos; + if (!str) { + return((char*)comment); + } - if (!str) - return (char*)comment; + pos = str; + if (length) { + pos=strmov(str, comment); + *pos++=';'; + *pos++=' '; + } - pos=str; - if (length) - { - pos=strmov(str,comment); - *pos++=';'; - *pos++=' '; - } - sprintf(pos, "InnoDB free: %lu kB", (ulong) innobase_get_free_space()); + pos += sprintf(pos, "InnoDB free: %lu kB", + (ulong) innobase_get_free_space()); - return(str); + /* We assume 150 bytes of space to print info */ + + dict_print_info_on_foreign_keys(pos, 150, prebuilt->table); + + return(str); } /**************************************************************************** diff --git a/sql/ha_innobase.h b/sql/ha_innobase.h index 404b20edbac..95bba76c842 100644 --- a/sql/ha_innobase.h +++ b/sql/ha_innobase.h @@ -63,7 +63,7 @@ class ha_innobase: public handler uint last_match_mode;/* match mode of the latest search: ROW_SEL_EXACT, ROW_SEL_EXACT_PREFIX, or undefined */ - + longlong auto_inc_counter_for_this_stat; ulong max_row_length(const byte *buf); uint store_key_val_for_row(uint keynr, char* buff, const byte* record); @@ -96,7 +96,10 @@ class ha_innobase: public handler uint max_record_length() const { return HA_MAX_REC_LENGTH; } uint max_keys() const { return MAX_KEY; } uint max_key_parts() const { return MAX_REF_PARTS; } - uint max_key_length() const { return MAX_KEY_LENGTH; } + /* An InnoDB page must store >= 2 keys: + max key length is therefore set to 7000 + bytes */ + uint max_key_length() const { return 7000; } bool fast_key_read() { return 1;} bool has_transactions() { return 1;} @@ -161,11 +164,12 @@ extern long innobase_mirrored_log_groups, innobase_log_files_in_group; extern long innobase_log_file_size, innobase_log_buffer_size; extern long innobase_buffer_pool_size, innobase_additional_mem_pool_size; extern long innobase_file_io_threads, innobase_lock_wait_timeout; +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_use_native_aio, innobase_fast_shutdown; extern TYPELIB innobase_lock_typelib; diff --git a/sql/ha_myisammrg.cc b/sql/ha_myisammrg.cc index 0a2ef534ad1..d82c202baa3 100644 --- a/sql/ha_myisammrg.cc +++ b/sql/ha_myisammrg.cc @@ -181,7 +181,11 @@ void ha_myisammrg::info(uint flag) mean_rec_length=info.reclength; block_size=0; update_time=0; +#if SIZEOF_OFF_T > 4 ref_length=6; // Should be big enough +#else + ref_length=4; // Can't be > than my_off_t +#endif } diff --git a/sql/handler.cc b/sql/handler.cc index 742bcd3aa0a..9bf9b25f76f 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -642,6 +642,15 @@ void handler::print_error(int error, myf errflag) case HA_ERR_READ_ONLY_TRANSACTION: textno=ER_READ_ONLY_TRANSACTION; break; + case HA_ERR_CANNOT_ADD_FOREIGN: + textno=ER_CANNOT_ADD_FOREIGN; + break; + case HA_ERR_ROW_IS_REFERENCED: + textno=ER_ROW_IS_REFERENCED; + break; + case HA_ERR_NO_REFERENCED_ROW: + textno=ER_NO_REFERENCED_ROW; + break; default: { my_error(ER_GET_ERRNO,errflag,error); diff --git a/sql/item.h b/sql/item.h index df2b1aa243d..1bcbc4c7f0f 100644 --- a/sql/item.h +++ b/sql/item.h @@ -309,6 +309,7 @@ public: Item_result_field() :result_field(0) {} ~Item_result_field() {} /* Required with gcc 2.95 */ Field *tmp_table_field() { return result_field; } + table_map used_tables() const { return 1; } virtual void fix_length_and_dec()=0; }; diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index b305b5ccec3..a8bd219eef1 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -248,8 +248,10 @@ longlong Item_func_unix_timestamp::val_int() longlong Item_func_time_to_sec::val_int() { TIME ltime; + longlong seconds; (void) get_arg0_time(<ime); - return ltime.hour*3600L+ltime.minute*60+ltime.second; + seconds=ltime.hour*3600L+ltime.minute*60+ltime.second; + return ltime.neg ? -seconds : seconds; } diff --git a/sql/log.cc b/sql/log.cc index 51bf077895a..b55d514058f 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -516,36 +516,46 @@ bool MYSQL_LOG::is_active(const char* log_file_name) void MYSQL_LOG::new_file(bool inside_mutex) { - // only rotate open logs that are marked non-rotatable - // (binlog with constant name are non-rotatable) - if (is_open() && ! no_rotate) + if (is_open()) { char new_name[FN_REFLEN], *old_name=name; if (!inside_mutex) VOID(pthread_mutex_lock(&LOCK_log)); - if (generate_new_name(new_name, name)) - { - if (!inside_mutex) - VOID(pthread_mutex_unlock(&LOCK_log)); - return; // Something went wrong - } - if (log_type == LOG_BIN) + + if (!no_rotate) { /* - We log the whole file name for log file as the user may decide - to change base names at some point. + only rotate open logs that are marked non-rotatable + (binlog with constant name are non-rotatable) */ - THD* thd = current_thd; - Rotate_log_event r(thd,new_name+dirname_length(new_name)); - r.set_log_seq(0, this); - // this log rotation could have been initiated by a master of - // the slave running with log-bin - // we set the flag on rotate event to prevent inifinite log rotation - // loop - if(thd && slave_thd && thd == slave_thd) - r.flags |= LOG_EVENT_FORCED_ROTATE_F; - r.write(&log_file); - VOID(pthread_cond_broadcast(&COND_binlog_update)); + if (generate_new_name(new_name, name)) + { + if (!inside_mutex) + VOID(pthread_mutex_unlock(&LOCK_log)); + return; // Something went wrong + } + if (log_type == LOG_BIN) + { + /* + We log the whole file name for log file as the user may decide + to change base names at some point. + */ + THD* thd = current_thd; + Rotate_log_event r(thd,new_name+dirname_length(new_name)); + r.set_log_seq(0, this); + + /* + This log rotation could have been initiated by a master of + the slave running with log-bin we set the flag on rotate + event to prevent inifinite log rotation loop + */ + if (thd && slave_thd && thd == slave_thd) + r.flags |= LOG_EVENT_FORCED_ROTATE_F; + r.write(&log_file); + VOID(pthread_cond_broadcast(&COND_binlog_update)); + } + else + strmov(new_name, old_name); // Reopen old file name } name=0; close(); @@ -843,7 +853,7 @@ 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 Rows_examined: %lu\n", + "# Query_time: %lu Lock_time: %lu Rows_sent: %lu Rows_examined: %lu\n", (ulong) (current_time - query_start), (ulong) (thd->time_after_lock - query_start), (ulong) thd->sent_row_count, diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 61eba065f9a..45812754cad 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1237,7 +1237,7 @@ the thread stack. Please read http://www.mysql.com/doc/L/i/Linux.html\n\n", Some pointers may be invalid and cause the dump to abort...\n"); safe_print_str("thd->query", thd->query, 1024); fprintf(stderr, "thd->thread_id=%ld\n", thd->thread_id); - fprintf(stderr, "\n + fprintf(stderr, "\n\ Successfully dumped variables, if you ran with --log, take a look at the\n\ details of what thread %ld did to cause the crash. In some cases of really\n\ bad corruption, the values shown above may be invalid.\n\n", @@ -2083,14 +2083,18 @@ int main(int argc, char **argv) { if (argc == 2) { + char path[FN_REFLEN]; + my_path(path, argv[0], ""); // Find name in path + fn_format(path,argv[0],path,"",1+4+16); // Force use of full path + if (!strcmp(argv[1],"-install") || !strcmp(argv[1],"--install")) { - char path[FN_REFLEN]; - my_path(path, argv[0], ""); // Find name in path - fn_format(path,argv[0],path,"",1+4+16); // Force use of full path - if (!Service.Install(MYSQL_SERVICENAME,MYSQL_SERVICENAME,path)) - MessageBox(NULL,"Failed to install Service",MYSQL_SERVICENAME, - MB_OK|MB_ICONSTOP); + Service.Install(1,MYSQL_SERVICENAME,MYSQL_SERVICENAME,path); + return 0; + } + else if (!strcmp(argv[1],"-install-manual") || !strcmp(argv[1],"--install-manual")) + { + Service.Install(0,MYSQL_SERVICENAME,MYSQL_SERVICENAME,path); return 0; } else if (!strcmp(argv[1],"-remove") || !strcmp(argv[1],"--remove")) @@ -2586,6 +2590,7 @@ enum options { OPT_INNODB_LOG_ARCHIVE, OPT_INNODB_FLUSH_LOG_AT_TRX_COMMIT, OPT_INNODB_FLUSH_METHOD, + OPT_INNODB_FAST_SHUTDOWN, OPT_SAFE_SHOW_DB, OPT_INNODB_SKIP, OPT_SKIP_SAFEMALLOC, OPT_TEMP_POOL, OPT_TX_ISOLATION, @@ -2648,6 +2653,8 @@ static struct option long_options[] = { OPT_INNODB_LOG_ARCHIVE}, {"innodb_flush_log_at_trx_commit", optional_argument, 0, OPT_INNODB_FLUSH_LOG_AT_TRX_COMMIT}, + {"innodb_fast_shutdown", optional_argument, 0, + OPT_INNODB_FAST_SHUTDOWN}, {"innodb_flush_method", required_argument, 0, OPT_INNODB_FLUSH_METHOD}, #endif @@ -2762,6 +2769,8 @@ static struct option long_options[] = { {0, 0, 0, 0} }; +#define LONG_TIMEOUT ((ulong) 3600L*24L*365L) + CHANGEABLE_VAR changeable_vars[] = { { "back_log", (long*) &back_log, 50, 1, 65535, 0, 1 }, @@ -2779,15 +2788,15 @@ CHANGEABLE_VAR changeable_vars[] = { { "binlog_cache_size", (long*) &binlog_cache_size, 32*1024L, IO_SIZE, ~0L, 0, IO_SIZE }, { "connect_timeout", (long*) &connect_timeout, - CONNECT_TIMEOUT, 2, 65535, 0, 1 }, + CONNECT_TIMEOUT, 2, LONG_TIMEOUT, 0, 1 }, { "delayed_insert_timeout", (long*) &delayed_insert_timeout, - DELAYED_WAIT_TIMEOUT, 1, ~0L, 0, 1 }, + DELAYED_WAIT_TIMEOUT, 1, LONG_TIMEOUT, 0, 1 }, { "delayed_insert_limit", (long*) &delayed_insert_limit, DELAYED_LIMIT, 1, ~0L, 0, 1 }, { "delayed_queue_size", (long*) &delayed_queue_size, DELAYED_QUEUE_SIZE, 1, ~0L, 0, 1 }, { "flush_time", (long*) &flush_time, - FLUSH_TIME, 0, ~0L, 0, 1 }, + FLUSH_TIME, 0, LONG_TIMEOUT, 0, 1 }, { "ft_min_word_len", (long*) &ft_min_word_len, 4, 1, HA_FT_MAXLEN, 0, 1 }, { "ft_max_word_len", (long*) &ft_max_word_len, @@ -2816,15 +2825,19 @@ CHANGEABLE_VAR changeable_vars[] = { {"innodb_lock_wait_timeout", (long*) &innobase_lock_wait_timeout, 1024 * 1024 * 1024, 1, 1024 * 1024 * 1024, 0, 1}, + {"innodb_thread_concurrency", + (long*) &innobase_thread_concurrency, 8, 1, 1000, 0, 1}, + {"innodb_force_recovery", + (long*) &innobase_force_recovery, 0, 0, 6, 0, 1}, #endif { "interactive_timeout", (long*) &net_interactive_timeout, - NET_WAIT_TIMEOUT, 1, 31*24*60*60, 0, 1 }, + NET_WAIT_TIMEOUT, 1, LONG_TIMEOUT, 0, 1 }, { "join_buffer_size", (long*) &join_buff_size, 128*1024L, IO_SIZE*2+MALLOC_OVERHEAD, ~0L, MALLOC_OVERHEAD, IO_SIZE }, { "key_buffer_size", (long*) &keybuff_size, KEY_CACHE_SIZE, MALLOC_OVERHEAD, (long) ~0, MALLOC_OVERHEAD, IO_SIZE }, { "long_query_time", (long*) &long_query_time, - 10, 1, ~0L, 0, 1 }, + 10, 1, LONG_TIMEOUT, 0, 1 }, { "lower_case_table_names", (long*) &lower_case_table_names, IF_WIN(1,0), 0, 1, 0, 1 }, { "max_allowed_packet", (long*) &max_allowed_packet, @@ -2868,9 +2881,9 @@ CHANGEABLE_VAR changeable_vars[] = { { "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, 1, 65535, 0, 1 }, + NET_READ_TIMEOUT, 1, LONG_TIMEOUT, 0, 1 }, { "net_write_timeout", (long*) &net_write_timeout, - NET_WRITE_TIMEOUT, 1, 65535, 0, 1 }, + NET_WRITE_TIMEOUT, 1, LONG_TIMEOUT, 0, 1 }, { "open_files_limit", (long*) &open_files_limit, 0, 0, 65535, 0, 1}, { "query_buffer_size", (long*) &query_buff_size, @@ -2880,9 +2893,9 @@ CHANGEABLE_VAR changeable_vars[] = { { "record_rnd_buffer", (long*) &record_rnd_cache_size, 0, IO_SIZE*2+MALLOC_OVERHEAD, ~0L, MALLOC_OVERHEAD, IO_SIZE }, { "slave_net_timeout", (long*) &slave_net_timeout, - SLAVE_NET_TIMEOUT, 1, 65535, 0, 1 }, + SLAVE_NET_TIMEOUT, 1, LONG_TIMEOUT, 0, 1 }, { "slow_launch_time", (long*) &slow_launch_time, - 2L, 0L, ~0L, 0, 1 }, + 2L, 0L, LONG_TIMEOUT, 0, 1 }, { "sort_buffer", (long*) &sortbuff_size, MAX_SORT_MEMORY, MIN_SORT_MEMORY+MALLOC_OVERHEAD*2, ~0L, MALLOC_OVERHEAD, 1 }, { "table_cache", (long*) &table_cache_size, @@ -2896,7 +2909,7 @@ CHANGEABLE_VAR changeable_vars[] = { { "thread_stack", (long*) &thread_stack, DEFAULT_THREAD_STACK, 1024*32, ~0L, 0, 1024 }, { "wait_timeout", (long*) &net_wait_timeout, - NET_WAIT_TIMEOUT, 1, ~0L, 0, 1 }, + NET_WAIT_TIMEOUT, 1, LONG_TIMEOUT, 0, 1 }, { NullS, (long*) 0, 0, 0, 0, 0, 0} }; @@ -2942,7 +2955,10 @@ struct show_var_st init_vars[]= { {"innodb_data_file_path", (char*) &innobase_data_file_path, SHOW_CHAR_PTR}, {"innodb_data_home_dir", (char*) &innobase_data_home_dir, SHOW_CHAR_PTR}, {"innodb_file_io_threads", (char*) &innobase_file_io_threads, SHOW_LONG }, + {"innodb_force_recovery", (char*) &innobase_force_recovery, SHOW_LONG }, + {"innodb_thread_concurrency", (char*) &innobase_thread_concurrency, SHOW_LONG }, {"innodb_flush_log_at_trx_commit", (char*) &innobase_flush_log_at_trx_commit, SHOW_MY_BOOL}, + {"innodb_fast_shutdown", (char*) &innobase_fast_shutdown, SHOW_MY_BOOL}, {"innodb_flush_method", (char*) &innobase_unix_file_flush_method, SHOW_CHAR_PTR}, {"innodb_lock_wait_timeout", (char*) &innobase_lock_wait_timeout, SHOW_LONG }, {"innodb_log_arch_dir", (char*) &innobase_log_arch_dir, SHOW_CHAR_PTR}, @@ -3869,6 +3885,8 @@ static void get_options(int argc,char **argv) break; case OPT_INNODB_FLUSH_LOG_AT_TRX_COMMIT: innobase_flush_log_at_trx_commit= optarg ? test(atoi(optarg)) : 1; + case OPT_INNODB_FAST_SHUTDOWN: + innobase_fast_shutdown= optarg ? test(atoi(optarg)) : 1; break; case OPT_INNODB_FLUSH_METHOD: innobase_unix_file_flush_method=optarg; diff --git a/sql/nt_servc.cc b/sql/nt_servc.cc index 3a36f5740a9..6930800982e 100644 --- a/sql/nt_servc.cc +++ b/sql/nt_servc.cc @@ -5,6 +5,7 @@ -------------------------------------------------------------------------- */ #include <windows.h> #include <process.h> +#include <stdio.h> #include "nt_servc.h" @@ -52,11 +53,12 @@ NTService::NTService() -------------------------------------------------------------------------- */ NTService::~NTService() { - if(ServiceName != NULL) delete[] ServiceName; + if (ServiceName != NULL) delete[] ServiceName; } /* ------------------------------------------------------------------------ -------------------------------------------------------------------------- */ + BOOL NTService::GetOS() { bOsNT = FALSE; @@ -70,12 +72,14 @@ BOOL NTService::GetOS() return bOsNT; } + /* ------------------------------------------------------------------------ Init() Registers the main service thread with the service manager ServiceThread - pointer to the main programs entry function when the service is started -------------------------------------------------------------------------- */ + long NTService::Init(LPCSTR szInternName,void *ServiceThread) { @@ -93,6 +97,8 @@ long NTService::Init(LPCSTR szInternName,void *ServiceThread) return StartServiceCtrlDispatcher(stb); //register with the Service Manager } + + /* ------------------------------------------------------------------------ Install() - Installs the service with Service manager nError values: @@ -100,41 +106,55 @@ long NTService::Init(LPCSTR szInternName,void *ServiceThread) 1 Can't open the Service manager 2 Failed to create service -------------------------------------------------------------------------- */ -BOOL NTService::Install(LPCSTR szInternName,LPCSTR szDisplayName, - LPCSTR szFullPath, LPCSTR szAccountName,LPCSTR szPassword) + +BOOL NTService::Install(int startType, LPCSTR szInternName, + LPCSTR szDisplayName, + LPCSTR szFullPath, LPCSTR szAccountName, + LPCSTR szPassword) { + BOOL ret_val=FALSE; SC_HANDLE newService, scm; - nError=0; + if (!SeekStatus(szInternName,1)) + return FALSE; + + char szFilePath[_MAX_PATH]; + GetModuleFileName(NULL, szFilePath, sizeof(szFilePath)); // open a connection to the SCM - scm = OpenSCManager(0, 0,SC_MANAGER_CREATE_SERVICE); - if(scm) // Install the new service - { newService = CreateService( - scm, - szInternName, - szDisplayName, - dwDesiredAccess, //default: SERVICE_ALL_ACCESS - dwServiceType, //default: SERVICE_WIN32_OWN_PROCESS - dwStartType, //default: SERVICE_AUTOSTART - dwErrorControl, //default: SERVICE_ERROR_NORMAL - szFullPath, //exec full path - szLoadOrderGroup, //default: NULL - lpdwTagID, //default: NULL - szDependencies, //default: NULL - szAccountName, //default: NULL - szPassword); //default: NULL - - if (newService) CloseServiceHandle(newService); // clean up - else nError=2; - - // clean up + if (!(scm = OpenSCManager(0, 0,SC_MANAGER_CREATE_SERVICE))) + printf("Failed to install the service (Couldn't open the SCM)\n"); + else // Install the new service + { + if (!(newService= + CreateService(scm, + szInternName, + szDisplayName, + dwDesiredAccess,//default: SERVICE_ALL_ACCESS + dwServiceType, //default: SERVICE_WIN32_OWN_PROCESS + //default: SERVICE_AUTOSTART + (startType == 1 ? SERVICE_AUTO_START : + SERVICE_DEMAND_START), + dwErrorControl, //default: SERVICE_ERROR_NORMAL + szFullPath, //exec full path + szLoadOrderGroup, //default: NULL + lpdwTagID, //default: NULL + szDependencies, //default: NULL + szAccountName, //default: NULL + szPassword))) //default: NULL + printf("Failed to install the service (Couldn't create service)\n"); + else + { + printf("Service successfully installed.\n"); + CloseServiceHandle(newService); + ret_val=TRUE; // Everything went ok + } CloseServiceHandle(scm); } - else nError=1; - - return (!nError); + return ret_val; } + + /* ------------------------------------------------------------------------ Remove() - Removes the service nError values: @@ -143,35 +163,40 @@ BOOL NTService::Install(LPCSTR szInternName,LPCSTR szDisplayName, 2 Failed to locate service 3 Failed to delete service -------------------------------------------------------------------------- */ + BOOL NTService::Remove(LPCSTR szInternName) { - + BOOL ret_value=FALSE; SC_HANDLE service, scm; + if (!SeekStatus(szInternName,0)) + return FALSE; + nError=0; // open a connection to the SCM - scm = OpenSCManager(0, 0,SC_MANAGER_CREATE_SERVICE); - - if (scm) + if (!(scm = OpenSCManager(0, 0,SC_MANAGER_CREATE_SERVICE))) + { + printf("Failed to remove the service (Couldn't open the SCM)\n"); + } + else { - //open the service - service = OpenService(scm,szInternName, DELETE ); - if(service) + if ((service = OpenService(scm,szInternName, DELETE))) { - if(!DeleteService(service)) nError=3; + if (!DeleteService(service)) + printf("Failed to remove the service\n"); + else + { + printf("Service successfully removed.\n"); + ret_value=TRUE; // everything went ok + } CloseServiceHandle(service); } else - { - //MessageBox(NULL,"Can't find the service","Remove Error",MB_OK|MB_ICONHAND); - nError=2; - } + printf("Failed to remove the service (Couldn't open the service)\n"); CloseServiceHandle(scm); } - else nError=1; - - return (!nError); + return ret_value; } /* ------------------------------------------------------------------------ @@ -189,80 +214,66 @@ void NTService::Stop(void) ServiceMain() - This is the function that is called from the service manager to start the service -------------------------------------------------------------------------- */ + void NTService::ServiceMain(DWORD argc, LPTSTR *argv) { // registration function - pService->hServiceStatusHandle = - RegisterServiceCtrlHandler(pService->ServiceName, - (LPHANDLER_FUNCTION )NTService::ServiceCtrlHandler); - - if(!pService->hServiceStatusHandle) - { - pService->Exit(GetLastError()); - return; - } + if (!(pService->hServiceStatusHandle = + RegisterServiceCtrlHandler(pService->ServiceName, + (LPHANDLER_FUNCTION) + NTService::ServiceCtrlHandler))) + goto error; // notify SCM of progress - if(!pService->SetStatus(SERVICE_START_PENDING,NO_ERROR, 0, 1, 8000)) - { - pService->Exit(GetLastError()); - return; - } + if (!pService->SetStatus(SERVICE_START_PENDING,NO_ERROR, 0, 1, 8000)) + goto error; // create the exit event - pService->hExitEvent = CreateEvent (0, TRUE, FALSE,0); - if(!pService->hExitEvent) - { - pService->Exit(GetLastError()); - return; - } + if (!(pService->hExitEvent = CreateEvent (0, TRUE, FALSE,0))) + goto error; - if(!pService->SetStatus(SERVICE_START_PENDING,NO_ERROR, 0, 3, pService->nStartTimeOut)) - { - pService->Exit(GetLastError()); - return; - } + if (!pService->SetStatus(SERVICE_START_PENDING,NO_ERROR, 0, 3, + pService->nStartTimeOut)) + goto error; // save start arguments pService->my_argc=argc; pService->my_argv=argv; // start the service - if(!pService->StartService()) - { - pService->Exit(GetLastError()); - return; - } + if (!pService->StartService()) + goto error; - // the service is now running. - if(!pService->SetStatus(SERVICE_RUNNING,NO_ERROR, 0, 0, 0)) - { - pService->Exit(GetLastError()); - return; - } + // Check that the service is now running. + if (!pService->SetStatus(SERVICE_RUNNING,NO_ERROR, 0, 0, 0)) + goto error; // wait for exit event WaitForSingleObject (pService->hExitEvent, INFINITE); // wait for thread to exit - if (WaitForSingleObject (pService->hThreadHandle, 1000)==WAIT_TIMEOUT) + if (WaitForSingleObject (pService->hThreadHandle, 1000) == WAIT_TIMEOUT) CloseHandle(pService->hThreadHandle); pService->Exit(0); + return; + +error: + pService->Exit(GetLastError()); + return; } /* ------------------------------------------------------------------------ StartService() - starts the appliaction thread -------------------------------------------------------------------------- */ + BOOL NTService::StartService() { - // Start the real service's thread (application) - hThreadHandle = (HANDLE) _beginthread((THREAD_FC)fpServiceThread,0,(void *)this); - - if (hThreadHandle==0) return FALSE; - + if (!(hThreadHandle = (HANDLE) _beginthread((THREAD_FC)fpServiceThread,0, + (void *) this))) + return FALSE; bRunning = TRUE; return TRUE; } @@ -274,7 +285,7 @@ void NTService::StopService() bRunning=FALSE; // Set the event for application - if(hShutdownEvent) + if (hShutdownEvent) SetEvent(hShutdownEvent); // Set the event for ServiceMain @@ -285,117 +296,186 @@ void NTService::StopService() -------------------------------------------------------------------------- */ void NTService::PauseService() { - bPause = TRUE; - SuspendThread(hThreadHandle); + bPause = TRUE; + SuspendThread(hThreadHandle); } /* ------------------------------------------------------------------------ -------------------------------------------------------------------------- */ void NTService::ResumeService() { - bPause=FALSE; - ResumeThread(hThreadHandle); + bPause=FALSE; + ResumeThread(hThreadHandle); } /* ------------------------------------------------------------------------ -------------------------------------------------------------------------- */ BOOL NTService::SetStatus (DWORD dwCurrentState,DWORD dwWin32ExitCode, - DWORD dwServiceSpecificExitCode,DWORD dwCheckPoint,DWORD dwWaitHint) + DWORD dwServiceSpecificExitCode, DWORD dwCheckPoint, + DWORD dwWaitHint) { BOOL bRet; SERVICE_STATUS serviceStatus; - dwState=dwCurrentState; - - serviceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; - serviceStatus.dwCurrentState = dwCurrentState; + dwState=dwCurrentState; - if (dwCurrentState == SERVICE_START_PENDING) - serviceStatus.dwControlsAccepted = 0; //don't accept conrol events - else - serviceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | - SERVICE_ACCEPT_PAUSE_CONTINUE | SERVICE_ACCEPT_SHUTDOWN; + serviceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; + serviceStatus.dwCurrentState = dwCurrentState; - // if a specific exit code is defined,set up the win32 exit code properly - if (dwServiceSpecificExitCode == 0) - serviceStatus.dwWin32ExitCode = dwWin32ExitCode; - else - serviceStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR; + if (dwCurrentState == SERVICE_START_PENDING) + serviceStatus.dwControlsAccepted = 0; //don't accept control events + else + serviceStatus.dwControlsAccepted = (SERVICE_ACCEPT_STOP | + SERVICE_ACCEPT_PAUSE_CONTINUE | + SERVICE_ACCEPT_SHUTDOWN); - serviceStatus.dwServiceSpecificExitCode = dwServiceSpecificExitCode; + // if a specific exit code is defined,set up the win32 exit code properly + if (dwServiceSpecificExitCode == 0) + serviceStatus.dwWin32ExitCode = dwWin32ExitCode; + else + serviceStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR; - serviceStatus.dwCheckPoint = dwCheckPoint; - serviceStatus.dwWaitHint = dwWaitHint; + serviceStatus.dwServiceSpecificExitCode = dwServiceSpecificExitCode; - // Pass the status to the Service Manager - bRet=SetServiceStatus (hServiceStatusHandle, &serviceStatus); + serviceStatus.dwCheckPoint = dwCheckPoint; + serviceStatus.dwWaitHint = dwWaitHint; - if(!bRet) StopService(); + // Pass the status to the Service Manager + if (!(bRet=SetServiceStatus (hServiceStatusHandle, &serviceStatus))) + StopService(); - return bRet; + return bRet; } /* ------------------------------------------------------------------------ -------------------------------------------------------------------------- */ void NTService::ServiceCtrlHandler(DWORD ctrlCode) { + DWORD dwState; - DWORD dwState = 0; - - if(!pService) return; + if (!pService) + return; dwState=pService->dwState; // get current state - switch(ctrlCode) - { + switch(ctrlCode) { - /*********** do we need this ? ******************************* - case SERVICE_CONTROL_PAUSE: - if (pService->bRunning && ! pService->bPause) - { - dwState = SERVICE_PAUSED; - pService->SetStatus(SERVICE_PAUSE_PENDING,NO_ERROR, 0, 1, pService->nPauseTimeOut); - pService->PauseService(); - } - break; - - case SERVICE_CONTROL_CONTINUE: - if (pService->bRunning && pService->bPause) - { - dwState = SERVICE_RUNNING; - pService->SetStatus(SERVICE_CONTINUE_PENDING,NO_ERROR, 0, 1, pService->nResumeTimeOut); - pService->ResumeService(); - } - break; - ****************************************************************/ - - case SERVICE_CONTROL_SHUTDOWN: - case SERVICE_CONTROL_STOP: - dwState = SERVICE_STOP_PENDING; - pService->SetStatus(SERVICE_STOP_PENDING,NO_ERROR, 0, 1, pService->nStopTimeOut); - pService->StopService(); - break; - - default: - pService->SetStatus(dwState, NO_ERROR,0, 0, 0); - break; +#ifdef NOT_USED /* do we need this ? */ + case SERVICE_CONTROL_PAUSE: + if (pService->bRunning && ! pService->bPause) + { + dwState = SERVICE_PAUSED; + pService->SetStatus(SERVICE_PAUSE_PENDING,NO_ERROR, 0, 1, + pService->nPauseTimeOut); + pService->PauseService(); + } + break; + + case SERVICE_CONTROL_CONTINUE: + if (pService->bRunning && pService->bPause) + { + dwState = SERVICE_RUNNING; + pService->SetStatus(SERVICE_CONTINUE_PENDING,NO_ERROR, 0, 1, + pService->nResumeTimeOut); + pService->ResumeService(); + } + break; +#endif + + case SERVICE_CONTROL_SHUTDOWN: + case SERVICE_CONTROL_STOP: + dwState = SERVICE_STOP_PENDING; + pService->SetStatus(SERVICE_STOP_PENDING,NO_ERROR, 0, 1, + pService->nStopTimeOut); + pService->StopService(); + break; + + default: + pService->SetStatus(dwState, NO_ERROR,0, 0, 0); + break; } //pService->SetStatus(dwState, NO_ERROR,0, 0, 0); } + /* ------------------------------------------------------------------------ -------------------------------------------------------------------------- */ + void NTService::Exit(DWORD error) { - if (hExitEvent) CloseHandle(hExitEvent); + if (hExitEvent) + CloseHandle(hExitEvent); // Send a message to the scm to tell that we stop if (hServiceStatusHandle) - SetStatus(SERVICE_STOPPED, error,0, 0, 0); + SetStatus(SERVICE_STOPPED, error,0, 0, 0); // If the thread has started kill it ??? // if (hThreadHandle) CloseHandle(hThreadHandle); } -/* ------------------------- the end -------------------------------------- */ +/* ------------------------------------------------------------------------ + + -------------------------------------------------------------------------- */ + +BOOL NTService::SeekStatus(LPCSTR szInternName, int OperationType) +{ + BOOL ret_value=FALSE; + SC_HANDLE service, scm; + + // open a connection to the SCM + if (!(scm = OpenSCManager(0, 0,SC_MANAGER_CREATE_SERVICE))) + printf("There is a problem with the Service Control Manager!\n"); + else + { + if (OperationType == 1) + { + /* an install operation */ + if ((service = OpenService(scm,szInternName, SERVICE_ALL_ACCESS ))) + { + LPQUERY_SERVICE_CONFIG ConfigBuf; + DWORD dwSize; + + ConfigBuf = (LPQUERY_SERVICE_CONFIG) LocalAlloc(LPTR, 4096); + printf("The service already exists!\n"); + if (QueryServiceConfig(service,ConfigBuf,4096,&dwSize)) + printf("The current server installed: %s\n", + ConfigBuf->lpBinaryPathName); + LocalFree(ConfigBuf); + CloseServiceHandle(service); + } + else + ret_value=TRUE; + } + else + { + /* a remove operation */ + if (!(service = OpenService(scm,szInternName, SERVICE_ALL_ACCESS ))) + printf("The service doesn't exists!\n"); + else + { + SERVICE_STATUS ss; + + memset(&ss, 0, sizeof(ss)); + if (QueryServiceStatus(service,&ss)) + { + DWORD dwState = ss.dwCurrentState; + if (dwState == SERVICE_RUNNING) + printf("Failed to remove the service because the service is running\nStop the service and try again\n"); + else if (dwState == SERVICE_STOP_PENDING) + printf("\ +Failed to remove the service because the service is in stop pending state!\n\ +Wait 30 seconds and try again.\n\ +If this condition persist, reboot the machine and try again\n"); + else + ret_value= TRUE; + } + CloseServiceHandle(service); + } + } + CloseServiceHandle(scm); + } + + return ret_value; +} diff --git a/sql/nt_servc.h b/sql/nt_servc.h index 5fda96dc4d8..40d1a8c03fa 100644 --- a/sql/nt_servc.h +++ b/sql/nt_servc.h @@ -48,8 +48,9 @@ class NTService //service install / un-install - BOOL Install(LPCSTR szInternName,LPCSTR szDisplayName,LPCSTR szFullPath, + BOOL Install(int startType,LPCSTR szInternName,LPCSTR szDisplayName,LPCSTR szFullPath, LPCSTR szAccountName=NULL,LPCSTR szPassword=NULL); + BOOL SeekStatus(LPCSTR szInternName, int OperationType); BOOL Remove(LPCSTR szInternName); void Stop(void); //to be called from app. to stop service diff --git a/sql/share/norwegian-ny/.cvsignore b/sql/share/norwegian-ny/.cvsignore deleted file mode 100755 index 2f68f259c40..00000000000 --- a/sql/share/norwegian-ny/.cvsignore +++ /dev/null @@ -1 +0,0 @@ -errmsg.sys diff --git a/sql/share/norwegian/.cvsignore b/sql/share/norwegian/.cvsignore deleted file mode 100755 index 2f68f259c40..00000000000 --- a/sql/share/norwegian/.cvsignore +++ /dev/null @@ -1 +0,0 @@ -errmsg.sys diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 0a553945ea1..befae9103f4 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -616,9 +616,30 @@ int yylex(void *arg) return(IDENT); case STATE_USER_VARIABLE_DELIMITER: - lex->tok_start=lex->ptr; // Skip first ` - while ((c=yyGet()) && state_map[c] != STATE_USER_VARIABLE_DELIMITER && - c != (uchar) NAMES_SEP_CHAR) ; + lex->tok_start=lex->ptr; // Skipp first ` +#ifdef USE_MB + if (use_mb(default_charset_info)) + { + while ((c=yyGet()) && state_map[c] != STATE_USER_VARIABLE_DELIMITER && + c != (uchar) NAMES_SEP_CHAR) + { + if (my_ismbhead(default_charset_info, c)) + { + int l; + if ((l = my_ismbchar(default_charset_info, + (const char *)lex->ptr-1, + (const char *)lex->end_of_query)) == 0) + break; + lex->ptr += l-1; + } + } + } + else +#endif + { + while ((c=yyGet()) && state_map[c] != STATE_USER_VARIABLE_DELIMITER && + c != (uchar) NAMES_SEP_CHAR) ; + } yylval->lex_str=get_token(lex,yyLength()); if (lex->convert_set) lex->convert_set->convert((char*) yylval->lex_str.str,lex->yytoklen); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index f2c25e89bd8..fea3dd7728b 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -3185,7 +3185,8 @@ remove_eq_conds(COND *cond,Item::cond_result *cond_value) /* fix to replace 'NULL' dates with '0' (shreeve@uci.edu) */ else if (((field->type() == FIELD_TYPE_DATE) || (field->type() == FIELD_TYPE_DATETIME)) && - (field->flags & NOT_NULL_FLAG)) + (field->flags & NOT_NULL_FLAG) && + !field->table->maybe_null) { COND *new_cond; if ((new_cond= new Item_func_eq(args[0],new Item_int("0", 0, 2)))) @@ -4083,14 +4084,17 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure) { if (table->group && join->tmp_table_param.sum_func_count) { - DBUG_PRINT("info",("Using end_update")); if (table->keys) { + DBUG_PRINT("info",("Using end_update")); end_select=end_update; table->file->index_init(0); } else + { + DBUG_PRINT("info",("Using end_unique_update")); end_select=end_unique_update; + } } else if (join->sort_and_group) { @@ -4206,8 +4210,6 @@ sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records) int error; bool found=0; COND *on_expr=join_tab->on_expr, *select_cond=join_tab->select_cond; - int (*next_select)(JOIN *,struct st_join_table *,bool)= - join_tab->next_select; if (!(error=(*join_tab->read_first_record)(join_tab))) { @@ -4215,7 +4217,6 @@ 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 { @@ -4224,6 +4225,7 @@ sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records) my_error(ER_SERVER_SHUTDOWN,MYF(0)); /* purecov: inspected */ return -2; /* purecov: inspected */ } + join->examined_rows++; if (!on_expr || on_expr->val_int()) { found=1; @@ -4231,7 +4233,7 @@ sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records) break; // Searching after not null columns if (!select_cond || select_cond->val_int()) { - if ((error=(*next_select)(join,join_tab+1,0)) < 0) + if ((error=(*join_tab->next_select)(join,join_tab+1,0)) < 0) return error; if (not_used_in_distinct && found_records != join->found_records) return 0; @@ -4252,7 +4254,7 @@ sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records) mark_as_null_row(join_tab->table); // For group by without error if (!select_cond || select_cond->val_int()) { - if ((error=(*next_select)(join,join_tab+1,0)) < 0) + if ((error=(*join_tab->next_select)(join,join_tab+1,0)) < 0) return error; /* purecov: inspected */ } } @@ -5449,6 +5451,41 @@ err: DBUG_RETURN(-1); } +/* +** Add the HAVING criteria to table->select +*/ + +#ifdef NOT_YET +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; + + DBUG_EXECUTE("where",print_where(*having,"having");); + 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; +} +#endif + + /***************************************************************************** ** Remove duplicates from tmp table ** This should be recoded to add a uniuqe index to the table and remove diff --git a/sql/time.cc b/sql/time.cc index 440cba457f4..e4565bdeea7 100644 --- a/sql/time.cc +++ b/sql/time.cc @@ -429,7 +429,6 @@ timestamp_type str_to_TIME(const char *str, uint length, TIME *l_time,bool fuzzy_date) { uint field_length,year_length,digits,i,number_of_fields,date[7]; - bool date_used=0; const char *pos; const char *end=str+length; DBUG_ENTER("str_to_TIME"); @@ -455,8 +454,7 @@ str_to_TIME(const char *str, uint length, TIME *l_time,bool fuzzy_date) tmp_value=tmp_value*10 + (uint) (uchar) (*str - '0'); str++; } - if ((date[i]=tmp_value)) - date_used=1; // Found something + date[i]=tmp_value; if (i == 2 && str != end && *str == 'T') str++; // ISO8601: CCYYMMDDThhmmss else if ( i != 5 ) // Skip inter-field delimiters @@ -489,7 +487,7 @@ str_to_TIME(const char *str, uint length, TIME *l_time,bool fuzzy_date) number_of_fields=i; while (i < 6) date[i++]=0; - if (number_of_fields < 3 || !date_used || date[1] > 12 || + if (number_of_fields < 3 || date[1] > 12 || date[2] > 31 || date[3] > 23 || date[4] > 59 || date[5] > 59 || !fuzzy_date && (date[1] == 0 || date[2] == 0)) { |