Commit b5e37b24 authored by unknown's avatar unknown

Don't count NULL values in cardinalty for MyISAM tables.

Free row buffer cache after each query for MyISAM tables.
Added table join option FORCE INDEX
Fixed core dump bug when connecting with hostname that could not be resolved.


include/my_base.h:
  Don't count NULL values in cardinalty
myisam/mi_check.c:
  Don't count NULL values in cardinalty
myisam/mi_extra.c:
  Free row buffer cache after each query
myisam/mi_open.c:
  Avoid realloc if cache size doesn't change
myisam/mi_search.c:
  Don't count NULL values in cardinalty
myisam/myisamdef.h:
  Change buffer length from uint to uint32 to make it more portable/predictable
mysql-test/r/myisam.result:
  Test case for cardinality with NULL keys and FORCE INDEX
mysql-test/t/myisam.test:
  Test case for cardinality with NULL keys and FORCE INDEX
sql/lex.h:
  Added table join option FORCE INDEX
sql/mysql_priv.h:
  Added table join option FORCE INDEX
sql/opt_range.cc:
  Added table join option FORCE INDEX
sql/sql_base.cc:
  Added table join option FORCE INDEX
sql/sql_lex.h:
  Added table join option FORCE INDEX
sql/sql_parse.cc:
  Added table join option FORCE INDEX
  Don't use strlen() on hostname without first checking if it's not NULL
sql/sql_select.cc:
  Added table join option FORCE INDEX
sql/sql_yacc.yy:
  Added table join option FORCE INDEX
sql/table.h:
  Added table join option FORCE INDEX
parent a3f4a46b
...@@ -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 /*
SEARCH_NO_FIND,SEARCH_LAST and HA_REVERSE_SORT flags. my_flag is raw comparison result to be changed according to
flag is the value returned by _mi_key_cmp and as treated as final */ SEARCH_NO_FIND,SEARCH_LAST and HA_REVERSE_SORT flags.
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,7 +498,8 @@ check_connections(THD *thd) ...@@ -498,7 +498,8 @@ 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 */
thd->host[min(strlen(thd->host), HOSTNAME_LENGTH)]= 0; if (thd->host)
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