diff options
-rw-r--r-- | include/my_base.h | 1 | ||||
-rw-r--r-- | myisam/mi_check.c | 3 | ||||
-rw-r--r-- | myisam/mi_extra.c | 5 | ||||
-rw-r--r-- | myisam/mi_open.c | 14 | ||||
-rw-r--r-- | myisam/mi_search.c | 47 | ||||
-rw-r--r-- | myisam/myisamdef.h | 4 | ||||
-rw-r--r-- | mysql-test/r/myisam.result | 44 | ||||
-rw-r--r-- | mysql-test/t/myisam.test | 26 | ||||
-rw-r--r-- | sql/lex.h | 1 | ||||
-rw-r--r-- | sql/mysql_priv.h | 6 | ||||
-rw-r--r-- | sql/opt_range.cc | 4 | ||||
-rw-r--r-- | sql/sql_base.cc | 6 | ||||
-rw-r--r-- | sql/sql_lex.h | 2 | ||||
-rw-r--r-- | sql/sql_parse.cc | 36 | ||||
-rw-r--r-- | sql/sql_select.cc | 3 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 55 | ||||
-rw-r--r-- | sql/table.h | 2 |
17 files changed, 207 insertions, 52 deletions
diff --git a/include/my_base.h b/include/my_base.h index bcb8c8d6a2f..feb5259ef08 100644 --- a/include/my_base.h +++ b/include/my_base.h @@ -263,6 +263,7 @@ enum ha_base_keytype { #define MBR_EQUAL 8192 #define MBR_DATA 16384 #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 */ #define QUICK_USED 1 diff --git a/myisam/mi_check.c b/myisam/mi_check.c index 540f3c92ad3..b65e963bcb7 100644 --- a/myisam/mi_check.c +++ b/myisam/mi_check.c @@ -601,7 +601,8 @@ static int chk_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo, if (*keys != 1L) /* not first_key */ { 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); param->unique_count[diff-1]++; } diff --git a/myisam/mi_extra.c b/myisam/mi_extra.c index 8429b22dad4..75057dd4e6a 100644 --- a/myisam/mi_extra.c +++ b/myisam/mi_extra.c @@ -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: 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)) { info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED); 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 (info->opt_flag & MEMMAP_USED) madvise(share->file_map,share->state.state.data_file_length,MADV_RANDOM); diff --git a/myisam/mi_open.c b/myisam/mi_open.c index aeacf81d90a..0da5ebabf40 100644 --- a/myisam/mi_open.c +++ b/myisam/mi_open.c @@ -559,28 +559,36 @@ err: DBUG_RETURN (NULL); } /* mi_open */ + byte *mi_alloc_rec_buff(MI_INFO *info, ulong length, byte **buf) { 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; /* to simplify initial init of info->rec_buf in mi_open and mi_extra */ if (length == (ulong) -1) + { length= max(info->s->base.pack_reclength+info->s->base.pack_bits, info->s->base.max_key_length); + /* Avoid unnecessary realloc */ + if (newptr && length == old_length) + return newptr; + } extra= ((info->s->options & HA_OPTION_PACK_RECORD) ? ALIGN_SIZE(MI_MAX_DYN_BLOCK_HEADER)+MI_SPLIT_LENGTH+ MI_REC_BUFF_OFFSET : 0); if (extra && newptr) - newptr-=MI_REC_BUFF_OFFSET; + newptr-= MI_REC_BUFF_OFFSET; if (!(newptr=(byte*) my_realloc((gptr)newptr, length+extra+8, MYF(MY_ALLOW_ZERO_PTR)))) return newptr; - *((uint *)newptr)=length; + *((uint32 *) newptr)= (uint32) length; *buf= newptr+(extra ? MI_REC_BUFF_OFFSET : 0); } return *buf; diff --git a/myisam/mi_search.c b/myisam/mi_search.c index d57fd1bb5b2..41d53e76241 100644 --- a/myisam/mi_search.c +++ b/myisam/mi_search.c @@ -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 *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. - flag is the value returned by _mi_key_cmp and as treated as final */ + /* + my_flag is raw comparison result to be changed according to + 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; uint nod_flag, length, len, matched, cmplen, kseg_len; uint prefix_len,suffix_len; @@ -695,13 +697,29 @@ static int compare_bin(uchar *a, uint a_length, uchar *b, uint b_length, } - /* - ** Compare two keys - ** Returns <0, 0, >0 acording to which is bigger - ** Key_length specifies length of key to use. Number-keys can't - ** be splited - ** If flag <> SEARCH_FIND compare also position - */ +/* + Compare two keys + + SYNOPSIS + _mi_key_cmp() + 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)) @@ -738,6 +756,15 @@ int _mi_key_cmp(register MI_KEYSEG *keyseg, register uchar *a, { if (nextflag == (SEARCH_FIND | SEARCH_UPDATE)) 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; continue; /* To next key part */ } diff --git a/myisam/myisamdef.h b/myisam/myisamdef.h index 07744e11e5f..601a9a40aea 100644 --- a/myisam/myisamdef.h +++ b/myisam/myisamdef.h @@ -358,7 +358,7 @@ struct st_myisam_info { #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_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 */ @@ -529,7 +529,7 @@ extern byte *mi_alloc_rec_buff(MI_INFO *,ulong, byte**); ((((info)->s->options & HA_OPTION_PACK_RECORD) && (buf)) ? \ (buf) - MI_REC_BUFF_OFFSET : (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, ulong reclength); diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result index 4a0eb47efb7..3a3558eedcb 100644 --- a/mysql-test/r/myisam.result +++ b/mysql-test/r/myisam.result @@ -1,4 +1,4 @@ -drop table if exists t1; +drop table if exists t1,t2; CREATE TABLE t1 ( STRING_DATA char(255) default NULL, KEY STRING_DATA (STRING_DATA) @@ -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); Specified key was too long. Max key length is 500 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; diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test index 1265d809149..c96a21e73dd 100644 --- a/mysql-test/t/myisam.test +++ b/mysql-test/t/myisam.test @@ -2,7 +2,13 @@ # 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 ( STRING_DATA char(255) default NULL, KEY STRING_DATA (STRING_DATA) @@ -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); 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; diff --git a/sql/lex.h b/sql/lex.h index 826b9b4a9ef..82ed322af83 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -151,6 +151,7 @@ static SYMBOL symbols[] = { { "FLOAT8", SYM(DOUBLE_SYM),0,0}, { "FLUSH", SYM(FLUSH_SYM),0,0}, { "FOREIGN", SYM(FOREIGN),0,0}, + { "FORCE", SYM(FORCE_SYM),0,0}, { "RAID_TYPE", SYM(RAID_TYPE),0,0}, { "RAID_CHUNKS", SYM(RAID_CHUNKS),0,0}, { "RAID_CHUNKSIZE", SYM(RAID_CHUNKSIZE),0,0}, diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 2a8b263bf28..75bf4e97634 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -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_INUSE "IN USE" +/* Options to add_table_to_list() */ +#define TL_OPTION_UPDATING 1 +#define TL_OPTION_FORCE_INDEX 2 + /* Some portable defines */ #define portable_sizeof_char_ptr 8 @@ -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); bool add_to_list(SQL_LIST &list,Item *group,bool asc=0); TABLE_LIST *add_table_to_list(Table_ident *table,LEX_STRING *alias, - bool updating, + ulong table_option, thr_lock_type flags=TL_UNLOCK, List<String> *use_index=0, List<String> *ignore_index=0); diff --git a/sql/opt_range.cc b/sql/opt_range.cc index a18c0178b5d..c607e71c01b 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -605,12 +605,14 @@ int SQL_SELECT::test_quick_select(key_map keys_to_use, table_map prev_tables, records++; /* purecov: inspected */ scan_time=(double) records / TIME_FOR_COMPARE+1; read_time=(double) head->file->scan_time()+ scan_time + 1.0; + if (head->force_index) + scan_time= read_time= DBL_MAX; if (limit < records) read_time=(double) records+scan_time+1; // Force to use index else if (read_time <= 2.0 && !force_quick_range) 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; if (keys_to_use) diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 7b7c8c01aab..54c3e40244a 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -752,7 +752,7 @@ TABLE *reopen_name_locked_table(THD* thd, TABLE_LIST* table_list) table->tablenr=thd->current_tablenr++; table->used_fields=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->keys_in_use_for_query= table->keys_in_use; table->used_keys= table->keys_for_keyread; @@ -910,7 +910,7 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name, table->tablenr=thd->current_tablenr++; table->used_fields=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->keys_in_use_for_query= table->keys_in_use; table->used_keys= table->keys_for_keyread; @@ -981,6 +981,7 @@ bool reopen_table(TABLE *table,bool locked) tmp.status= table->status; tmp.keys_in_use_for_query= tmp.keys_in_use; tmp.used_keys= tmp.keys_for_keyread; + tmp.force_index= tmp.force_index; /* Get state */ tmp.key_length= table->key_length; @@ -1888,6 +1889,7 @@ bool setup_tables(TABLE_LIST *tables) table->maybe_null=test(table->outer_join=table_list->outer_join); table->tablenr=tablenr; table->map= (table_map) 1 << tablenr; + table->force_index= table_list->force_index; if (table_list->use_index) { key_map map= get_key_map_from_key_list(table, diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 54e72fafdd5..a905871e629 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -110,7 +110,7 @@ typedef struct st_select_lex char *db,*db1,*table1,*db2,*table2; /* For outer join using .. */ Item *where,*having; ha_rows select_limit,offset_limit; - ulong options; + ulong options, table_join_options; List<List_item> expr_list; List<List_item> when_list; SQL_LIST order_list,table_list,group_list; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index a0336d0b50b..5bf3a1c0bcd 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -498,7 +498,8 @@ check_connections(THD *thd) vio_in_addr(net->vio,&thd->remote.sin_addr); thd->host=ip_to_hostname(&thd->remote.sin_addr,&connect_errors); /* 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) return(ER_HOST_IS_BLOCKED); } @@ -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, - bool updating, - thr_lock_type flags, + ulong table_options, + thr_lock_type lock_type, List<String> *use_index, - List<String> *ignore_index - ) + List<String> *ignore_index) { register TABLE_LIST *ptr; THD *thd=current_thd; @@ -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_length=table->table.length; - ptr->lock_type=flags; - ptr->updating=updating; + ptr->lock_type= lock_type; + ptr->updating= test(table_options & TL_OPTION_UPDATING); + ptr->force_index= test(table_options & TL_OPTION_FORCE_INDEX); if (use_index) ptr->use_index=(List<String> *) thd->memdup((gptr) use_index, sizeof(*use_index)); @@ -3221,7 +3241,7 @@ TABLE_LIST *add_table_to_list(Table_ident *table, LEX_STRING *alias, sizeof(*ignore_index)); /* 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 ; tables ; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 28aa21e94ce..237197ba6be 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -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 && best_max_key_part >= s->table->quick_key_parts[best_key->key]) && !((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 if (s->on_expr) { diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index e26e57b8bbd..0e93f048406 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2001 MySQL AB +/* Copyright (C) 2000-2003 MySQL AB 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 @@ -198,6 +198,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token FIRST_SYM %token FIXED_SYM %token FLOAT_NUM +%token FORCE_SYM %token FOREIGN %token FROM %token FULL @@ -735,7 +736,8 @@ create: lex->sql_command= SQLCOM_CREATE_TABLE; if (!add_table_to_list($5, ($2 & HA_LEX_CREATE_TMP_TABLE ? - &tmp_table_alias : (LEX_STRING*) 0),1)) + &tmp_table_alias : (LEX_STRING*) 0), + TL_OPTION_UPDATING)) YYABORT; lex->create_list.empty(); lex->key_list.empty(); @@ -751,7 +753,7 @@ create: { LEX *lex=Lex; 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; lex->create_list.empty(); lex->key_list.empty(); @@ -1171,7 +1173,7 @@ alter: LEX *lex=Lex; lex->sql_command = SQLCOM_ALTER_TABLE; lex->name=0; - if (!add_table_to_list($4, NULL,1)) + if (!add_table_to_list($4, NULL, TL_OPTION_UPDATING)) YYABORT; lex->drop_primary=0; lex->create_list.empty(); @@ -1442,8 +1444,9 @@ table_to_table_list: table_to_table: 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; }; @@ -2127,11 +2130,13 @@ join_table: { SELECT_LEX *sel=Select; sel->use_index_ptr=sel->ignore_index_ptr=0; + sel->table_join_options= 0; } table_ident opt_table_alias opt_key_definition { 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))) YYABORT; } @@ -2150,12 +2155,20 @@ opt_key_definition: sel->use_index= *$2; 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 { SELECT_LEX *sel=Select; sel->ignore_index= *$2; sel->ignore_index_ptr= &sel->ignore_index; - }; + } + ; key_usage_list: key_or_index { Select->interval_list.empty(); } '(' key_usage_list2 ')' @@ -2443,7 +2456,7 @@ drop: lex->drop_list.empty(); lex->drop_list.push_back(new Alter_drop(Alter_drop::KEY, $3.str)); - if (!add_table_to_list($5,NULL, 1)) + if (!add_table_to_list($5, NULL, TL_OPTION_UPDATING)) YYABORT; } | DROP DATABASE if_exists ident @@ -2467,7 +2480,7 @@ table_list: table_name: table_ident - { if (!add_table_to_list($1,NULL,1)) YYABORT; }; + { if (!add_table_to_list($1,NULL,TL_OPTION_UPDATING)) YYABORT; }; if_exists: /* empty */ { $$= 0; } @@ -2678,7 +2691,8 @@ delete: single_multi: 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; } where_clause opt_order_clause @@ -2699,13 +2713,14 @@ table_wild_list: table_wild_one: ident opt_wild { - if (!add_table_to_list(new Table_ident($1), NULL, 1, - Lex->lock_option)) + if (!add_table_to_list(new Table_ident($1), NULL, + TL_OPTION_UPDATING, Lex->lock_option)) YYABORT; } | 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)) YYABORT; } @@ -2774,7 +2789,7 @@ show_param: Lex->sql_command= SQLCOM_SHOW_FIELDS; if ($5) $4->change_db($5); - if (!add_table_to_list($4,NULL,0)) + if (!add_table_to_list($4, NULL, 0)) YYABORT; } | NEW_SYM MASTER_SYM FOR_SYM SLAVE WITH MASTER_LOG_FILE_SYM EQ @@ -2807,7 +2822,7 @@ show_param: Lex->sql_command= SQLCOM_SHOW_KEYS; if ($4) $3->change_db($4); - if (!add_table_to_list($3,NULL,0)) + if (!add_table_to_list($3, NULL, 0)) YYABORT; } | STATUS_SYM wild @@ -2834,7 +2849,7 @@ show_param: | CREATE TABLE_SYM table_ident { Lex->sql_command = SQLCOM_SHOW_CREATE; - if(!add_table_to_list($3, NULL,0)) + if(!add_table_to_list($3, NULL, 0)) YYABORT; } | MASTER_SYM STATUS_SYM @@ -2879,7 +2894,7 @@ describe: lex->wild=0; lex->verbose=0; lex->sql_command=SQLCOM_SHOW_FIELDS; - if (!add_table_to_list($2, NULL,0)) + if (!add_table_to_list($2, NULL, 0)) YYABORT; } opt_describe_column {} @@ -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_ignore_lines opt_field_spec { - if (!add_table_to_list($11,NULL,1)) + if (!add_table_to_list($11, NULL, TL_OPTION_UPDATING)) YYABORT; } | LOAD TABLE_SYM table_ident FROM MASTER_SYM { 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; } diff --git a/sql/table.h b/sql/table.h index 3a08cd11a2a..c3f469115b5 100644 --- a/sql/table.h +++ b/sql/table.h @@ -91,6 +91,7 @@ struct st_table { my_bool copy_blobs; /* copy_blobs when storing */ my_bool null_row; /* All columns are null */ my_bool maybe_null,outer_join; /* Used with OUTER JOIN */ + my_bool force_index; my_bool distinct,const_table,no_rows; my_bool key_read, bulk_insert; my_bool crypted; @@ -157,6 +158,7 @@ typedef struct st_table_list bool straight; /* optimize with prev table */ bool updating; /* for replicate-do/ignore table */ bool do_redirect; /* To get the struct in UNION's */ + bool force_index; /* Prefer index over table scan */ } TABLE_LIST; |