summaryrefslogtreecommitdiff
path: root/sql/sql_class.cc
diff options
context:
space:
mode:
authorunknown <monty@mysql.com>2004-10-29 19:26:52 +0300
committerunknown <monty@mysql.com>2004-10-29 19:26:52 +0300
commitf095274fe8c3d3394d6c0ce0a68f4bea04311999 (patch)
tree23bcc9a71fe7237887a111b158e30f5a6bb665d3 /sql/sql_class.cc
parentf41bba8c6156a7adf4c67dfa75e16112767a5d3c (diff)
parent5be6c328f5a9f78f37176bbbd88a538fa3b65fe9 (diff)
downloadmariadb-git-f095274fe8c3d3394d6c0ce0a68f4bea04311999.tar.gz
merge with 4.1
BitKeeper/etc/ignore: auto-union BitKeeper/etc/logging_ok: auto-union BitKeeper/triggers/post-commit: Auto merged Docs/Support/texi2html: Auto merged Makefile.am: Auto merged client/Makefile.am: Auto merged client/mysql.cc: Auto merged client/mysqldump.c: Auto merged include/my_base.h: Auto merged include/my_global.h: Auto merged include/my_pthread.h: Auto merged include/my_sys.h: Auto merged include/my_time.h: Auto merged include/mysql.h: Auto merged include/mysql_com.h: Auto merged innobase/buf/buf0buf.c: Auto merged innobase/include/row0mysql.h: Auto merged innobase/row/row0sel.c: Auto merged libmysql/libmysql.c: Auto merged libmysqld/examples/Makefile.am: Auto merged myisam/mi_check.c: Auto merged mysql-test/include/ps_modify.inc: Auto merged mysql-test/install_test_db.sh: Auto merged mysql-test/r/alter_table.result: Auto merged mysql-test/r/auto_increment.result: Auto merged mysql-test/r/bdb.result: Auto merged mysql-test/r/ctype_latin1_de.result: Auto merged mysql-test/r/ctype_recoding.result: Auto merged mysql-test/r/fulltext.result: Auto merged mysql-test/r/func_gconcat.result: Auto merged mysql-test/r/func_group.result: Auto merged mysql-test/r/func_if.result: Auto merged mysql-test/t/derived.test: Auto merged mysql-test/t/insert.test: merge with 4.1 Fixed test case to not use 'if exists' when it shouldn't mysql-test/t/range.test: merge with 4.1 Added missing drop table sql/ha_ndbcluster.cc: merge with 4.1 Simple optimization: use max() instead of ? : sql/item_func.cc: merge with 4.1 (Added back old variable names for easier merges) sql/opt_range.cc: merge with 4.1 Removed argument 'parent_alloc' from QUICK_RANGE_SELECT as this was not used Added assert if using QUICK_GROUP_MIN_MAX_SELECT with parent_alloc as the init() function can't handle this Changed back get_quick_select_for_ref() to use it's own alloc root becasue this function may be called several times for one query sql/sql_handler.cc: merge with 4.1 change variable 'err' to 'error' as same function had a label named 'err' sql/sql_update.cc: Use multi-update code from 5.0 instead of 4.1 We will fix the locking code shortly in 5.0 to be faster than in 4.1
Diffstat (limited to 'sql/sql_class.cc')
-rw-r--r--sql/sql_class.cc163
1 files changed, 121 insertions, 42 deletions
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 392534492df..9bf7cff85c0 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -176,6 +176,7 @@ THD::THD()
query_error= tmp_table_used= 0;
next_insert_id=last_insert_id=0;
open_tables= temporary_tables= handler_tables= derived_tables= 0;
+ hash_clear(&handler_tables_hash);
tmp_table=0;
lock=locked_tables=0;
used_tables=0;
@@ -225,8 +226,7 @@ THD::THD()
init();
/* Initialize sub structures */
- clear_alloc_root(&transaction.mem_root);
- init_alloc_root(&warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE);
+ init_sql_alloc(&warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE);
user_connect=(USER_CONN *)0;
hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0,
(hash_get_key) get_var_key,
@@ -265,6 +265,7 @@ THD::THD()
transaction.trans_log.end_of_file= max_binlog_cache_size;
}
#endif
+ init_sql_alloc(&transaction.mem_root, ALLOC_ROOT_MIN_BLOCK_SIZE, 0);
{
ulong tmp=sql_rnd_with_mutex();
randominit(&rand, tmp + (ulong) &rand, tmp + (ulong) ::query_id);
@@ -310,12 +311,13 @@ void THD::init(void)
void THD::init_for_queries()
{
- init_sql_alloc(&mem_root,
- variables.query_alloc_block_size,
- variables.query_prealloc_size);
- init_sql_alloc(&transaction.mem_root,
- variables.trans_alloc_block_size,
- variables.trans_prealloc_size);
+ ha_enable_transaction(this,TRUE);
+
+ reset_root_defaults(&mem_root, variables.query_alloc_block_size,
+ variables.query_prealloc_size);
+ reset_root_defaults(&transaction.mem_root,
+ variables.trans_alloc_block_size,
+ variables.trans_prealloc_size);
}
@@ -335,6 +337,7 @@ void THD::change_user(void)
cleanup();
cleanup_done= 0;
init();
+ stmt_map.reset();
hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0,
(hash_get_key) get_var_key,
(hash_free_key) free_user_var, 0);
@@ -354,11 +357,9 @@ void THD::cleanup(void)
lock=locked_tables; locked_tables=0;
close_thread_tables(this);
}
- if (handler_tables)
- {
- open_tables=handler_tables; handler_tables=0;
- close_thread_tables(this);
- }
+ mysql_ha_flush(this, (TABLE_LIST*) 0,
+ MYSQL_HA_CLOSE_FINAL | MYSQL_HA_FLUSH_ALL);
+ hash_free(&handler_tables_hash);
close_temporary_tables(this);
my_free((char*) variables.time_format, MYF(MY_ALLOW_ZERO_PTR));
my_free((char*) variables.date_format, MYF(MY_ALLOW_ZERO_PTR));
@@ -709,27 +710,29 @@ CHANGED_TABLE_LIST* THD::changed_table_dup(const char *key, long key_length)
return new_table;
}
+
int THD::send_explain_fields(select_result *result)
{
List<Item> field_list;
Item *item;
+ CHARSET_INFO *cs= system_charset_info;
field_list.push_back(new Item_return_int("id",3, MYSQL_TYPE_LONGLONG));
- field_list.push_back(new Item_empty_string("select_type",19));
- field_list.push_back(new Item_empty_string("table",NAME_LEN));
- field_list.push_back(new Item_empty_string("type",10));
+ field_list.push_back(new Item_empty_string("select_type", 19, cs));
+ field_list.push_back(new Item_empty_string("table", NAME_LEN, cs));
+ field_list.push_back(new Item_empty_string("type", 10, cs));
field_list.push_back(item=new Item_empty_string("possible_keys",
- NAME_LEN*MAX_KEY));
+ NAME_LEN*MAX_KEY, cs));
item->maybe_null=1;
- field_list.push_back(item=new Item_empty_string("key",NAME_LEN));
+ field_list.push_back(item=new Item_empty_string("key", NAME_LEN, cs));
item->maybe_null=1;
field_list.push_back(item=new Item_empty_string("key_len",
NAME_LEN*MAX_KEY));
item->maybe_null=1;
field_list.push_back(item=new Item_empty_string("ref",
- NAME_LEN*MAX_REF_PARTS));
+ NAME_LEN*MAX_REF_PARTS, cs));
item->maybe_null=1;
- field_list.push_back(new Item_return_int("rows",10, MYSQL_TYPE_LONGLONG));
- field_list.push_back(new Item_empty_string("Extra",255));
+ field_list.push_back(new Item_return_int("rows", 10, MYSQL_TYPE_LONGLONG));
+ field_list.push_back(new Item_empty_string("Extra", 255, cs));
return (result->send_fields(field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF));
}
@@ -751,6 +754,54 @@ void THD::close_active_vio()
#endif
+struct Item_change_record: public ilink
+{
+ Item **place;
+ Item *old_value;
+ /* Placement new was hidden by `new' in ilink (TODO: check): */
+ static void *operator new(size_t size, void *mem) { return mem; }
+};
+
+
+/*
+ Register an item tree tree transformation, performed by the query
+ optimizer. We need a pointer to runtime_memroot because it may be !=
+ thd->mem_root (due to possible set_n_backup_item_arena called for thd).
+*/
+
+void THD::nocheck_register_item_tree_change(Item **place, Item *old_value,
+ MEM_ROOT *runtime_memroot)
+{
+ Item_change_record *change;
+ /*
+ Now we use one node per change, which adds some memory overhead,
+ but still is rather fast as we use alloc_root for allocations.
+ A list of item tree changes of an average query should be short.
+ */
+ void *change_mem= alloc_root(runtime_memroot, sizeof(*change));
+ if (change_mem == 0)
+ {
+ fatal_error();
+ return;
+ }
+ change= new (change_mem) Item_change_record;
+ change->place= place;
+ change->old_value= old_value;
+ change_list.append(change);
+}
+
+
+void THD::rollback_item_tree_changes()
+{
+ I_List_iterator<Item_change_record> it(change_list);
+ Item_change_record *change;
+ while ((change= it++))
+ *change->place= change->old_value;
+ /* We can forget about changes memory: it's allocated in runtime memroot */
+ change_list.empty();
+}
+
+
/*****************************************************************************
** Functions to provide a interface to select results
*****************************************************************************/
@@ -847,7 +898,8 @@ bool select_send::send_eof()
/* Unlock tables before sending packet to gain some speed */
if (thd->lock)
{
- mysql_unlock_tables(thd, thd->lock); thd->lock=0;
+ mysql_unlock_tables(thd, thd->lock);
+ thd->lock=0;
}
if (!thd->net.report_error)
{
@@ -948,9 +1000,14 @@ static File create_file(THD *thd, char *path, sql_exchange *exchange,
option|= MY_REPLACE_DIR; // Force use of db directory
#endif
- strxnmov(path, FN_REFLEN, mysql_real_data_home, thd->db ? thd->db : "",
- NullS);
- (void) fn_format(path, exchange->file_name, path, "", option);
+ if (!dirname_length(exchange->file_name))
+ {
+ strxnmov(path, FN_REFLEN, mysql_real_data_home, thd->db ? thd->db : "", NullS);
+ (void) fn_format(path, exchange->file_name, path, "", option);
+ }
+ else
+ (void) fn_format(path, exchange->file_name, mysql_real_data_home, "", option);
+
if (!access(path, F_OK))
{
my_error(ER_FILE_EXISTS_ERROR, MYF(0), exchange->file_name);
@@ -1388,6 +1445,17 @@ void select_dumpvar::cleanup()
}
+/*
+ Create arena for already constructed THD.
+
+ SYNOPSYS
+ Item_arena()
+ thd - thread for which arena is created
+
+ DESCRIPTION
+ Create arena for already existing THD using its variables as parameters
+ for memory root initialization.
+*/
Item_arena::Item_arena(THD* thd)
:free_list(0),
state(INITIALIZED)
@@ -1398,24 +1466,31 @@ Item_arena::Item_arena(THD* thd)
}
-/* This constructor is called when Item_arena is a subobject of THD */
+/*
+ Create arena and optionally initialize memory root.
-Item_arena::Item_arena()
- :free_list(0),
- state(CONVENTIONAL_EXECUTION)
-{
- clear_alloc_root(&mem_root);
-}
+ SYNOPSYS
+ Item_arena()
+ init_mem_root - whenever we need to initialize memory root
+ DESCRIPTION
+ Create arena and optionally initialize memory root with minimal
+ possible parameters.
+ NOTE
+ We use this constructor when arena is part of THD, but reinitialize
+ its memory root in THD::init_for_queries() before execution of real
+ statements.
+*/
Item_arena::Item_arena(bool init_mem_root)
:free_list(0),
- state(INITIALIZED)
+ state(CONVENTIONAL_EXECUTION)
{
if (init_mem_root)
- clear_alloc_root(&mem_root);
+ init_sql_alloc(&mem_root, ALLOC_ROOT_MIN_BLOCK_SIZE, 0);
}
+
Item_arena::Type Item_arena::type() const
{
DBUG_ASSERT(0); /* Should never be called */
@@ -1423,10 +1498,6 @@ Item_arena::Type Item_arena::type() const
}
-Item_arena::~Item_arena()
-{}
-
-
/*
Statement functions
*/
@@ -1451,7 +1522,7 @@ Statement::Statement(THD *thd)
*/
Statement::Statement()
- :Item_arena(),
+ :Item_arena((bool)TRUE),
id(0),
set_query_id(1),
allow_sum_func(0), /* initialized later */
@@ -1496,7 +1567,7 @@ void Statement::restore_backup_statement(Statement *stmt, Statement *backup)
}
-void Statement::end_statement()
+void THD::end_statement()
{
/* Cleanup SQL processing state to resuse this statement in next query. */
lex_end(lex);
@@ -1524,8 +1595,16 @@ void Item_arena::restore_backup_item_arena(Item_arena *set, Item_arena *backup)
{
set->set_item_arena(this);
set_item_arena(backup);
- // reset backup mem_root to avoid its freeing
+#ifdef NOT_NEEDED_NOW
+ /*
+ Reset backup mem_root to avoid its freeing.
+ Since Item_arena's mem_root is freed only when it is part of Statement
+ we need this only if we use some Statement's arena as backup storage.
+ But we do this only with THD::stmt_backup and this Statement is specially
+ handled in this respect. So this code is not really needed now.
+ */
clear_alloc_root(&backup->mem_root);
+#endif
}
void Item_arena::set_item_arena(Item_arena *set)
@@ -1573,7 +1652,7 @@ Statement_map::Statement_map() :
START_STMT_HASH_SIZE = 16,
START_NAME_HASH_SIZE = 16
};
- hash_init(&st_hash, default_charset_info, START_STMT_HASH_SIZE, 0, 0,
+ hash_init(&st_hash, &my_charset_bin, START_STMT_HASH_SIZE, 0, 0,
get_statement_id_as_hash_key,
delete_statement_as_hash_key, MYF(0));
hash_init(&names_hash, system_charset_info, START_NAME_HASH_SIZE, 0, 0,