sql_select.cc ft-optimization: AND, GT/LT/GE/LE

sql_select.cc	EXPLAIN fulltext
Makefile.am	CLEANFILES corrected
sql_show.cc	SHOW CREATE now displays FULLTEXT keys properly
parent 23385734
...@@ -46,7 +46,7 @@ libmyisam_a_SOURCES = mi_open.c mi_extra.c mi_info.c mi_rkey.c \ ...@@ -46,7 +46,7 @@ libmyisam_a_SOURCES = mi_open.c mi_extra.c mi_info.c mi_rkey.c \
mi_delete_table.c mi_rename.c mi_check.c mi_debug.c \ mi_delete_table.c mi_rename.c mi_check.c mi_debug.c \
ft_parser.c ft_search.c ft_stopwords.c ft_static.c \ ft_parser.c ft_search.c ft_stopwords.c ft_static.c \
ft_update.c sort.c ft_update.c sort.c
CLEANFILES = test?.IS? isam.log mi_test_all CLEANFILES = test?.MY? FT?.MY? isam.log mi_test_all
DEFS = -DMAP_TO_USE_RAID DEFS = -DMAP_TO_USE_RAID
# Omit dependency for ../mit-pthreads/include/sys that only exits if # Omit dependency for ../mit-pthreads/include/sys that only exits if
# mit-pthreads are used # mit-pthreads are used
......
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
#include <assert.h> #include <assert.h>
const char *join_type_str[]={ "UNKNOWN","system","const","eq_ref","ref", const char *join_type_str[]={ "UNKNOWN","system","const","eq_ref","ref",
"MAYBE_REF","ALL","range","index" }; "MAYBE_REF","ALL","range","index","fulltext" };
static bool make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds, static bool make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
DYNAMIC_ARRAY *keyuse,List<Item_func_match> &ftfuncs); DYNAMIC_ARRAY *keyuse,List<Item_func_match> &ftfuncs);
...@@ -1280,15 +1280,54 @@ static void ...@@ -1280,15 +1280,54 @@ static void
add_ft_keys(DYNAMIC_ARRAY *keyuse_array, add_ft_keys(DYNAMIC_ARRAY *keyuse_array,
JOIN_TAB *stat,COND *cond,table_map usable_tables) JOIN_TAB *stat,COND *cond,table_map usable_tables)
{ {
/* for now, handling only the simples WHERE MATCH (...) case */ Item_func_match *cond_func=NULL;
/* a bit more complex WHERE MATCH (...) > const,
AND's and (perhaps) OR's are on the way SerG */ if (cond->type() == Item::FUNC_ITEM)
{
Item_func *func=(Item_func *)cond,
*arg0=(Item_func *)(func->arguments()[0]),
*arg1=(Item_func *)(func->arguments()[1]);
if (func->functype() == Item_func::FT_FUNC)
cond_func=(Item_func_match *)cond;
else if (arg0->type() == Item::FUNC_ITEM &&
arg0->functype() == Item_func::FT_FUNC &&
(func->functype() == Item_func::GE_FUNC ||
func->functype() == Item_func::GT_FUNC) &&
arg1->const_item() && arg1->val()>=0)
cond_func=(Item_func_match *)arg0;
else if (arg1->type() == Item::FUNC_ITEM &&
arg1->functype() == Item_func::FT_FUNC &&
(func->functype() == Item_func::LE_FUNC ||
func->functype() == Item_func::LT_FUNC) &&
arg0->const_item() && arg0->val()>=0)
cond_func=(Item_func_match *)arg1;
}
else if (cond->type() == Item::COND_ITEM)
{
List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
if (cond->type() != Item::FUNC_ITEM || if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
((Item_func*) cond)->functype() != Item_func::FT_FUNC) {
return; Item *item;
/* I'm too lazy to implement proper recursive descent here,
and anyway, nobody will use such a stupid queries
that will require it :-)
May be later...
*/
while ((item=li++))
if (item->type() == Item::FUNC_ITEM &&
((Item_func *)item)->functype() == Item_func::FT_FUNC)
{
cond_func=(Item_func_match *)item;
break;
}
}
}
if(!cond_func)
return;
Item_func_match *cond_func= (Item_func_match *) cond;
KEYUSE keyuse; KEYUSE keyuse;
keyuse.table= cond_func->table; keyuse.table= cond_func->table;
...@@ -1936,8 +1975,7 @@ get_best_combination(JOIN *join) ...@@ -1936,8 +1975,7 @@ get_best_combination(JOIN *join)
if (ftkey) if (ftkey)
{ {
j->ref.items[0]=((Item_func*)(keyuse->val))->key_item(); j->ref.items[0]=((Item_func*)(keyuse->val))->key_item();
if (!keyuse->used_tables && if (!keyuse->used_tables)
!(join->select_options & SELECT_DESCRIBE))
{ {
// AFAIK key_buff is zeroed... // AFAIK key_buff is zeroed...
// We don't need to free ft_tmp as the buffer will be freed atom. // We don't need to free ft_tmp as the buffer will be freed atom.
......
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult 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
the Free Software Foundation; either version 2 of the License, or the Free Software Foundation; either version 2 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
...@@ -488,7 +488,7 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list) ...@@ -488,7 +488,7 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list)
if (send_fields(thd,field_list,1)) if (send_fields(thd,field_list,1))
DBUG_RETURN(1); DBUG_RETURN(1);
String *packet = &thd->packet; String *packet = &thd->packet;
for(;table; table = table->next) for(;table; table = table->next)
{ {
...@@ -510,7 +510,7 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list) ...@@ -510,7 +510,7 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list)
// into fewer, so we cannot use net_store_data() anymore, // into fewer, so we cannot use net_store_data() anymore,
// and do it ourselves // and do it ourselves
char* p = (char*)packet->ptr() + store_len_offset; char* p = (char*)packet->ptr() + store_len_offset;
*p++ = (char) 253; // The client the length is stored using 3-bytes *p++ = (char) 253; // The client the length is stored using 3-bytes
int3store(p, create_len); int3store(p, create_len);
// now we are in business :-) // now we are in business :-)
...@@ -649,10 +649,10 @@ mysqld_dump_create_info(THD *thd, TABLE *table, int fd) ...@@ -649,10 +649,10 @@ mysqld_dump_create_info(THD *thd, TABLE *table, int fd)
DBUG_PRINT("enter",("table: %s",table->real_name)); DBUG_PRINT("enter",("table: %s",table->real_name));
String* packet = &thd->packet; String* packet = &thd->packet;
packet->length(0); packet->length(0);
if(store_create_info(thd,table,packet)) if(store_create_info(thd,table,packet))
DBUG_RETURN(-1); DBUG_RETURN(-1);
if(fd < 0) if(fd < 0)
{ {
if(my_net_write(&thd->net, (char*)packet->ptr(), packet->length())) if(my_net_write(&thd->net, (char*)packet->ptr(), packet->length()))
...@@ -661,14 +661,14 @@ mysqld_dump_create_info(THD *thd, TABLE *table, int fd) ...@@ -661,14 +661,14 @@ mysqld_dump_create_info(THD *thd, TABLE *table, int fd)
} }
else else
{ {
if(my_write(fd, (const byte*) packet->ptr(), packet->length(), if(my_write(fd, (const byte*) packet->ptr(), packet->length(),
MYF(MY_WME))) MYF(MY_WME)))
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
DBUG_RETURN(0); DBUG_RETURN(0);
} }
static int static int
store_create_info(THD *thd, TABLE *table, String* packet) store_create_info(THD *thd, TABLE *table, String* packet)
{ {
...@@ -676,37 +676,37 @@ store_create_info(THD *thd, TABLE *table, String* packet) ...@@ -676,37 +676,37 @@ store_create_info(THD *thd, TABLE *table, String* packet)
DBUG_PRINT("enter",("table: %s",table->real_name)); DBUG_PRINT("enter",("table: %s",table->real_name));
restore_record(table,2); // Get empty record restore_record(table,2); // Get empty record
List<Item> field_list; List<Item> field_list;
char tmp[MAX_FIELD_WIDTH]; char tmp[MAX_FIELD_WIDTH];
String type(tmp, sizeof(tmp)); String type(tmp, sizeof(tmp));
packet->append("create table ", 13); packet->append("create table ", 13);
packet->append(table->real_name); packet->append(table->real_name);
packet->append('('); packet->append('(');
Field **ptr,*field; Field **ptr,*field;
for (ptr=table->field ; (field= *ptr); ptr++) for (ptr=table->field ; (field= *ptr); ptr++)
{ {
if(ptr != table->field) if(ptr != table->field)
packet->append(','); packet->append(',');
uint flags = field->flags; uint flags = field->flags;
packet->append(field->field_name); packet->append(field->field_name);
packet->append(' '); packet->append(' ');
// check for surprises from the previous call to Field::sql_type() // check for surprises from the previous call to Field::sql_type()
if(type.ptr() != tmp) if(type.ptr() != tmp)
type.set(tmp, sizeof(tmp)); type.set(tmp, sizeof(tmp));
field->sql_type(type); field->sql_type(type);
packet->append(type.ptr(),type.length()); packet->append(type.ptr(),type.length());
bool null_default_value = (field->type() == FIELD_TYPE_TIMESTAMP || bool null_default_value = (field->type() == FIELD_TYPE_TIMESTAMP ||
field->unireg_check == Field::NEXT_NUMBER); field->unireg_check == Field::NEXT_NUMBER);
bool has_default = (field->type() != FIELD_TYPE_BLOB); bool has_default = (field->type() != FIELD_TYPE_BLOB);
if((flags & NOT_NULL_FLAG) && !null_default_value) if((flags & NOT_NULL_FLAG) && !null_default_value)
packet->append(" not null", 9); packet->append(" not null", 9);
if(has_default) if(has_default)
{ {
...@@ -724,51 +724,54 @@ store_create_info(THD *thd, TABLE *table, String* packet) ...@@ -724,51 +724,54 @@ store_create_info(THD *thd, TABLE *table, String* packet)
else else
packet->append(tmp,0); packet->append(tmp,0);
} }
if (field->unireg_check == Field::NEXT_NUMBER) if (field->unireg_check == Field::NEXT_NUMBER)
packet->append(" auto_increment", 15 ); packet->append(" auto_increment", 15 );
} }
KEY *key_info=table->key_info; KEY *key_info=table->key_info;
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK | HA_STATUS_TIME); table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK | HA_STATUS_TIME);
uint primary_key = table->primary_key; uint primary_key = table->primary_key;
for (uint i=0 ; i < table->keys ; i++,key_info++) for (uint i=0 ; i < table->keys ; i++,key_info++)
{ {
packet->append(','); packet->append(',');
KEY_PART_INFO *key_part= key_info->key_part; KEY_PART_INFO *key_part= key_info->key_part;
if(i == primary_key) if(i == primary_key)
packet->append("primary", 7); packet->append("primary", 7);
else if(key_info->flags & HA_NOSAME) else if(key_info->flags & HA_NOSAME)
packet->append("unique", 6); packet->append("unique", 6);
else if(key_info->flags & HA_FULLTEXT)
packet->append("fulltext", 8);
packet->append(" key ", 5); packet->append(" key ", 5);
if(i != primary_key) if(i != primary_key)
packet->append(key_info->name); packet->append(key_info->name);
packet->append('('); packet->append('(');
for (uint j=0 ; j < key_info->key_parts ; j++,key_part++) for (uint j=0 ; j < key_info->key_parts ; j++,key_part++)
{ {
if(j) if(j)
packet->append(','); packet->append(',');
if(key_part->field) if(key_part->field)
packet->append(key_part->field->field_name); packet->append(key_part->field->field_name);
KEY *key=table->key_info+i; KEY *key=table->key_info+i;
if (!key_part->field || if (!key_part->field ||
key_part->length != (key_part->length !=
table->field[key_part->fieldnr-1]->key_length()) table->field[key_part->fieldnr-1]->key_length() &&
!(key_info->flags & HA_FULLTEXT)))
{ {
char buff[64]; char buff[64];
buff[0] = '('; buff[0] = '(';
char* end=int10_to_str((long) key_part->length, buff + 1,10); char* end=int10_to_str((long) key_part->length, buff + 1,10);
*end++ = ')'; *end++ = ')';
packet->append(buff,(uint) (end-buff)); packet->append(buff,(uint) (end-buff));
} }
} }
...@@ -776,13 +779,13 @@ store_create_info(THD *thd, TABLE *table, String* packet) ...@@ -776,13 +779,13 @@ store_create_info(THD *thd, TABLE *table, String* packet)
} }
packet->append(')'); packet->append(')');
handler *file = table->file; handler *file = table->file;
packet->append(" type=", 6); packet->append(" type=", 6);
packet->append(file->table_type()); packet->append(file->table_type());
char buff[128]; char buff[128];
char* p; char* p;
if(table->min_rows) if(table->min_rows)
{ {
packet->append(" min_rows="); packet->append(" min_rows=");
...@@ -796,7 +799,7 @@ store_create_info(THD *thd, TABLE *table, String* packet) ...@@ -796,7 +799,7 @@ store_create_info(THD *thd, TABLE *table, String* packet)
p = longlong10_to_str(table->max_rows, buff, 10); p = longlong10_to_str(table->max_rows, buff, 10);
packet->append(buff, (uint) (p - buff)); packet->append(buff, (uint) (p - buff));
} }
if (table->db_create_options & HA_OPTION_PACK_KEYS) if (table->db_create_options & HA_OPTION_PACK_KEYS)
packet->append(" pack_keys=1", 12); packet->append(" pack_keys=1", 12);
if (table->db_create_options & HA_OPTION_NO_PACK_KEYS) if (table->db_create_options & HA_OPTION_NO_PACK_KEYS)
...@@ -806,7 +809,7 @@ store_create_info(THD *thd, TABLE *table, String* packet) ...@@ -806,7 +809,7 @@ store_create_info(THD *thd, TABLE *table, String* packet)
if (table->db_create_options & HA_OPTION_DELAY_KEY_WRITE) if (table->db_create_options & HA_OPTION_DELAY_KEY_WRITE)
packet->append(" delay_key_write=1",18); packet->append(" delay_key_write=1",18);
DBUG_RETURN(0); DBUG_RETURN(0);
} }
......
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