Commit 2ea43f3c authored by monty@mashka.mysql.fi's avatar monty@mashka.mysql.fi

Merge work:/my/mysql-4.0 into mashka.mysql.fi:/home/my/mysql-4.0

parents 27cb1e8c 3c08da95
...@@ -263,6 +263,7 @@ enum ha_base_keytype { ...@@ -263,6 +263,7 @@ enum ha_base_keytype {
#define MBR_EQUAL 8192 #define MBR_EQUAL 8192
#define MBR_DATA 16384 #define MBR_DATA 16384
#define SEARCH_NULL_ARE_EQUAL 32768 /* NULL in keys are equal */ #define SEARCH_NULL_ARE_EQUAL 32768 /* NULL in keys are equal */
#define SEARCH_NULL_ARE_NOT_EQUAL 65536 /* NULL in keys are not equal */
/* bits in opt_flag */ /* bits in opt_flag */
#define QUICK_USED 1 #define QUICK_USED 1
......
...@@ -601,7 +601,8 @@ static int chk_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo, ...@@ -601,7 +601,8 @@ static int chk_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo,
if (*keys != 1L) /* not first_key */ if (*keys != 1L) /* not first_key */
{ {
uint diff; uint diff;
_mi_key_cmp(keyinfo->seg,info->lastkey,key,USE_WHOLE_KEY,SEARCH_FIND, _mi_key_cmp(keyinfo->seg,info->lastkey,key,USE_WHOLE_KEY,
SEARCH_FIND | SEARCH_NULL_ARE_NOT_EQUAL,
&diff); &diff);
param->unique_count[diff-1]++; param->unique_count[diff-1]++;
} }
......
...@@ -55,12 +55,17 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg) ...@@ -55,12 +55,17 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg)
/* /*
Free buffers and reset the following flags: Free buffers and reset the following flags:
EXTRA_CACHE, EXTRA_WRITE_CACHE, EXTRA_KEYREAD, EXTRA_QUICK EXTRA_CACHE, EXTRA_WRITE_CACHE, EXTRA_KEYREAD, EXTRA_QUICK
If the row buffer cache is large (for dynamic tables), reduce it
to save memory.
*/ */
if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED)) if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
{ {
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED); info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
error=end_io_cache(&info->rec_cache); error=end_io_cache(&info->rec_cache);
} }
if (share->base.blobs)
mi_alloc_rec_buff(info, -1, &info->rec_buff);
#if defined(HAVE_MMAP) && defined(HAVE_MADVICE) #if defined(HAVE_MMAP) && defined(HAVE_MADVICE)
if (info->opt_flag & MEMMAP_USED) if (info->opt_flag & MEMMAP_USED)
madvise(share->file_map,share->state.state.data_file_length,MADV_RANDOM); madvise(share->file_map,share->state.state.data_file_length,MADV_RANDOM);
......
...@@ -559,28 +559,36 @@ err: ...@@ -559,28 +559,36 @@ err:
DBUG_RETURN (NULL); DBUG_RETURN (NULL);
} /* mi_open */ } /* mi_open */
byte *mi_alloc_rec_buff(MI_INFO *info, ulong length, byte **buf) byte *mi_alloc_rec_buff(MI_INFO *info, ulong length, byte **buf)
{ {
uint extra; uint extra;
uint32 old_length;
LINT_INIT(old_length);
if (! *buf || length > mi_get_rec_buff_len(info, *buf)) if (! *buf || length > (old_length=mi_get_rec_buff_len(info, *buf)))
{ {
byte *newptr = *buf; byte *newptr = *buf;
/* to simplify initial init of info->rec_buf in mi_open and mi_extra */ /* to simplify initial init of info->rec_buf in mi_open and mi_extra */
if (length == (ulong) -1) if (length == (ulong) -1)
{
length= max(info->s->base.pack_reclength+info->s->base.pack_bits, length= max(info->s->base.pack_reclength+info->s->base.pack_bits,
info->s->base.max_key_length); info->s->base.max_key_length);
/* Avoid unnecessary realloc */
if (newptr && length == old_length)
return newptr;
}
extra= ((info->s->options & HA_OPTION_PACK_RECORD) ? extra= ((info->s->options & HA_OPTION_PACK_RECORD) ?
ALIGN_SIZE(MI_MAX_DYN_BLOCK_HEADER)+MI_SPLIT_LENGTH+ ALIGN_SIZE(MI_MAX_DYN_BLOCK_HEADER)+MI_SPLIT_LENGTH+
MI_REC_BUFF_OFFSET : 0); MI_REC_BUFF_OFFSET : 0);
if (extra && newptr) if (extra && newptr)
newptr-=MI_REC_BUFF_OFFSET; newptr-= MI_REC_BUFF_OFFSET;
if (!(newptr=(byte*) my_realloc((gptr)newptr, length+extra+8, if (!(newptr=(byte*) my_realloc((gptr)newptr, length+extra+8,
MYF(MY_ALLOW_ZERO_PTR)))) MYF(MY_ALLOW_ZERO_PTR))))
return newptr; return newptr;
*((uint *)newptr)=length; *((uint32 *) newptr)= (uint32) length;
*buf= newptr+(extra ? MI_REC_BUFF_OFFSET : 0); *buf= newptr+(extra ? MI_REC_BUFF_OFFSET : 0);
} }
return *buf; return *buf;
......
...@@ -260,9 +260,11 @@ int _mi_prefix_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page, ...@@ -260,9 +260,11 @@ int _mi_prefix_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page,
uchar *key, uint key_len, uint nextflag, uchar **ret_pos, uchar *key, uint key_len, uint nextflag, uchar **ret_pos,
uchar *buff, my_bool *last_key) uchar *buff, my_bool *last_key)
{ {
/* my_flag is raw comparison result to be changed according to /*
my_flag is raw comparison result to be changed according to
SEARCH_NO_FIND,SEARCH_LAST and HA_REVERSE_SORT flags. SEARCH_NO_FIND,SEARCH_LAST and HA_REVERSE_SORT flags.
flag is the value returned by _mi_key_cmp and as treated as final */ flag is the value returned by _mi_key_cmp and as treated as final
*/
int flag=0, my_flag=-1; int flag=0, my_flag=-1;
uint nod_flag, length, len, matched, cmplen, kseg_len; uint nod_flag, length, len, matched, cmplen, kseg_len;
uint prefix_len,suffix_len; uint prefix_len,suffix_len;
...@@ -695,13 +697,29 @@ static int compare_bin(uchar *a, uint a_length, uchar *b, uint b_length, ...@@ -695,13 +697,29 @@ static int compare_bin(uchar *a, uint a_length, uchar *b, uint b_length,
} }
/* /*
** Compare two keys Compare two keys
** Returns <0, 0, >0 acording to which is bigger
** Key_length specifies length of key to use. Number-keys can't SYNOPSIS
** be splited _mi_key_cmp()
** If flag <> SEARCH_FIND compare also position keyseg Key segments of key to compare
*/ a First key to compare, in format from _mi_pack_key()
This is normally key specified by user
b Second key to compare. This is always from a row
key_length Length of key to compare. This can be shorter than
a to just compare sub keys
next_flag How keys should be compared
If bit SEARCH_FIND is not set the keys includes the row
position and this should also be compared
NOTES
Number-keys can't be splited
RETURN VALUES
<0 If a < b
0 If a == b
>0 If a > b
*/
#define FCMP(A,B) ((int) (A) - (int) (B)) #define FCMP(A,B) ((int) (A) - (int) (B))
...@@ -738,6 +756,15 @@ int _mi_key_cmp(register MI_KEYSEG *keyseg, register uchar *a, ...@@ -738,6 +756,15 @@ int _mi_key_cmp(register MI_KEYSEG *keyseg, register uchar *a,
{ {
if (nextflag == (SEARCH_FIND | SEARCH_UPDATE)) if (nextflag == (SEARCH_FIND | SEARCH_UPDATE))
nextflag=SEARCH_SAME; /* Allow duplicate keys */ nextflag=SEARCH_SAME; /* Allow duplicate keys */
else if (nextflag & SEARCH_NULL_ARE_NOT_EQUAL)
{
/*
This is only used from mi_check() to calculate cardinality.
It can't be used when searching for a key as this would cause
compare of (a,b) and (b,a) to return the same value.
*/
return -1;
}
next_key_length=key_length; next_key_length=key_length;
continue; /* To next key part */ continue; /* To next key part */
} }
......
...@@ -358,7 +358,7 @@ struct st_myisam_info { ...@@ -358,7 +358,7 @@ struct st_myisam_info {
#define MI_DYN_ALIGN_SIZE 4 /* Align blocks on this */ #define MI_DYN_ALIGN_SIZE 4 /* Align blocks on this */
#define MI_MAX_DYN_HEADER_BYTE 13 /* max header byte for dynamic rows */ #define MI_MAX_DYN_HEADER_BYTE 13 /* max header byte for dynamic rows */
#define MI_MAX_BLOCK_LENGTH ((((ulong) 1 << 24)-1) & (~ (ulong) (MI_DYN_ALIGN_SIZE-1))) #define MI_MAX_BLOCK_LENGTH ((((ulong) 1 << 24)-1) & (~ (ulong) (MI_DYN_ALIGN_SIZE-1)))
#define MI_REC_BUFF_OFFSET ALIGN_SIZE(MI_DYN_DELETE_BLOCK_HEADER+sizeof(uint)) #define MI_REC_BUFF_OFFSET ALIGN_SIZE(MI_DYN_DELETE_BLOCK_HEADER+sizeof(uint32))
#define MEMMAP_EXTRA_MARGIN 7 /* Write this as a suffix for file */ #define MEMMAP_EXTRA_MARGIN 7 /* Write this as a suffix for file */
...@@ -529,7 +529,7 @@ extern byte *mi_alloc_rec_buff(MI_INFO *,ulong, byte**); ...@@ -529,7 +529,7 @@ extern byte *mi_alloc_rec_buff(MI_INFO *,ulong, byte**);
((((info)->s->options & HA_OPTION_PACK_RECORD) && (buf)) ? \ ((((info)->s->options & HA_OPTION_PACK_RECORD) && (buf)) ? \
(buf) - MI_REC_BUFF_OFFSET : (buf)) (buf) - MI_REC_BUFF_OFFSET : (buf))
#define mi_get_rec_buff_len(info,buf) \ #define mi_get_rec_buff_len(info,buf) \
(*((uint *)(mi_get_rec_buff_ptr(info,buf)))) (*((uint32 *)(mi_get_rec_buff_ptr(info,buf))))
extern ulong _mi_rec_unpack(MI_INFO *info,byte *to,byte *from, extern ulong _mi_rec_unpack(MI_INFO *info,byte *to,byte *from,
ulong reclength); ulong reclength);
......
drop table if exists t1; drop table if exists t1,t2;
CREATE TABLE t1 ( CREATE TABLE t1 (
STRING_DATA char(255) default NULL, STRING_DATA char(255) default NULL,
KEY STRING_DATA (STRING_DATA) KEY STRING_DATA (STRING_DATA)
...@@ -318,3 +318,45 @@ CREATE TABLE t1 (a varchar(255), b varchar(255), c varchar(255)); ...@@ -318,3 +318,45 @@ CREATE TABLE t1 (a varchar(255), b varchar(255), c varchar(255));
ALTER TABLE t1 ADD INDEX t1 (a, b, c); ALTER TABLE t1 ADD INDEX t1 (a, b, c);
Specified key was too long. Max key length is 500 Specified key was too long. Max key length is 500
DROP TABLE t1; DROP TABLE t1;
CREATE TABLE t1 (a int not null, b int, c int, key(b), key(c), key(a,b), key(c,a));
INSERT into t1 values (0, null, 0), (0, null, 1), (0, null, 2), (0, null,3), (1,1,4);
create table t2 (a int not null, b int, c int, key(b), key(c), key(a));
INSERT into t2 values (1,1,1), (2,2,2);
optimize table t1;
Table Op Msg_type Msg_text
test.t1 optimize status OK
show index from t1;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
t1 1 b 1 b A 5 NULL NULL YES BTREE
t1 1 c 1 c A 5 NULL NULL YES BTREE
t1 1 a 1 a A 1 NULL NULL BTREE
t1 1 a 2 b A 5 NULL NULL YES BTREE
t1 1 c_2 1 c A 5 NULL NULL YES BTREE
t1 1 c_2 2 a A 5 NULL NULL BTREE
explain select * from t1,t2 where t1.a=t2.a;
table type possible_keys key key_len ref rows Extra
t1 ALL a NULL NULL NULL 5
t2 ALL a NULL NULL NULL 2 Using where
explain select * from t1,t2 force index(a) where t1.a=t2.a;
table type possible_keys key key_len ref rows Extra
t2 ALL a NULL NULL NULL 2
t1 ALL a NULL NULL NULL 5 Using where
explain select * from t1 force index(a),t2 force index(a) where t1.a=t2.a;
table type possible_keys key key_len ref rows Extra
t2 ALL a NULL NULL NULL 2
t1 ref a a 4 t2.a 3
explain select * from t1,t2 where t1.b=t2.b;
table type possible_keys key key_len ref rows Extra
t2 ALL b NULL NULL NULL 2
t1 ref b b 5 t2.b 1 Using where
explain select * from t1,t2 force index(c) where t1.a=t2.a;
table type possible_keys key key_len ref rows Extra
t1 ALL a NULL NULL NULL 5
t2 ALL NULL NULL NULL NULL 2 Using where
explain select * from t1 where a=0 or a=2;
table type possible_keys key key_len ref rows Extra
t1 ALL a NULL NULL NULL 5 Using where
explain select * from t1 force index (a) where a=0 or a=2;
table type possible_keys key key_len ref rows Extra
t1 range a a 4 NULL 4 Using where
drop table t1,t2;
...@@ -2,7 +2,13 @@ ...@@ -2,7 +2,13 @@
# Test bugs in the MyISAM code # Test bugs in the MyISAM code
# #
drop table if exists t1; # Initialise
drop table if exists t1,t2;
#
# Test problem with CHECK TABLE;
#
CREATE TABLE t1 ( CREATE TABLE t1 (
STRING_DATA char(255) default NULL, STRING_DATA char(255) default NULL,
KEY STRING_DATA (STRING_DATA) KEY STRING_DATA (STRING_DATA)
...@@ -326,3 +332,21 @@ CREATE TABLE t1 (a varchar(255), b varchar(255), c varchar(255)); ...@@ -326,3 +332,21 @@ CREATE TABLE t1 (a varchar(255), b varchar(255), c varchar(255));
ALTER TABLE t1 ADD INDEX t1 (a, b, c); ALTER TABLE t1 ADD INDEX t1 (a, b, c);
DROP TABLE t1; DROP TABLE t1;
#
# Test of cardinality of keys with NULL
#
CREATE TABLE t1 (a int not null, b int, c int, key(b), key(c), key(a,b), key(c,a));
INSERT into t1 values (0, null, 0), (0, null, 1), (0, null, 2), (0, null,3), (1,1,4);
create table t2 (a int not null, b int, c int, key(b), key(c), key(a));
INSERT into t2 values (1,1,1), (2,2,2);
optimize table t1;
show index from t1;
explain select * from t1,t2 where t1.a=t2.a;
explain select * from t1,t2 force index(a) where t1.a=t2.a;
explain select * from t1 force index(a),t2 force index(a) where t1.a=t2.a;
explain select * from t1,t2 where t1.b=t2.b;
explain select * from t1,t2 force index(c) where t1.a=t2.a;
explain select * from t1 where a=0 or a=2;
explain select * from t1 force index (a) where a=0 or a=2;
drop table t1,t2;
...@@ -151,6 +151,7 @@ static SYMBOL symbols[] = { ...@@ -151,6 +151,7 @@ static SYMBOL symbols[] = {
{ "FLOAT8", SYM(DOUBLE_SYM),0,0}, { "FLOAT8", SYM(DOUBLE_SYM),0,0},
{ "FLUSH", SYM(FLUSH_SYM),0,0}, { "FLUSH", SYM(FLUSH_SYM),0,0},
{ "FOREIGN", SYM(FOREIGN),0,0}, { "FOREIGN", SYM(FOREIGN),0,0},
{ "FORCE", SYM(FORCE_SYM),0,0},
{ "RAID_TYPE", SYM(RAID_TYPE),0,0}, { "RAID_TYPE", SYM(RAID_TYPE),0,0},
{ "RAID_CHUNKS", SYM(RAID_CHUNKS),0,0}, { "RAID_CHUNKS", SYM(RAID_CHUNKS),0,0},
{ "RAID_CHUNKSIZE", SYM(RAID_CHUNKSIZE),0,0}, { "RAID_CHUNKSIZE", SYM(RAID_CHUNKSIZE),0,0},
......
...@@ -226,6 +226,10 @@ void debug_sync_point(const char* lock_name, uint lock_timeout); ...@@ -226,6 +226,10 @@ void debug_sync_point(const char* lock_name, uint lock_timeout);
#define SHOW_LOG_STATUS_FREE "FREE" #define SHOW_LOG_STATUS_FREE "FREE"
#define SHOW_LOG_STATUS_INUSE "IN USE" #define SHOW_LOG_STATUS_INUSE "IN USE"
/* Options to add_table_to_list() */
#define TL_OPTION_UPDATING 1
#define TL_OPTION_FORCE_INDEX 2
/* Some portable defines */ /* Some portable defines */
#define portable_sizeof_char_ptr 8 #define portable_sizeof_char_ptr 8
...@@ -509,7 +513,7 @@ bool add_field_to_list(char *field_name, enum enum_field_types type, ...@@ -509,7 +513,7 @@ bool add_field_to_list(char *field_name, enum enum_field_types type,
void store_position_for_column(const char *name); void store_position_for_column(const char *name);
bool add_to_list(SQL_LIST &list,Item *group,bool asc=0); bool add_to_list(SQL_LIST &list,Item *group,bool asc=0);
TABLE_LIST *add_table_to_list(Table_ident *table,LEX_STRING *alias, TABLE_LIST *add_table_to_list(Table_ident *table,LEX_STRING *alias,
bool updating, ulong table_option,
thr_lock_type flags=TL_UNLOCK, thr_lock_type flags=TL_UNLOCK,
List<String> *use_index=0, List<String> *use_index=0,
List<String> *ignore_index=0); List<String> *ignore_index=0);
......
...@@ -605,12 +605,14 @@ int SQL_SELECT::test_quick_select(key_map keys_to_use, table_map prev_tables, ...@@ -605,12 +605,14 @@ int SQL_SELECT::test_quick_select(key_map keys_to_use, table_map prev_tables,
records++; /* purecov: inspected */ records++; /* purecov: inspected */
scan_time=(double) records / TIME_FOR_COMPARE+1; scan_time=(double) records / TIME_FOR_COMPARE+1;
read_time=(double) head->file->scan_time()+ scan_time + 1.0; read_time=(double) head->file->scan_time()+ scan_time + 1.0;
if (head->force_index)
scan_time= read_time= DBL_MAX;
if (limit < records) if (limit < records)
read_time=(double) records+scan_time+1; // Force to use index read_time=(double) records+scan_time+1; // Force to use index
else if (read_time <= 2.0 && !force_quick_range) else if (read_time <= 2.0 && !force_quick_range)
DBUG_RETURN(0); /* No need for quick select */ DBUG_RETURN(0); /* No need for quick select */
DBUG_PRINT("info",("Time to scan table: %ld",(long) read_time)); DBUG_PRINT("info",("Time to scan table: %g", read_time));
keys_to_use&=head->keys_in_use_for_query; keys_to_use&=head->keys_in_use_for_query;
if (keys_to_use) if (keys_to_use)
......
...@@ -752,7 +752,7 @@ TABLE *reopen_name_locked_table(THD* thd, TABLE_LIST* table_list) ...@@ -752,7 +752,7 @@ TABLE *reopen_name_locked_table(THD* thd, TABLE_LIST* table_list)
table->tablenr=thd->current_tablenr++; table->tablenr=thd->current_tablenr++;
table->used_fields=0; table->used_fields=0;
table->const_table=0; table->const_table=0;
table->outer_join=table->null_row=table->maybe_null=0; table->outer_join= table->null_row= table->maybe_null= table->force_index= 0;
table->status=STATUS_NO_RECORD; table->status=STATUS_NO_RECORD;
table->keys_in_use_for_query= table->keys_in_use; table->keys_in_use_for_query= table->keys_in_use;
table->used_keys= table->keys_for_keyread; table->used_keys= table->keys_for_keyread;
...@@ -910,7 +910,7 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name, ...@@ -910,7 +910,7 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name,
table->tablenr=thd->current_tablenr++; table->tablenr=thd->current_tablenr++;
table->used_fields=0; table->used_fields=0;
table->const_table=0; table->const_table=0;
table->outer_join=table->null_row=table->maybe_null=0; table->outer_join= table->null_row= table->maybe_null= table->force_index= 0;
table->status=STATUS_NO_RECORD; table->status=STATUS_NO_RECORD;
table->keys_in_use_for_query= table->keys_in_use; table->keys_in_use_for_query= table->keys_in_use;
table->used_keys= table->keys_for_keyread; table->used_keys= table->keys_for_keyread;
...@@ -981,6 +981,7 @@ bool reopen_table(TABLE *table,bool locked) ...@@ -981,6 +981,7 @@ bool reopen_table(TABLE *table,bool locked)
tmp.status= table->status; tmp.status= table->status;
tmp.keys_in_use_for_query= tmp.keys_in_use; tmp.keys_in_use_for_query= tmp.keys_in_use;
tmp.used_keys= tmp.keys_for_keyread; tmp.used_keys= tmp.keys_for_keyread;
tmp.force_index= tmp.force_index;
/* Get state */ /* Get state */
tmp.key_length= table->key_length; tmp.key_length= table->key_length;
...@@ -1888,6 +1889,7 @@ bool setup_tables(TABLE_LIST *tables) ...@@ -1888,6 +1889,7 @@ bool setup_tables(TABLE_LIST *tables)
table->maybe_null=test(table->outer_join=table_list->outer_join); table->maybe_null=test(table->outer_join=table_list->outer_join);
table->tablenr=tablenr; table->tablenr=tablenr;
table->map= (table_map) 1 << tablenr; table->map= (table_map) 1 << tablenr;
table->force_index= table_list->force_index;
if (table_list->use_index) if (table_list->use_index)
{ {
key_map map= get_key_map_from_key_list(table, key_map map= get_key_map_from_key_list(table,
......
...@@ -110,7 +110,7 @@ typedef struct st_select_lex ...@@ -110,7 +110,7 @@ typedef struct st_select_lex
char *db,*db1,*table1,*db2,*table2; /* For outer join using .. */ char *db,*db1,*table1,*db2,*table2; /* For outer join using .. */
Item *where,*having; Item *where,*having;
ha_rows select_limit,offset_limit; ha_rows select_limit,offset_limit;
ulong options; ulong options, table_join_options;
List<List_item> expr_list; List<List_item> expr_list;
List<List_item> when_list; List<List_item> when_list;
SQL_LIST order_list,table_list,group_list; SQL_LIST order_list,table_list,group_list;
......
...@@ -498,6 +498,7 @@ check_connections(THD *thd) ...@@ -498,6 +498,7 @@ check_connections(THD *thd)
vio_in_addr(net->vio,&thd->remote.sin_addr); vio_in_addr(net->vio,&thd->remote.sin_addr);
thd->host=ip_to_hostname(&thd->remote.sin_addr,&connect_errors); thd->host=ip_to_hostname(&thd->remote.sin_addr,&connect_errors);
/* Cut very long hostnames to avoid possible overflows */ /* Cut very long hostnames to avoid possible overflows */
if (thd->host)
thd->host[min(strlen(thd->host), HOSTNAME_LENGTH)]= 0; thd->host[min(strlen(thd->host), HOSTNAME_LENGTH)]= 0;
if (connect_errors > max_connect_errors) if (connect_errors > max_connect_errors)
return(ER_HOST_IS_BLOCKED); return(ER_HOST_IS_BLOCKED);
...@@ -3158,12 +3159,30 @@ bool add_to_list(SQL_LIST &list,Item *item,bool asc) ...@@ -3158,12 +3159,30 @@ bool add_to_list(SQL_LIST &list,Item *item,bool asc)
} }
/*
Add a table to list of used tables
SYNOPSIS
add_table_to_list()
table Table to add
alias alias for table (or null if no alias)
table_options A set of the following bits:
TL_OPTION_UPDATING Table will be updated
TL_OPTION_FORCE_INDEX Force usage of index
lock_type How table should be locked
use_index List of indexed used in USE INDEX
ignore_index List of indexed used in IGNORE INDEX
RETURN
0 Error
# Pointer to TABLE_LIST element added to the total table list
*/
TABLE_LIST *add_table_to_list(Table_ident *table, LEX_STRING *alias, TABLE_LIST *add_table_to_list(Table_ident *table, LEX_STRING *alias,
bool updating, ulong table_options,
thr_lock_type flags, thr_lock_type lock_type,
List<String> *use_index, List<String> *use_index,
List<String> *ignore_index List<String> *ignore_index)
)
{ {
register TABLE_LIST *ptr; register TABLE_LIST *ptr;
THD *thd=current_thd; THD *thd=current_thd;
...@@ -3211,8 +3230,9 @@ TABLE_LIST *add_table_to_list(Table_ident *table, LEX_STRING *alias, ...@@ -3211,8 +3230,9 @@ TABLE_LIST *add_table_to_list(Table_ident *table, LEX_STRING *alias,
} }
ptr->real_name=table->table.str; ptr->real_name=table->table.str;
ptr->real_name_length=table->table.length; ptr->real_name_length=table->table.length;
ptr->lock_type=flags; ptr->lock_type= lock_type;
ptr->updating=updating; ptr->updating= test(table_options & TL_OPTION_UPDATING);
ptr->force_index= test(table_options & TL_OPTION_FORCE_INDEX);
if (use_index) if (use_index)
ptr->use_index=(List<String> *) thd->memdup((gptr) use_index, ptr->use_index=(List<String> *) thd->memdup((gptr) use_index,
sizeof(*use_index)); sizeof(*use_index));
...@@ -3221,7 +3241,7 @@ TABLE_LIST *add_table_to_list(Table_ident *table, LEX_STRING *alias, ...@@ -3221,7 +3241,7 @@ TABLE_LIST *add_table_to_list(Table_ident *table, LEX_STRING *alias,
sizeof(*ignore_index)); sizeof(*ignore_index));
/* check that used name is unique */ /* check that used name is unique */
if (flags != TL_IGNORE) if (lock_type != TL_IGNORE)
{ {
for (TABLE_LIST *tables=(TABLE_LIST*) thd->lex.select->table_list.first ; for (TABLE_LIST *tables=(TABLE_LIST*) thd->lex.select->table_list.first ;
tables ; tables ;
......
...@@ -2057,7 +2057,8 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count, ...@@ -2057,7 +2057,8 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
!(s->quick && best_key && s->quick->index == best_key->key && !(s->quick && best_key && s->quick->index == best_key->key &&
best_max_key_part >= s->table->quick_key_parts[best_key->key]) && best_max_key_part >= s->table->quick_key_parts[best_key->key]) &&
!((s->table->file->table_flags() & HA_TABLE_SCAN_ON_INDEX) && !((s->table->file->table_flags() & HA_TABLE_SCAN_ON_INDEX) &&
s->table->used_keys && best_key)) s->table->used_keys && best_key) &&
!(s->table->force_index && best_key))
{ // Check full join { // Check full join
if (s->on_expr) if (s->on_expr)
{ {
......
/* Copyright (C) 2000-2001 MySQL AB /* Copyright (C) 2000-2003 MySQL AB
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
...@@ -198,6 +198,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); ...@@ -198,6 +198,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token FIRST_SYM %token FIRST_SYM
%token FIXED_SYM %token FIXED_SYM
%token FLOAT_NUM %token FLOAT_NUM
%token FORCE_SYM
%token FOREIGN %token FOREIGN
%token FROM %token FROM
%token FULL %token FULL
...@@ -735,7 +736,8 @@ create: ...@@ -735,7 +736,8 @@ create:
lex->sql_command= SQLCOM_CREATE_TABLE; lex->sql_command= SQLCOM_CREATE_TABLE;
if (!add_table_to_list($5, if (!add_table_to_list($5,
($2 & HA_LEX_CREATE_TMP_TABLE ? ($2 & HA_LEX_CREATE_TMP_TABLE ?
&tmp_table_alias : (LEX_STRING*) 0),1)) &tmp_table_alias : (LEX_STRING*) 0),
TL_OPTION_UPDATING))
YYABORT; YYABORT;
lex->create_list.empty(); lex->create_list.empty();
lex->key_list.empty(); lex->key_list.empty();
...@@ -751,7 +753,7 @@ create: ...@@ -751,7 +753,7 @@ create:
{ {
LEX *lex=Lex; LEX *lex=Lex;
lex->sql_command= SQLCOM_CREATE_INDEX; lex->sql_command= SQLCOM_CREATE_INDEX;
if (!add_table_to_list($6,NULL,1)) if (!add_table_to_list($6, NULL, TL_OPTION_UPDATING))
YYABORT; YYABORT;
lex->create_list.empty(); lex->create_list.empty();
lex->key_list.empty(); lex->key_list.empty();
...@@ -1171,7 +1173,7 @@ alter: ...@@ -1171,7 +1173,7 @@ alter:
LEX *lex=Lex; LEX *lex=Lex;
lex->sql_command = SQLCOM_ALTER_TABLE; lex->sql_command = SQLCOM_ALTER_TABLE;
lex->name=0; lex->name=0;
if (!add_table_to_list($4, NULL,1)) if (!add_table_to_list($4, NULL, TL_OPTION_UPDATING))
YYABORT; YYABORT;
lex->drop_primary=0; lex->drop_primary=0;
lex->create_list.empty(); lex->create_list.empty();
...@@ -1442,8 +1444,9 @@ table_to_table_list: ...@@ -1442,8 +1444,9 @@ table_to_table_list:
table_to_table: table_to_table:
table_ident TO_SYM table_ident table_ident TO_SYM table_ident
{ if (!add_table_to_list($1,NULL,1,TL_IGNORE) || {
!add_table_to_list($3,NULL,1,TL_IGNORE)) if (!add_table_to_list($1, NULL, TL_OPTION_UPDATING, TL_IGNORE) ||
!add_table_to_list($3, NULL, TL_OPTION_UPDATING, TL_IGNORE))
YYABORT; YYABORT;
}; };
...@@ -2127,11 +2130,13 @@ join_table: ...@@ -2127,11 +2130,13 @@ join_table:
{ {
SELECT_LEX *sel=Select; SELECT_LEX *sel=Select;
sel->use_index_ptr=sel->ignore_index_ptr=0; sel->use_index_ptr=sel->ignore_index_ptr=0;
sel->table_join_options= 0;
} }
table_ident opt_table_alias opt_key_definition table_ident opt_table_alias opt_key_definition
{ {
SELECT_LEX *sel=Select; SELECT_LEX *sel=Select;
if (!($$=add_table_to_list($2,$3,0,TL_UNLOCK, sel->use_index_ptr, if (!($$=add_table_to_list($2, $3, sel->table_join_options,
TL_UNLOCK, sel->use_index_ptr,
sel->ignore_index_ptr))) sel->ignore_index_ptr)))
YYABORT; YYABORT;
} }
...@@ -2150,12 +2155,20 @@ opt_key_definition: ...@@ -2150,12 +2155,20 @@ opt_key_definition:
sel->use_index= *$2; sel->use_index= *$2;
sel->use_index_ptr= &sel->use_index; sel->use_index_ptr= &sel->use_index;
} }
| FORCE_SYM key_usage_list
{
SELECT_LEX *sel=Select;
sel->use_index= *$2;
sel->use_index_ptr= &sel->use_index;
sel->table_join_options|= TL_OPTION_FORCE_INDEX;
}
| IGNORE_SYM key_usage_list | IGNORE_SYM key_usage_list
{ {
SELECT_LEX *sel=Select; SELECT_LEX *sel=Select;
sel->ignore_index= *$2; sel->ignore_index= *$2;
sel->ignore_index_ptr= &sel->ignore_index; sel->ignore_index_ptr= &sel->ignore_index;
}; }
;
key_usage_list: key_usage_list:
key_or_index { Select->interval_list.empty(); } '(' key_usage_list2 ')' key_or_index { Select->interval_list.empty(); } '(' key_usage_list2 ')'
...@@ -2443,7 +2456,7 @@ drop: ...@@ -2443,7 +2456,7 @@ drop:
lex->drop_list.empty(); lex->drop_list.empty();
lex->drop_list.push_back(new Alter_drop(Alter_drop::KEY, lex->drop_list.push_back(new Alter_drop(Alter_drop::KEY,
$3.str)); $3.str));
if (!add_table_to_list($5,NULL, 1)) if (!add_table_to_list($5, NULL, TL_OPTION_UPDATING))
YYABORT; YYABORT;
} }
| DROP DATABASE if_exists ident | DROP DATABASE if_exists ident
...@@ -2467,7 +2480,7 @@ table_list: ...@@ -2467,7 +2480,7 @@ table_list:
table_name: table_name:
table_ident table_ident
{ if (!add_table_to_list($1,NULL,1)) YYABORT; }; { if (!add_table_to_list($1,NULL,TL_OPTION_UPDATING)) YYABORT; };
if_exists: if_exists:
/* empty */ { $$= 0; } /* empty */ { $$= 0; }
...@@ -2678,7 +2691,8 @@ delete: ...@@ -2678,7 +2691,8 @@ delete:
single_multi: single_multi:
FROM table_ident FROM table_ident
{ {
if (!add_table_to_list($2, NULL, 1, Lex->lock_option)) if (!add_table_to_list($2, NULL, TL_OPTION_UPDATING,
Lex->lock_option))
YYABORT; YYABORT;
} }
where_clause opt_order_clause where_clause opt_order_clause
...@@ -2699,13 +2713,14 @@ table_wild_list: ...@@ -2699,13 +2713,14 @@ table_wild_list:
table_wild_one: table_wild_one:
ident opt_wild ident opt_wild
{ {
if (!add_table_to_list(new Table_ident($1), NULL, 1, if (!add_table_to_list(new Table_ident($1), NULL,
Lex->lock_option)) TL_OPTION_UPDATING, Lex->lock_option))
YYABORT; YYABORT;
} }
| ident '.' ident opt_wild | ident '.' ident opt_wild
{ {
if (!add_table_to_list(new Table_ident($1,$3,0), NULL, 1, if (!add_table_to_list(new Table_ident($1,$3,0), NULL,
TL_OPTION_UPDATING,
Lex->lock_option)) Lex->lock_option))
YYABORT; YYABORT;
} }
...@@ -2774,7 +2789,7 @@ show_param: ...@@ -2774,7 +2789,7 @@ show_param:
Lex->sql_command= SQLCOM_SHOW_FIELDS; Lex->sql_command= SQLCOM_SHOW_FIELDS;
if ($5) if ($5)
$4->change_db($5); $4->change_db($5);
if (!add_table_to_list($4,NULL,0)) if (!add_table_to_list($4, NULL, 0))
YYABORT; YYABORT;
} }
| NEW_SYM MASTER_SYM FOR_SYM SLAVE WITH MASTER_LOG_FILE_SYM EQ | NEW_SYM MASTER_SYM FOR_SYM SLAVE WITH MASTER_LOG_FILE_SYM EQ
...@@ -2807,7 +2822,7 @@ show_param: ...@@ -2807,7 +2822,7 @@ show_param:
Lex->sql_command= SQLCOM_SHOW_KEYS; Lex->sql_command= SQLCOM_SHOW_KEYS;
if ($4) if ($4)
$3->change_db($4); $3->change_db($4);
if (!add_table_to_list($3,NULL,0)) if (!add_table_to_list($3, NULL, 0))
YYABORT; YYABORT;
} }
| STATUS_SYM wild | STATUS_SYM wild
...@@ -2834,7 +2849,7 @@ show_param: ...@@ -2834,7 +2849,7 @@ show_param:
| CREATE TABLE_SYM table_ident | CREATE TABLE_SYM table_ident
{ {
Lex->sql_command = SQLCOM_SHOW_CREATE; Lex->sql_command = SQLCOM_SHOW_CREATE;
if(!add_table_to_list($3, NULL,0)) if(!add_table_to_list($3, NULL, 0))
YYABORT; YYABORT;
} }
| MASTER_SYM STATUS_SYM | MASTER_SYM STATUS_SYM
...@@ -2879,7 +2894,7 @@ describe: ...@@ -2879,7 +2894,7 @@ describe:
lex->wild=0; lex->wild=0;
lex->verbose=0; lex->verbose=0;
lex->sql_command=SQLCOM_SHOW_FIELDS; lex->sql_command=SQLCOM_SHOW_FIELDS;
if (!add_table_to_list($2, NULL,0)) if (!add_table_to_list($2, NULL, 0))
YYABORT; YYABORT;
} }
opt_describe_column {} opt_describe_column {}
...@@ -2999,14 +3014,14 @@ load: LOAD DATA_SYM load_data_lock opt_local INFILE TEXT_STRING ...@@ -2999,14 +3014,14 @@ load: LOAD DATA_SYM load_data_lock opt_local INFILE TEXT_STRING
opt_duplicate INTO TABLE_SYM table_ident opt_field_term opt_line_term opt_duplicate INTO TABLE_SYM table_ident opt_field_term opt_line_term
opt_ignore_lines opt_field_spec opt_ignore_lines opt_field_spec
{ {
if (!add_table_to_list($11,NULL,1)) if (!add_table_to_list($11, NULL, TL_OPTION_UPDATING))
YYABORT; YYABORT;
} }
| |
LOAD TABLE_SYM table_ident FROM MASTER_SYM LOAD TABLE_SYM table_ident FROM MASTER_SYM
{ {
Lex->sql_command = SQLCOM_LOAD_MASTER_TABLE; Lex->sql_command = SQLCOM_LOAD_MASTER_TABLE;
if (!add_table_to_list($3,NULL,1)) if (!add_table_to_list($3, NULL, TL_OPTION_UPDATING))
YYABORT; YYABORT;
} }
......
...@@ -91,6 +91,7 @@ struct st_table { ...@@ -91,6 +91,7 @@ struct st_table {
my_bool copy_blobs; /* copy_blobs when storing */ my_bool copy_blobs; /* copy_blobs when storing */
my_bool null_row; /* All columns are null */ my_bool null_row; /* All columns are null */
my_bool maybe_null,outer_join; /* Used with OUTER JOIN */ my_bool maybe_null,outer_join; /* Used with OUTER JOIN */
my_bool force_index;
my_bool distinct,const_table,no_rows; my_bool distinct,const_table,no_rows;
my_bool key_read, bulk_insert; my_bool key_read, bulk_insert;
my_bool crypted; my_bool crypted;
...@@ -157,6 +158,7 @@ typedef struct st_table_list ...@@ -157,6 +158,7 @@ typedef struct st_table_list
bool straight; /* optimize with prev table */ bool straight; /* optimize with prev table */
bool updating; /* for replicate-do/ignore table */ bool updating; /* for replicate-do/ignore table */
bool do_redirect; /* To get the struct in UNION's */ bool do_redirect; /* To get the struct in UNION's */
bool force_index; /* Prefer index over table scan */
} TABLE_LIST; } TABLE_LIST;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment