diff options
Diffstat (limited to 'sql')
-rw-r--r-- | sql/examples/ha_archive.cc | 2 | ||||
-rw-r--r-- | sql/examples/ha_archive.h | 2 | ||||
-rw-r--r-- | sql/examples/ha_example.cc | 2 | ||||
-rw-r--r-- | sql/ha_ndbcluster.cc | 5 | ||||
-rw-r--r-- | sql/item.cc | 21 | ||||
-rw-r--r-- | sql/item.h | 1 | ||||
-rw-r--r-- | sql/log_event.cc | 2 | ||||
-rw-r--r-- | sql/log_event.h | 2 | ||||
-rw-r--r-- | sql/mysqld.cc | 3 | ||||
-rw-r--r-- | sql/sql_db.cc | 74 | ||||
-rw-r--r-- | sql/sql_prepare.cc | 5 | ||||
-rw-r--r-- | sql/sql_select.cc | 14 | ||||
-rw-r--r-- | sql/sql_table.cc | 3 | ||||
-rw-r--r-- | sql/table.h | 3 |
14 files changed, 115 insertions, 24 deletions
diff --git a/sql/examples/ha_archive.cc b/sql/examples/ha_archive.cc index d4e3b961223..503f3f6b1fe 100644 --- a/sql/examples/ha_archive.cc +++ b/sql/examples/ha_archive.cc @@ -18,7 +18,7 @@ #pragma implementation // gcc: Class implementation #endif -#include <mysql_priv.h> +#include "../mysql_priv.h" #ifdef HAVE_ARCHIVE_DB #include "ha_archive.h" diff --git a/sql/examples/ha_archive.h b/sql/examples/ha_archive.h index 7ab463b6661..52300fda8a2 100644 --- a/sql/examples/ha_archive.h +++ b/sql/examples/ha_archive.h @@ -58,7 +58,7 @@ public: ha_archive(TABLE *table): handler(table) { /* Set our original buffer from pre-allocated memory */ - buffer.set(byte_buffer, IO_SIZE, system_charset_info); + buffer.set((char*)byte_buffer, IO_SIZE, system_charset_info); /* The size of the offset value we will use for position() */ ref_length = sizeof(z_off_t); diff --git a/sql/examples/ha_example.cc b/sql/examples/ha_example.cc index 31e4e97c5c7..b3edce5ba4a 100644 --- a/sql/examples/ha_example.cc +++ b/sql/examples/ha_example.cc @@ -67,7 +67,7 @@ #pragma implementation // gcc: Class implementation #endif -#include <mysql_priv.h> +#include "../mysql_priv.h" #ifdef HAVE_EXAMPLE_DB #include "ha_example.h" diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 3109c314f6c..d1de0bd100e 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -3258,7 +3258,10 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type) DBUG_PRINT("info", ("Table schema version: %d", tab->getObjectVersion())); // Check if thread has stale local cache - if (tab->getObjectStatus() == NdbDictionary::Object::Invalid) + // New transaction must not use old tables... (trans != 0) + // Running might... + if ((trans && tab->getObjectStatus() != NdbDictionary::Object::Retrieved) + || tab->getObjectStatus() == NdbDictionary::Object::Invalid) { invalidate_dictionary_cache(FALSE); if (!(tab= dict->getTable(m_tabname, &tab_info))) diff --git a/sql/item.cc b/sql/item.cc index b3d2932acf6..2ae56d17b07 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1230,7 +1230,7 @@ bool Item_param::set_from_user_var(THD *thd, const user_var_entry *entry) CHARSET_INFO *tocs= thd->variables.collation_connection; uint32 dummy_offset; - value.cs_info.character_set_client= fromcs; + value.cs_info.character_set_of_placeholder= fromcs; /* Setup source and destination character sets so that they are different only if conversion is necessary: this will @@ -1482,10 +1482,17 @@ const String *Item_param::query_val_str(String* str) const buf= str->c_ptr_quick(); ptr= buf; - *ptr++= '\''; - ptr+= escape_string_for_mysql(str_value.charset(), ptr, - str_value.ptr(), str_value.length()); - *ptr++= '\''; + if (value.cs_info.character_set_client->escape_with_backslash_is_dangerous) + { + ptr= str_to_hex(ptr, str_value.ptr(), str_value.length()); + } + else + { + *ptr++= '\''; + ptr+= escape_string_for_mysql(str_value.charset(), ptr, + str_value.ptr(), str_value.length()); + *ptr++='\''; + } str->length(ptr - buf); break; } @@ -1515,10 +1522,10 @@ bool Item_param::convert_str_value(THD *thd) here only if conversion is really necessary. */ if (value.cs_info.final_character_set_of_str_value != - value.cs_info.character_set_client) + value.cs_info.character_set_of_placeholder) { rc= thd->convert_string(&str_value, - value.cs_info.character_set_client, + value.cs_info.character_set_of_placeholder, value.cs_info.final_character_set_of_str_value); } else diff --git a/sql/item.h b/sql/item.h index c71769b5129..080b804c730 100644 --- a/sql/item.h +++ b/sql/item.h @@ -532,6 +532,7 @@ public: struct CONVERSION_INFO { CHARSET_INFO *character_set_client; + CHARSET_INFO *character_set_of_placeholder; /* This points at character set of connection if conversion to it is required (i. e. if placeholder typecode is not BLOB). diff --git a/sql/log_event.cc b/sql/log_event.cc index 4d260763491..66c732e8cb0 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -207,7 +207,7 @@ static inline int read_str(char * &buf, char *buf_end, char * &str, /* Transforms a string into "" or its expression in 0x... form. */ -static char *str_to_hex(char *to, char *from, uint len) +char *str_to_hex(char *to, const char *from, uint len) { char *p= to; if (len) diff --git a/sql/log_event.h b/sql/log_event.h index 7ae4e863fc2..5c81d0c92f0 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -1069,5 +1069,5 @@ public: bool is_valid() { return 1; } }; #endif - +char *str_to_hex(char *to, const char *from, uint len); #endif /* _log_event_h */ diff --git a/sql/mysqld.cc b/sql/mysqld.cc index b5a292fec28..2e38ec98c08 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -152,6 +152,7 @@ int deny_severity = LOG_WARNING; #define zVOLSTATE_MAINTENANCE 3 #ifdef __NETWARE__ +#include <nks/netware.h> #include <nks/vm.h> #include <library.h> #include <monitor.h> @@ -4327,7 +4328,7 @@ Disable with --skip-bdb (will save memory).", (gptr*) &default_collation_name, (gptr*) &default_collation_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, {"default-storage-engine", OPT_STORAGE_ENGINE, - "Set the default storage engine (table tyoe) for tables.", 0, 0, + "Set the default storage engine (table type) for tables.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"default-table-type", OPT_STORAGE_ENGINE, "(deprecated) Use --default-storage-engine.", 0, 0, diff --git a/sql/sql_db.cc b/sql/sql_db.cc index ad6845572e1..6dcc7be0904 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -25,14 +25,20 @@ #include <direct.h> #endif +#define MAX_DROP_TABLE_Q_LEN 1024 + const char *del_exts[]= {".frm", ".BAK", ".TMD",".opt", NullS}; static TYPELIB deletable_extentions= {array_elements(del_exts)-1,"del_exts", del_exts, NULL}; static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, - const char *db, const char *path, - uint level); + const char *db, const char *path, uint level, + TABLE_LIST** dropped_tables); + +static inline void write_to_binlog(THD* thd, char* query, uint q_len, + char* db, uint db_len); + /* Database options hash */ static HASH dboptions; static my_bool dboptions_init= 0; @@ -57,6 +63,19 @@ static byte* dboptions_get_key(my_dbopt_t *opt, uint *length, return (byte*) opt->name; } +/* + Helper function to write a query to binlog used by mysql_rm_db() + */ +static inline void write_to_binlog(THD* thd, char* query, uint q_len, + char* db, uint db_len) +{ + Query_log_event qinfo(thd, query, q_len, 0, 0); + qinfo.error_code= 0; + qinfo.db= db; + qinfo.db_len= db_len; + mysql_bin_log.write(&qinfo); +} + /* Function to free dboptions hash element @@ -585,6 +604,7 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) char path[FN_REFLEN+16], tmp_db[NAME_LEN+1]; MY_DIR *dirp; uint length; + TABLE_LIST* dropped_tables= 0; DBUG_ENTER("mysql_rm_db"); VOID(pthread_mutex_lock(&LOCK_mysql_create_db)); @@ -621,8 +641,10 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) remove_db_from_cache(db); pthread_mutex_unlock(&LOCK_open); + error= -1; - if ((deleted= mysql_rm_known_files(thd, dirp, db, path, 0)) >= 0) + if ((deleted= mysql_rm_known_files(thd, dirp, db, path, 0, + &dropped_tables)) >= 0) { ha_drop_database(path); query_cache_invalidate1(db); @@ -672,6 +694,45 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) send_ok(thd, (ulong) deleted); thd->server_status&= ~SERVER_STATUS_DB_DROPPED; } + else if (mysql_bin_log.is_open()) + { + char* query= thd->alloc(MAX_DROP_TABLE_Q_LEN); + + if (!query) + goto exit; /* not much else we can do */ + char* p= strmov(query,"drop table "); + char* p_end= query + MAX_DROP_TABLE_Q_LEN; + TABLE_LIST* tbl; + bool last_query_needs_write= 0; + uint db_len= strlen(db); + + for (tbl= dropped_tables;tbl;tbl= tbl->next) + { + if (!tbl->was_dropped) + continue; + + /* 3 for the quotes and the comma*/ + uint tbl_name_len= strlen(tbl->real_name) + 3; + if (p + tbl_name_len + 1 >= p_end) + { + *--p= 0; /* kill , */ + write_to_binlog(thd, query, p - query, db, db_len); + p= query + 11; /* reuse the initial "drop table" */ + } + + *p++ = '`'; + p= strmov(p,tbl->real_name); + *p++ = '`'; + *p++ = ','; + last_query_needs_write= 1; + } + + if (last_query_needs_write) + { + *--p= 0; + write_to_binlog(thd, query, p - query, db, db_len); + } + } exit: start_waiting_global_read_lock(thd); @@ -716,7 +777,7 @@ exit2: */ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db, - const char *org_path, uint level) + const char *org_path, uint level, TABLE_LIST** dropped_tables) { long deleted=0; ulong found_other_files=0; @@ -758,7 +819,7 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db, if ((new_dirp = my_dir(newpath,MYF(MY_DONT_SORT)))) { DBUG_PRINT("my",("New subdir found: %s", newpath)); - if ((mysql_rm_known_files(thd, new_dirp, NullS, newpath,1)) < 0) + if ((mysql_rm_known_files(thd, new_dirp, NullS, newpath,1,0)) < 0) goto err; if (!(copy_of_path= thd->memdup(newpath, length+1)) || !(dir= new (thd->mem_root) String(copy_of_path, length, @@ -818,6 +879,9 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db, } my_dirend(dirp); + if (dropped_tables) + *dropped_tables= tot_list; + /* If the directory is a symbolic link, remove the link first, then remove the directory the symbolic link pointed at diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 6507de37a71..8a50d0bd50e 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -528,7 +528,9 @@ static void setup_one_conversion_function(THD *thd, Item_param *param, case MYSQL_TYPE_LONG_BLOB: case MYSQL_TYPE_BLOB: param->set_param_func= set_param_str; - param->value.cs_info.character_set_client= &my_charset_bin; + param->value.cs_info.character_set_of_placeholder= &my_charset_bin; + param->value.cs_info.character_set_client= + thd->variables.character_set_client; param->value.cs_info.final_character_set_of_str_value= &my_charset_bin; param->item_type= Item::STRING_ITEM; param->item_result_type= STRING_RESULT; @@ -544,6 +546,7 @@ static void setup_one_conversion_function(THD *thd, Item_param *param, CHARSET_INFO *tocs= thd->variables.collation_connection; uint32 dummy_offset; + param->value.cs_info.character_set_of_placeholder= fromcs; param->value.cs_info.character_set_client= fromcs; /* diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 9984cb4138f..b676cbb1fea 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -4899,7 +4899,15 @@ static Field* create_tmp_field_from_item(THD *thd, Item *item, TABLE *table, item->name, table, item->unsigned_flag); break; case STRING_RESULT: - if (item->max_length > 255) + enum enum_field_types type; + /* + DATE/TIME fields have STRING_RESULT result type. To preserve + type they needed to be handled separately. + */ + if ((type= item->field_type()) == MYSQL_TYPE_DATETIME || + type == MYSQL_TYPE_TIME || type == MYSQL_TYPE_DATE) + new_field= item->tmp_table_field_from_field_type(table); + else if (item->max_length > 255) { if (convert_blob_length) new_field= new Field_varstring(convert_blob_length, maybe_null, @@ -8517,9 +8525,7 @@ create_distinct_group(THD *thd, Item **ref_pointer_array, li.rewind(); while ((item=li++)) { - if (item->const_item() || item->with_sum_func) - continue; - if (!item->marker) + if (!item->const_item() && !item->with_sum_func && !item->marker) { ORDER *ord=(ORDER*) thd->calloc(sizeof(ORDER)); if (!ord) diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 87b864c73fa..80ac9e007b9 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -220,6 +220,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, for (table=tables ; table ; table=table->next) { char *db=table->db; + table->was_dropped= 0; mysql_ha_flush(thd, table, MYSQL_HA_CLOSE_FINAL); if (!close_temporary_table(thd, db, table->real_name)) { @@ -280,6 +281,8 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, wrong_tables.append(','); wrong_tables.append(String(table->real_name,system_charset_info)); } + else + table->was_dropped= 1; } thd->tmp_table_used= tmp_table_deleted; error= 0; diff --git a/sql/table.h b/sql/table.h index 77153e5d8cd..fb742acf804 100644 --- a/sql/table.h +++ b/sql/table.h @@ -235,6 +235,9 @@ typedef struct st_table_list bool cacheable_table; /* stop PS caching */ /* used in multi-upd privelege check */ bool table_in_update_from_clause; + + /* used for proper partially successful DROP DATABASE binlogging */ + bool was_dropped; } TABLE_LIST; typedef struct st_changed_table_list |