diff options
author | dlenev@brandersnatch.localdomain <> | 2004-03-31 21:25:55 +0400 |
---|---|---|
committer | dlenev@brandersnatch.localdomain <> | 2004-03-31 21:25:55 +0400 |
commit | 4122188cc2d3ce836f88681fc5e0d41cacfda3f9 (patch) | |
tree | 526682a26c471951e15c895db2723ad065b5690c /sql/sql_base.cc | |
parent | 9e28b7698d487f188c8669d5b7918fca1d750753 (diff) | |
download | mariadb-git-4122188cc2d3ce836f88681fc5e0d41cacfda3f9.tar.gz |
Fix for Bug #3307 "FLUSH TABLES sometimes breaks prepared statement
table resolution".
Added members to Item_ident for storing original db, table and field
names since those that set later from Field have shorter life-time
than required by prep. stmt. So we need to restore original names in
Item_ident::cleanup(). Also now using special construnctor for creation
of Item_field from Field object that ensures that table and field name
have big enough life-time.
"Fix" for bug #2050 "10 to 1 performance drop with server 4.1.1"
Clean ups in implementation of caching of field number in table.
Added caching of table in which field is found in find_field_in_tables().
Diffstat (limited to 'sql/sql_base.cc')
-rw-r--r-- | sql/sql_base.cc | 47 |
1 files changed, 35 insertions, 12 deletions
diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 375ebb069a3..4d8a70887b9 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1791,12 +1791,13 @@ bool rm_temporary_table(enum db_type base, char *path) Field *find_field_in_table(THD *thd,TABLE *table,const char *name,uint length, bool check_grants, bool allow_rowid, - int *cached_field_index_ptr) + uint *cached_field_index_ptr) { - Field **field_ptr= 0, *field; - int cached_field_index= *cached_field_index_ptr; + Field **field_ptr, *field; + uint cached_field_index= *cached_field_index_ptr; - if (cached_field_index >= 0 && cached_field_index < table->fields && + /* We assume here that table->field < NO_CACHED_FIELD_INDEX = UINT_MAX */ + if (cached_field_index < table->fields && !my_strcasecmp(system_charset_info, table->field[cached_field_index]->field_name, name)) field_ptr= table->field + cached_field_index; @@ -1805,14 +1806,11 @@ Field *find_field_in_table(THD *thd,TABLE *table,const char *name,uint length, length); else { - if (!(field_ptr=table->field)) + if (!(field_ptr= table->field)) return (Field *)0; - while (*field_ptr) - { + for (; *field_ptr; ++field_ptr) if (!my_strcasecmp(system_charset_info, (*field_ptr)->field_name, name)) break; - ++field_ptr; - } } if (field_ptr && *field_ptr) @@ -1882,6 +1880,31 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, uint length=(uint) strlen(name); char name_buff[NAME_LEN+1]; + + if (item->cached_table) + { + /* + This shortcut is used by prepared statements. We assuming that + TABLE_LIST *tables is not changed during query execution (which + is true for all queries except RENAME but luckily RENAME doesn't + use fields...) so we can rely on reusing pointer to its member. + With this optimisation we also miss case when addition of one more + field makes some prepared query ambiguous and so erronous, but we + accept this trade off. + */ + found= find_field_in_table(thd,tables->table,name,length, + test(tables->table->grant.want_privilege), + 1, &(item->cached_field_index)); + + if (found) + { + (*where)= tables; + if (found == WRONG_GRANT) + return (Field*) 0; + return found; + } + } + if (db && lower_case_table_names) { /* @@ -1909,7 +1932,7 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, 1, &(item->cached_field_index)); if (find) { - (*where)= tables; + (*where)= item->cached_table= tables; if (find == WRONG_GRANT) return (Field*) 0; if (db || !thd->where) @@ -1968,7 +1991,7 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, { if (field == WRONG_GRANT) return (Field*) 0; - (*where)= tables; + (*where)= item->cached_table= tables; if (found) { if (!thd->where) // Returns first found @@ -2304,7 +2327,7 @@ insert_fields(THD *thd,TABLE_LIST *tables, const char *db_name, thd->used_tables|=table->map; while ((field = *ptr++)) { - Item_field *item= new Item_field(field); + Item_field *item= new Item_field(thd, field); if (!found++) (void) it->replace(item); // Replace '*' else |