mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
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
This commit is contained in:
184
sql/sql_base.cc
184
sql/sql_base.cc
@ -308,7 +308,7 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh,
|
||||
thd->proc_info="Flushing tables";
|
||||
|
||||
close_old_data_files(thd,thd->open_tables,1,1);
|
||||
mysql_ha_close_list(thd, tables);
|
||||
mysql_ha_flush(thd, tables, MYSQL_HA_REOPEN_ON_USAGE | MYSQL_HA_FLUSH_ALL);
|
||||
bool found=1;
|
||||
/* Wait until all threads has closed all the tables we had locked */
|
||||
DBUG_PRINT("info",
|
||||
@ -371,7 +371,7 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh,
|
||||
|
||||
void close_thread_tables(THD *thd, bool lock_in_use, bool skip_derived)
|
||||
{
|
||||
bool found_old_table=0;
|
||||
bool found_old_table;
|
||||
DBUG_ENTER("close_thread_tables");
|
||||
|
||||
if (thd->derived_tables && !skip_derived)
|
||||
@ -406,6 +406,7 @@ void close_thread_tables(THD *thd, bool lock_in_use, bool skip_derived)
|
||||
|
||||
DBUG_PRINT("info", ("thd->open_tables: %p", thd->open_tables));
|
||||
|
||||
found_old_table= 0;
|
||||
while (thd->open_tables)
|
||||
found_old_table|=close_thread_table(thd, &thd->open_tables);
|
||||
thd->some_tables_deleted=0;
|
||||
@ -876,8 +877,9 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
|
||||
{
|
||||
for (table= thd->temporary_tables; table ; table=table->next)
|
||||
{
|
||||
if (table->key_length == key_length + 8 &&
|
||||
!memcmp(table->table_cache_key, key, key_length + 8))
|
||||
if (table->key_length == key_length + TMP_TABLE_KEY_EXTRA &&
|
||||
!memcmp(table->table_cache_key, key,
|
||||
key_length + TMP_TABLE_KEY_EXTRA))
|
||||
{
|
||||
if (table->query_id == thd->query_id)
|
||||
{
|
||||
@ -888,7 +890,8 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
|
||||
table->query_id= thd->query_id;
|
||||
table->clear_query_id= 1;
|
||||
thd->tmp_table_used= 1;
|
||||
goto reset;
|
||||
DBUG_PRINT("info",("Using temporary table"));
|
||||
goto reset;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -903,6 +906,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
|
||||
table->query_id != thd->query_id)
|
||||
{
|
||||
table->query_id=thd->query_id;
|
||||
DBUG_PRINT("info",("Using locked table"));
|
||||
goto reset;
|
||||
}
|
||||
}
|
||||
@ -954,7 +958,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
|
||||
}
|
||||
|
||||
/* close handler tables which are marked for flush */
|
||||
mysql_ha_close_list(thd, (TABLE_LIST*) NULL, /*flushed*/ 1);
|
||||
mysql_ha_flush(thd, (TABLE_LIST*) NULL, MYSQL_HA_REOPEN_ON_USAGE);
|
||||
|
||||
for (table=(TABLE*) hash_search(&open_cache,(byte*) key,key_length) ;
|
||||
table && table->in_use ;
|
||||
@ -1047,6 +1051,31 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
|
||||
for (uint i=0 ; i < table->fields ; i++)
|
||||
table->field[i]->table_name=table->table_name;
|
||||
}
|
||||
#if MYSQL_VERSION_ID < 40100
|
||||
/*
|
||||
If per-connection "new" variable (represented by variables.new_mode)
|
||||
is set then we should pretend that the length of TIMESTAMP field is 19.
|
||||
The cheapest (from perfomance viewpoint) way to achieve that is to set
|
||||
field_length of all Field_timestamp objects in a table after opening
|
||||
it (to 19 if new_mode is true or to original field length otherwise).
|
||||
We save value of new_mode variable in TABLE::timestamp_mode to
|
||||
not perform this setup if new_mode value is the same between sequential
|
||||
table opens.
|
||||
*/
|
||||
my_bool new_mode= thd->variables.new_mode;
|
||||
if (table->timestamp_mode != new_mode)
|
||||
{
|
||||
for (uint i=0 ; i < table->fields ; i++)
|
||||
{
|
||||
Field *field= table->field[i];
|
||||
|
||||
if (field->type() == FIELD_TYPE_TIMESTAMP)
|
||||
field->field_length= new_mode ? 19 :
|
||||
((Field_timestamp *)(field))->orig_field_length;
|
||||
}
|
||||
table->timestamp_mode= new_mode;
|
||||
}
|
||||
#endif
|
||||
/* These variables are also set in reopen_table() */
|
||||
table->tablenr=thd->current_tablenr++;
|
||||
table->used_fields=0;
|
||||
@ -1056,7 +1085,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
|
||||
table->keys_in_use_for_query= table->keys_in_use;
|
||||
table->used_keys= table->keys_for_keyread;
|
||||
if (table->timestamp_field)
|
||||
table->timestamp_field->set_timestamp_offsets();
|
||||
table->timestamp_field_type= table->timestamp_field->get_auto_set_type();
|
||||
table_list->updatable= 1; // It is not derived table nor non-updatable VIEW
|
||||
DBUG_ASSERT(table->key_read == 0);
|
||||
DBUG_RETURN(table);
|
||||
@ -1339,7 +1368,7 @@ bool wait_for_tables(THD *thd)
|
||||
{
|
||||
thd->some_tables_deleted=0;
|
||||
close_old_data_files(thd,thd->open_tables,0,dropping_tables != 0);
|
||||
mysql_ha_close_list(thd, (TABLE_LIST*) NULL, /*flushed*/ 1);
|
||||
mysql_ha_flush(thd, (TABLE_LIST*) NULL, MYSQL_HA_REOPEN_ON_USAGE);
|
||||
if (!table_is_used(thd->open_tables,1))
|
||||
break;
|
||||
(void) pthread_cond_wait(&COND_refresh,&LOCK_open);
|
||||
@ -1469,7 +1498,7 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db,
|
||||
*/
|
||||
if (discover_retry_count++ != 0)
|
||||
goto err;
|
||||
if (create_table_from_handler(db, name, true) != 0)
|
||||
if (ha_create_table_from_engine(thd, db, name, TRUE) != 0)
|
||||
goto err;
|
||||
|
||||
thd->clear_error(); // Clear error message
|
||||
@ -1510,7 +1539,7 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db,
|
||||
/* Give right error message */
|
||||
thd->clear_error();
|
||||
my_error(ER_NOT_KEYFILE, MYF(0), name, my_errno);
|
||||
sql_print_error("Error: Couldn't repair table: %s.%s",db,name);
|
||||
sql_print_error("Couldn't repair table: %s.%s",db,name);
|
||||
if (entry->file)
|
||||
closefrm(entry);
|
||||
error=1;
|
||||
@ -1557,7 +1586,7 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db,
|
||||
DBA on top of warning the client (which will automatically be done
|
||||
because of MYF(MY_WME) in my_malloc() above).
|
||||
*/
|
||||
sql_print_error("Error: when opening HEAP table, could not allocate \
|
||||
sql_print_error("When opening HEAP table, could not allocate \
|
||||
memory to write 'DELETE FROM `%s`.`%s`' to the binary log",db,name);
|
||||
delete entry->triggers;
|
||||
if (entry->file)
|
||||
@ -1827,13 +1856,22 @@ int open_and_lock_tables(THD *thd, TABLE_LIST *tables)
|
||||
{
|
||||
DBUG_ENTER("open_and_lock_tables");
|
||||
uint counter;
|
||||
if (open_tables(thd, tables, &counter) || lock_tables(thd, tables, counter)
|
||||
|| mysql_handle_derived(thd->lex))
|
||||
if (open_tables(thd, tables, &counter) ||
|
||||
lock_tables(thd, tables, counter) ||
|
||||
mysql_handle_derived(thd->lex))
|
||||
DBUG_RETURN(thd->net.report_error ? -1 : 1); /* purecov: inspected */
|
||||
/*
|
||||
Let us propagate pointers to open tables from global table list
|
||||
to table lists in particular selects if needed.
|
||||
*/
|
||||
relink_tables_for_derived(thd);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Let us propagate pointers to open tables from global table list
|
||||
to table lists in particular selects if needed.
|
||||
*/
|
||||
|
||||
void relink_tables_for_derived(THD *thd)
|
||||
{
|
||||
if (thd->lex->all_selects_list->next_select_in_list() ||
|
||||
thd->lex->time_zone_tables_used)
|
||||
{
|
||||
@ -1850,7 +1888,6 @@ int open_and_lock_tables(THD *thd, TABLE_LIST *tables)
|
||||
}
|
||||
}
|
||||
}
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
||||
@ -1890,7 +1927,7 @@ int lock_tables(THD *thd, TABLE_LIST *tables, uint count)
|
||||
if (!table->placeholder())
|
||||
*(ptr++)= table->table;
|
||||
}
|
||||
if (!(thd->lock=mysql_lock_tables(thd,start,count)))
|
||||
if (!(thd->lock=mysql_lock_tables(thd,start, (uint) (ptr - start))))
|
||||
return -1; /* purecov: inspected */
|
||||
}
|
||||
else
|
||||
@ -1983,8 +2020,8 @@ bool rm_temporary_table(enum db_type base, char *path)
|
||||
if (file && file->delete_table(path))
|
||||
{
|
||||
error=1;
|
||||
sql_print_error("Warning: Could not remove tmp table: '%s', error: %d",
|
||||
path, my_errno);
|
||||
sql_print_warning("Could not remove tmp table: '%s', error: %d",
|
||||
path, my_errno);
|
||||
}
|
||||
delete file;
|
||||
DBUG_RETURN(error);
|
||||
@ -2367,14 +2404,17 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
|
||||
return not_found_item, report other errors,
|
||||
return 0
|
||||
IGNORE_ERRORS Do not report errors, return 0 if error
|
||||
|
||||
unaliased Set to true if item is field which was found
|
||||
by original field name and not by its alias
|
||||
in item list. Set to false otherwise.
|
||||
|
||||
RETURN VALUES
|
||||
0 Item is not found or item is not unique,
|
||||
error message is reported
|
||||
not_found_item Function was called with
|
||||
report_error == REPORT_EXCEPT_NOT_FOUND and
|
||||
item was not found. No error message was reported
|
||||
found field
|
||||
found field
|
||||
*/
|
||||
|
||||
// Special Item pointer for find_item_in_list returning
|
||||
@ -2383,7 +2423,7 @@ const Item **not_found_item= (const Item**) 0x1;
|
||||
|
||||
Item **
|
||||
find_item_in_list(Item *find, List<Item> &items, uint *counter,
|
||||
find_item_error_report_type report_error)
|
||||
find_item_error_report_type report_error, bool *unaliased)
|
||||
{
|
||||
List_iterator<Item> li(items);
|
||||
Item **found=0, **found_unaliased= 0, *item;
|
||||
@ -2392,6 +2432,9 @@ find_item_in_list(Item *find, List<Item> &items, uint *counter,
|
||||
const char *table_name=0;
|
||||
bool found_unaliased_non_uniq= 0;
|
||||
uint unaliased_counter;
|
||||
|
||||
*unaliased= FALSE;
|
||||
|
||||
if (find->type() == Item::FIELD_ITEM || find->type() == Item::REF_ITEM)
|
||||
{
|
||||
field_name= ((Item_ident*) find)->field_name;
|
||||
@ -2419,32 +2462,42 @@ find_item_in_list(Item *find, List<Item> &items, uint *counter,
|
||||
/*
|
||||
If table name is specified we should find field 'field_name' in
|
||||
table 'table_name'. According to SQL-standard we should ignore
|
||||
aliases in this case. Note that we should prefer fields from the
|
||||
select list over other fields from the tables participating in
|
||||
this select in case of ambiguity.
|
||||
aliases in this case.
|
||||
|
||||
Since we should NOT prefer fields from the select list over
|
||||
other fields from the tables participating in this select in
|
||||
case of ambiguity we have to do extra check outside this function.
|
||||
|
||||
We use strcmp for table names and database names as these may be
|
||||
case sensitive.
|
||||
In cases where they are not case sensitive, they are always in lower
|
||||
case.
|
||||
case sensitive. In cases where they are not case sensitive, they
|
||||
are always in lower case.
|
||||
|
||||
item_field->field_name and item_field->table_name can be 0x0 if
|
||||
item is not fix_field()'ed yet.
|
||||
*/
|
||||
if (!my_strcasecmp(system_charset_info, item_field->field_name,
|
||||
if (item_field->field_name && item_field->table_name &&
|
||||
!my_strcasecmp(system_charset_info, item_field->field_name,
|
||||
field_name) &&
|
||||
!strcmp(item_field->table_name, table_name) &&
|
||||
(!db_name || (item_field->db_name &&
|
||||
!strcmp(item_field->db_name, db_name))))
|
||||
{
|
||||
if (found)
|
||||
if (found_unaliased)
|
||||
{
|
||||
if ((*found)->eq(item, 0))
|
||||
continue; // Same field twice
|
||||
if ((*found_unaliased)->eq(item, 0))
|
||||
continue;
|
||||
/*
|
||||
Two matching fields in select list.
|
||||
We already can bail out because we are searching through
|
||||
unaliased names only and will have duplicate error anyway.
|
||||
*/
|
||||
if (report_error != IGNORE_ERRORS)
|
||||
my_printf_error(ER_NON_UNIQ_ERROR, ER(ER_NON_UNIQ_ERROR),
|
||||
MYF(0), find->full_name(), current_thd->where);
|
||||
return (Item**) 0;
|
||||
}
|
||||
found= li.ref();
|
||||
*counter= i;
|
||||
found_unaliased= li.ref();
|
||||
unaliased_counter= i;
|
||||
if (db_name)
|
||||
break; // Perfect match
|
||||
}
|
||||
@ -2516,6 +2569,7 @@ find_item_in_list(Item *find, List<Item> &items, uint *counter,
|
||||
{
|
||||
found= found_unaliased;
|
||||
*counter= unaliased_counter;
|
||||
*unaliased= TRUE;
|
||||
}
|
||||
}
|
||||
if (found)
|
||||
@ -2540,8 +2594,11 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
|
||||
uint wild_num)
|
||||
{
|
||||
Item *item;
|
||||
DBUG_ENTER("setup_wild");
|
||||
|
||||
if (!wild_num)
|
||||
return 0;
|
||||
DBUG_RETURN(0);
|
||||
|
||||
Item_arena *arena= thd->current_arena, backup;
|
||||
|
||||
/*
|
||||
@ -2556,7 +2613,8 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
|
||||
List_iterator<Item> it(fields);
|
||||
while (wild_num && (item= it++))
|
||||
{
|
||||
if (item->type() == Item::FIELD_ITEM && ((Item_field*) item)->field_name &&
|
||||
if (item->type() == Item::FIELD_ITEM &&
|
||||
((Item_field*) item)->field_name &&
|
||||
((Item_field*) item)->field_name[0] == '*' &&
|
||||
!((Item_field*) item)->field)
|
||||
{
|
||||
@ -2579,7 +2637,7 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
|
||||
{
|
||||
if (arena)
|
||||
thd->restore_backup_item_arena(arena, &backup);
|
||||
return (-1);
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
if (sum_func_list)
|
||||
{
|
||||
@ -2602,7 +2660,7 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
|
||||
|
||||
thd->restore_backup_item_arena(arena, &backup);
|
||||
}
|
||||
return 0;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -2635,7 +2693,7 @@ int setup_fields(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
|
||||
*(ref++)= item;
|
||||
if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM &&
|
||||
sum_func_list)
|
||||
item->split_sum_func(ref_pointer_array, *sum_func_list);
|
||||
item->split_sum_func(thd, ref_pointer_array, *sum_func_list);
|
||||
thd->used_tables|=item->used_tables();
|
||||
}
|
||||
DBUG_RETURN(test(thd->net.report_error));
|
||||
@ -2647,23 +2705,21 @@ int setup_fields(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
|
||||
|
||||
SYNOPSIS
|
||||
setup_tables()
|
||||
thd - thread handler
|
||||
tables - tables list
|
||||
conds - condition of current SELECT (can be changed by VIEW)
|
||||
thd Thread handler
|
||||
tables Table list
|
||||
conds Condition of current SELECT (can be changed by VIEW)
|
||||
|
||||
RETURN
|
||||
0 ok; In this case *map will includes the choosed index
|
||||
1 error
|
||||
NOTE
|
||||
Remap table numbers if INSERT ... SELECT
|
||||
Check also that the 'used keys' and 'ignored keys' exists and set up the
|
||||
table structure accordingly
|
||||
|
||||
NOTE
|
||||
Remap table numbers if INSERT ... SELECT
|
||||
Check also that the 'used keys' and 'ignored keys' exists and set up the
|
||||
table structure accordingly
|
||||
This has to be called for all tables that are used by items, as otherwise
|
||||
table->map is not set and all Item_field will be regarded as const items.
|
||||
|
||||
This has to be called for all tables that are used by items, as otherwise
|
||||
table->map is not set and all Item_field will be regarded as const items.
|
||||
|
||||
if tables do not contain VIEWs it is OK to pass 0 as conds
|
||||
RETURN
|
||||
0 ok; In this case *map will includes the choosed index
|
||||
1 error
|
||||
*/
|
||||
|
||||
bool setup_tables(THD *thd, TABLE_LIST *tables, Item **conds)
|
||||
@ -2973,8 +3029,7 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
|
||||
{
|
||||
table_map not_null_tables= 0;
|
||||
SELECT_LEX *select_lex= thd->lex->current_select;
|
||||
Item_arena *arena= thd->current_arena;
|
||||
Item_arena backup;
|
||||
Item_arena *arena= thd->current_arena, backup;
|
||||
bool save_wrapper= thd->lex->current_select->no_wrap_view_item;
|
||||
DBUG_ENTER("setup_conds");
|
||||
|
||||
@ -3090,7 +3145,7 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
|
||||
{
|
||||
if (t2_field != view_ref_found)
|
||||
{
|
||||
if (!(item_t2= new Item_field(t2_field)))
|
||||
if (!(item_t2= new Item_field(thd, t2_field)))
|
||||
goto err;
|
||||
/* Mark field used for table cache */
|
||||
t2_field->query_id= thd->query_id;
|
||||
@ -3143,6 +3198,8 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (arena)
|
||||
thd->restore_backup_item_arena(arena, &backup);
|
||||
}
|
||||
embedding= embedded->embedding;
|
||||
}
|
||||
@ -3301,8 +3358,15 @@ void flush_tables()
|
||||
|
||||
|
||||
/*
|
||||
** Mark all entries with the table as deleted to force an reopen of the table
|
||||
** Returns true if the table is in use by another thread
|
||||
Mark all entries with the table as deleted to force an reopen of the table
|
||||
|
||||
The table will be closed (not stored in cache) by the current thread when
|
||||
close_thread_tables() is called.
|
||||
|
||||
RETURN
|
||||
0 This thread now have exclusive access to this table and no other thread
|
||||
can access the table until close_thread_tables() is called.
|
||||
1 Table is in use by another thread
|
||||
*/
|
||||
|
||||
bool remove_table_from_cache(THD *thd, const char *db, const char *table_name,
|
||||
|
Reference in New Issue
Block a user