diff options
author | serg@infomag.ape.relarn.ru <> | 2000-08-28 17:43:58 +0400 |
---|---|---|
committer | serg@infomag.ape.relarn.ru <> | 2000-08-28 17:43:58 +0400 |
commit | eb8ad15751606cf9203caff2515ac868dd03c8d0 (patch) | |
tree | 485c3b99b43fae8c2b58b7a5ab72b383265423d2 | |
parent | 6236dfc7a34cd528b5d11fad4ce32d230720ce44 (diff) | |
download | mariadb-git-eb8ad15751606cf9203caff2515ac868dd03c8d0.tar.gz |
ft_optimization: identical queries merging. collection -> fulltext. Bugs fixed.
**************** !!! NOTE EVERYBODY: SYNTAX CHANGED !!! ********************
There's no COLLECTIONs now, full-text indexes can be created via the word
FULLTEXT, which should be used like UNIQUE.
-rw-r--r-- | Docs/manual.texi | 84 | ||||
-rw-r--r-- | myisam/ft_search.c | 7 | ||||
-rw-r--r-- | myisam/mi_check.c | 20 | ||||
-rw-r--r-- | sql/item_func.cc | 69 | ||||
-rw-r--r-- | sql/item_func.h | 21 | ||||
-rw-r--r-- | sql/lex.h | 24 | ||||
-rw-r--r-- | sql/sql_base.cc | 84 | ||||
-rw-r--r-- | sql/sql_select.cc | 41 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 28 |
9 files changed, 208 insertions, 170 deletions
diff --git a/Docs/manual.texi b/Docs/manual.texi index 3b4e1ff5eaf..ae56e1e15f4 100644 --- a/Docs/manual.texi +++ b/Docs/manual.texi @@ -11670,7 +11670,6 @@ to restart @code{mysqld} with @code{--skip-grant-tables} to be able to run * GRANT:: @code{GRANT} and @code{REVOKE} syntax * CREATE INDEX:: @code{CREATE INDEX} syntax * DROP INDEX:: @code{DROP INDEX} syntax -* CREATE COLLECTION:: @code{CREATE COLLECTION} syntax * Comments:: Comment syntax * CREATE FUNCTION:: @code{CREATE FUNCTION} syntax * Reserved words:: Is @strong{MySQL} picky about reserved words? @@ -13436,9 +13435,9 @@ mysql> CREATE TABLE test ( For @code{BLOB} and @code{TEXT} columns, you must index a prefix of the column, you cannot index the entire thing. -In @strong{MySQL} 3.23.23 or later, you can also create special indexes -called @strong{collections}. They are used for full-text search. Only -@code{MyISAM} table type supports collections. Collection can be created +In @strong{MySQL} 3.23.23 or later, you can also create special +@strong{fulltext} indexes. They are used for full-text search. Only +@code{MyISAM} table type supports fulltext indexes. They can be created only from @code{VARCHAR}, @code{BLOB}, and @code{TEXT} columns. Indexing always happens over the entire column, partial indexing is not supported. See @ref{MySQL full-text search} for details of operation. @@ -14165,7 +14164,7 @@ mysql> select STRCMP('text', 'text'); relevance - similarity measure between the text in columns @code{(col1,col2,...)} and the query @code{expr}. Relevance is a positive floating point number. Zero relevance means no similarity. -For @code{MATCH ... AGAINST()} to work, a @code{COLLECTION} +For @code{MATCH ... AGAINST()} to work, a @strong{fulltext index} must be created first. @xref{CREATE TABLE, , @code{CREATE TABLE}}. @code{MATCH ... AGAINST()} is available in @code{MySQL} 3.23.23 or later. For details and usage examples see @xref{MySQL full-text search}. @@ -16178,7 +16177,7 @@ create_definition: or KEY [index_name] (index_col_name,...) or INDEX [index_name] (index_col_name,...) or UNIQUE [INDEX] [index_name] (index_col_name,...) - or COLLECTION [collection_name] (collection_col_name,...) + or FULLTEXT [INDEX] [index_name] (index_col_name,...) or [CONSTRAINT symbol] FOREIGN KEY index_name (index_col_name,...) [reference_definition] or CHECK (expr) @@ -16422,10 +16421,10 @@ When you use @code{ORDER BY} or @code{GROUP BY} with a @code{TEXT} or @xref{BLOB, , @code{BLOB}}. @item -In @strong{MySQL} 3.23.23 or later, you can also create special indexes -called @strong{collections}. They are used for full-text search. Only -@code{MyISAM} table type supports collections. Collection can be created -from any mix of @code{VARCHAR}, @code{BLOB}, and @code{TEXT} columns. +In @strong{MySQL} 3.23.23 or later, you can also create special +@strong{fulltext} indexes. They are used for full-text search. Only +@code{MyISAM} table type supports fulltext indexes. They can be created +only from @code{VARCHAR}, @code{BLOB}, and @code{TEXT} columns. Indexing always happens over the entire column, partial indexing is not supported. See @ref{MySQL full-text search} for details of operation. @@ -16598,7 +16597,7 @@ alter_specification: or ADD INDEX [index_name] (index_col_name,...) or ADD PRIMARY KEY (index_col_name,...) or ADD UNIQUE [index_name] (index_col_name,...) - or ADD COLLECTION [collection_name] (collection_col_name,...) + or ADD FULLTEXT [index_name] (index_col_name,...) or ALTER [COLUMN] col_name @{SET DEFAULT literal | DROP DEFAULT@} or CHANGE [COLUMN] old_col_name create_definition or MODIFY [COLUMN] create_definition @@ -19769,7 +19768,7 @@ dropped only with explicit @code{REVOKE} commands or by manipulating the @section @code{CREATE INDEX} syntax @example -CREATE [UNIQUE] INDEX index_name ON tbl_name (col_name[(length)],... ) +CREATE [UNIQUE|FULLTEXT] INDEX index_name ON tbl_name (col_name[(length)],... ) @end example The @code{CREATE INDEX} statement doesn't do anything in @strong{MySQL} prior @@ -19803,15 +19802,19 @@ which could save a lot of disk space and might also speed up @code{INSERT} operations! Note that you can only add an index on a column that can have @code{NULL} -values or on a @code{BLOB}/@code{TEXT} column if you are useing +values or on a @code{BLOB}/@code{TEXT} column if you are using @strong{MySQL} version 3.23.2 or newer and are using the @code{MyISAM} table type. For more information about how @strong{MySQL} uses indexes, see @ref{MySQL indexes, , @strong{MySQL} indexes}. +Fulltext indexes can index only @code{VARCHAR}, @code{BLOB}, and +@code{TEXT} columns, and only in @code{MyISAM} tables. Fulltext indexes +are available from @strong{MySQL} 3.23.23. @ref{MySQL full-text search}. + @findex DROP INDEX -@node DROP INDEX, CREATE COLLECTION, CREATE INDEX, Reference +@node DROP INDEX, Comments, CREATE INDEX, Reference @section @code{DROP INDEX} syntax @example @@ -19824,30 +19827,8 @@ prior to version 3.22. In 3.22 or later, @code{DROP INDEX} is mapped to an @code{ALTER TABLE} statement to drop the index. @xref{ALTER TABLE, , @code{ALTER TABLE}}. -@findex CREATE COLLECTION -@node CREATE COLLECTION, Comments, DROP INDEX, Reference -@section @code{CREATE COLLECTION} syntax - -@example -CREATE COLLECTION collection_name ON tbl_name (col_name,... ) -@end example - -@code{CREATE COLLECTION} statement is mapped to an -@code{ALTER TABLE} statement to create collections. -@xref{ALTER TABLE, , @code{ALTER TABLE}}. - -A column list of the form @code{(col1,col2,...)} creates a -multiple-column collection. Search in such a collection means a search -over the concatenated columns that comprise the collection. - -There is no special @code{DROP COLLECTION} statement. -@code{DROP INDEX} should be used to drop collections instead. - -Only @code{VARCHAR}, @code{BLOB}, and @code{TEXT} columns can be part -of the collection. See @ref{MySQL full-text search} for details of operation. - @findex Comment syntax -@node Comments, CREATE FUNCTION, CREATE COLLECTION, Reference +@node Comments, CREATE FUNCTION, DROP INDEX, Reference @section Comment syntax The @strong{MySQL} server supports the @code{# to end of line}, @code{-- @@ -34106,14 +34087,14 @@ DELAYED} threads. @section MySQL full-text search Since version 3.23.23, @strong{MySQL} has support for full-text indexing -and searching. Full-text index in @strong{MySQL} is a special type of index -called @strong{collection}. Collections can be created from @code{VARCHAR}, -@code{TEXT}, and @code{BLOB} columns at @code{CREATE TABLE} -time or added later with @code{ALTER TABLE} or @code{CREATE COLLECTION}. -Collection is queried with @code{MATCH} function. +and searching. Full-text index in @strong{MySQL} is an +index of type @code{FULLTEXT}. Fulltext indexes can be created from +@code{VARCHAR}, @code{TEXT}, and @code{BLOB} columns at +@code{CREATE TABLE} time or added later with @code{ALTER TABLE} or +@code{CREATE INDEX}. Full-text search is performed with @code{MATCH} function. @example -mysql> CREATE TABLE t (a VARCHAR(200), b TEXT, COLLECTION (a,b)); +mysql> CREATE TABLE t (a VARCHAR(200), b TEXT, FULLTEXT (a,b)); Query OK, 0 rows affected (0.00 sec) mysql> INSERT INTO t VALUES -> ('MySQL has now support', 'for full-text search'), @@ -34145,15 +34126,16 @@ mysql> SELECT *,MATCH a,b AGAINST ('collections support') as x FROM t; @end example Function @code{MATCH} matches a natural language query @code{AGAINST} a -text collection. For every row in a table it returns relevance - +text collection (which is simply the columns that are covered +by fulltext index). For every row in a table it returns relevance - similarity measure between the text in that row (in the columns, that -are part of the collection) and the query. When it used in a @code{WHERE} -clause (see example above) the rows returned are automatically sorted -with relevance decreasing. Relevance is a non-negative floating point -number. Zero relevance means no similarity. Relevance is computed based -on number of words in the row and number of unique words in that row, -total number of words in the collection, number of documents (rows), -that contain a particular word, etc. +are part of the collection) and the query. When it used in a +@code{WHERE} clause (see example above) the rows returned are +automatically sorted with relevance decreasing. Relevance is a non- +negative floating point number. Zero relevance means no similarity. +Relevance is computed based on number of words in the row and number of +unique words in that row, total number of words in the collection, +number of documents (rows), that contain a particular word, etc. MySQL uses very simple parser to split text into words. "Word" is any sequence of letters, numbers, @code{'}, and @code{_}. Any "word" diff --git a/myisam/ft_search.c b/myisam/ft_search.c index 9dfa7f05412..91c63055fef 100644 --- a/myisam/ft_search.c +++ b/myisam/ft_search.c @@ -158,6 +158,7 @@ FT_DOCLIST * ft_init_search(void *info, uint keynr, byte *key, ALL_IN_ONE aio; FT_DOCLIST *dlist; FT_DOC *dptr; + my_off_t saved_lastpos; /* black magic ON */ if ((int) (keynr = _mi_check_index((MI_INFO *)info,keynr)) < 0) @@ -173,6 +174,8 @@ FT_DOCLIST * ft_init_search(void *info, uint keynr, byte *key, aio.keyinfo=aio.info->s->keyinfo+keynr; aio.key_root=aio.info->s->state.key_root[keynr]; + saved_lastpos=aio.info->lastpos; + if(!(wtree=ft_parse(NULL,key,key_len))) return NULL; init_tree(&aio.dtree,0,sizeof(FT_SUPERDOC),(qsort_cmp)&FT_SUPERDOC_cmp,0, @@ -199,6 +202,7 @@ FT_DOCLIST * ft_init_search(void *info, uint keynr, byte *key, } err: + aio.info->lastpos=saved_lastpos; delete_tree(&aio.dtree); delete_tree(wtree); free(wtree); @@ -217,7 +221,8 @@ int ft_read_next(FT_DOCLIST *handler, char *record) info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); - if (!(*info->read_record)(info,handler->doc[handler->curdoc].dpos,record)) + info->lastpos=handler->doc[handler->curdoc].dpos; + if (!(*info->read_record)(info,info->lastpos,record)) { info->update|= HA_STATE_AKTIV; /* Record is read */ return 0; diff --git a/myisam/mi_check.c b/myisam/mi_check.c index c6bd9f67c65..2b5a14f1e87 100644 --- a/myisam/mi_check.c +++ b/myisam/mi_check.c @@ -1141,7 +1141,13 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info, for (i=0 ; i < share->state.header.max_block_size ; i++) share->state.key_del[i]= HA_OFFSET_ERROR; - share->state.key_map= ((ulonglong)1L << share->base.keys)-1; /* Should I ? */ + /* I think mi_repair and mi_repair_by_sort should do the same + (according, e.g. to ha_myisam::repair), but as mi_repair doesn't + touch key_map it cannot be used to T_CREATE_MISSING_KEYS. + That is the next line for... (serg) + */ + + share->state.key_map= ((ulonglong)1L << share->base.keys)-1; info->state->key_file_length=share->base.keystart; @@ -1935,6 +1941,11 @@ static int sort_key_read(SORT_INFO *sort_info, void *key) "Found too many records; Can`t continue"); DBUG_RETURN(1); } + /* Hmm, repair_by_sort uses find_all_keys, and find_all_keys strictly + implies "one row - one key per keynr", while for ft_key one row/keynr + can produce as many keys as the number of unique words in the text + that's why I disabled repair_by_sort for ft-keys. (serg) + */ if (sort_info->keyinfo->flag & HA_FULLTEXT ) { mi_check_print_error(sort_info->param, @@ -3009,6 +3020,13 @@ my_bool mi_test_if_sort_rep(MI_INFO *info, ha_rows rows) return FALSE; /* Can't use sort */ for (i=0 ; i < share->base.keys ; i++,key++) { +/* It's to disable repair_by_sort for ft-keys. + Another solution would be to make ft-keys just too_big_key_for_sort, + but then they won't be disabled by dectivate_non_unique_index + and so they will be created at the first stage. As ft-key creation + is very time-consuming process, it's better to leave it to repair stage + but this repair shouldn't be repair_by_sort (serg) + */ if (mi_too_big_key_for_sort(key,rows) || (key->flag & HA_FULLTEXT)) return FALSE; } diff --git a/sql/item_func.cc b/sql/item_func.cc index 66e03e72f6b..65677690ed3 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -1837,26 +1837,8 @@ err: double Item_func_match::val() { - my_off_t docid=table->file->row_position(); // HAVE to do it here... - if (first_call) - { - if (join_key=(table->file->get_index() == key && - (ft_handler=(FT_DOCLIST *)table->file->ft_handler))) - ; - else - { - /* join won't use this ft-key, but we must to init it anyway */ - String *ft_tmp=0; - char tmp1[FT_QUERY_MAXLEN]; - String tmp2(tmp1,sizeof(tmp1)); - - ft_tmp=key_item()->val_str(&tmp2); - ft_handler=(FT_DOCLIST *) - table->file->ft_init_ext(key, (byte*) ft_tmp->ptr(), ft_tmp->length()); - } - first_call=0; - } + init_search(); // Don't know how to return an error from val(), so NULL will be returned if ((null_value=(ft_handler==NULL))) @@ -1873,6 +1855,7 @@ double Item_func_match::val() int a,b,c; FT_DOC *docs=ft_handler->doc; + my_off_t docid=table->file->row_position(); if ((null_value=(docid==HA_OFFSET_ERROR))) return 0.0; @@ -1893,6 +1876,36 @@ double Item_func_match::val() } } +void Item_func_match::init_search() +{ + if (!first_call) + return; + first_call=false; + + if (master) + { + master->init_search(); + ft_handler=master->ft_handler; + join_key=master->join_key; + return; + } + + if (join_key) + { + ft_handler=((FT_DOCLIST *)table->file->ft_handler); + return; + } + + /* join won't use this ft-key, but we must to init it anyway */ + String *ft_tmp=0; + char tmp1[FT_QUERY_MAXLEN]; + String tmp2(tmp1,sizeof(tmp1)); + + ft_tmp=key_item()->val_str(&tmp2); + ft_handler=(FT_DOCLIST *) + table->file->ft_init_ext(key, (byte*) ft_tmp->ptr(), ft_tmp->length()); +} + bool Item_func_match::fix_fields(THD *thd,struct st_table_list *tlist) { List_iterator<Item> li(fields); @@ -1982,6 +1995,24 @@ bool Item_func_match::fix_index() this->key=max_key; first_call=1; maybe_null=1; + join_key=0; + + return 0; +} + +bool Item_func_match::eq(const Item *item) const +{ + if (item->type() != FUNC_ITEM) + return 0; + + if (func_name() != ((Item_func*)item)->func_name()) + return 0; + + Item_func_match *ifm=(Item_func_match*) item; + + if (key == ifm->key && table == ifm->table && + key_item()->eq(ifm->key_item())) + return 1; return 0; } diff --git a/sql/item_func.h b/sql/item_func.h index efee77c7be2..4af3e604f38 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -839,19 +839,28 @@ public: TABLE *table; uint key; bool first_call, join_key; + Item_func_match *master; FT_DOCLIST *ft_handler; Item_func_match(List<Item> &a, Item *b): Item_real_func(b), - fields(a), table(0), ft_handler(0) - {} - ~Item_func_match() { ft_close_search(ft_handler); - if(join_key) table->file->ft_handler=0; } + fields(a), table(0), ft_handler(0), master(0) {} + ~Item_func_match() + { + if (!master) + { + ft_close_search(ft_handler); + if(join_key) + table->file->ft_handler=0; + } + } const char *func_name() const { return "match"; } enum Functype functype() const { return FT_FUNC; } void update_used_tables() {} bool fix_fields(THD *thd,struct st_table_list *tlist); - bool fix_index(); - + bool eq(const Item *) const; double val(); longlong val_int() { return val()!=0.0; } + + bool fix_index(); + void init_search(); }; diff --git a/sql/lex.h b/sql/lex.h index a88bbe76fdd..a5c802e761c 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -1,15 +1,15 @@ /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult 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 the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ @@ -81,7 +81,6 @@ static SYMBOL symbols[] = { { "CHANGED", SYM(CHANGED),0,0}, { "CHECK", SYM(CHECK_SYM),0,0}, { "CHECKSUM", SYM(CHECKSUM_SYM),0,0}, - { "COLLECTION", SYM(COLLECTION),0,0}, { "COLUMN", SYM(COLUMN_SYM),0,0}, { "COLUMNS", SYM(COLUMNS),0,0}, { "COMMENT", SYM(COMMENT_SYM),0,0}, @@ -142,6 +141,7 @@ static SYMBOL symbols[] = { { "FROM", SYM(FROM),0,0}, { "FOR", SYM(FOR_SYM),0,0}, { "FULL", SYM(FULL),0,0}, + { "FULLTEXT", SYM(FULLTEXT_SYM),0,0}, { "FUNCTION", SYM(UDF_SYM),0,0}, { "GRANT", SYM(GRANT),0,0}, { "GRANTS", SYM(GRANTS),0,0}, @@ -191,14 +191,14 @@ static SYMBOL symbols[] = { { "LONGBLOB", SYM(LONGBLOB),0,0}, { "LONGTEXT", SYM(LONGTEXT),0,0}, { "LOW_PRIORITY", SYM(LOW_PRIORITY),0,0}, - { "MASTER", SYM(MASTER_SYM),0,0}, - { "MASTER_CONNECT_RETRY", SYM(MASTER_CONNECT_RETRY_SYM),0,0}, - { "MASTER_HOST", SYM(MASTER_HOST_SYM),0,0}, - { "MASTER_LOG_FILE", SYM(MASTER_LOG_FILE_SYM),0,0}, - { "MASTER_LOG_POS", SYM(MASTER_LOG_POS_SYM),0,0}, - { "MASTER_PASSWORD", SYM(MASTER_PASSWORD_SYM),0,0}, - { "MASTER_PORT", SYM(MASTER_PORT_SYM),0,0}, - { "MASTER_USER", SYM(MASTER_USER_SYM),0,0}, + { "MASTER", SYM(MASTER_SYM),0,0}, + { "MASTER_CONNECT_RETRY", SYM(MASTER_CONNECT_RETRY_SYM),0,0}, + { "MASTER_HOST", SYM(MASTER_HOST_SYM),0,0}, + { "MASTER_LOG_FILE", SYM(MASTER_LOG_FILE_SYM),0,0}, + { "MASTER_LOG_POS", SYM(MASTER_LOG_POS_SYM),0,0}, + { "MASTER_PASSWORD", SYM(MASTER_PASSWORD_SYM),0,0}, + { "MASTER_PORT", SYM(MASTER_PORT_SYM),0,0}, + { "MASTER_USER", SYM(MASTER_USER_SYM),0,0}, { "MAX_ROWS", SYM(MAX_ROWS),0,0}, { "MATCH", SYM(MATCH),0,0}, { "MEDIUMBLOB", SYM(MEDIUMBLOB),0,0}, diff --git a/sql/sql_base.cc b/sql/sql_base.cc index e6468890ed6..6bf44f7d7d6 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1,15 +1,15 @@ /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult 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 the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ @@ -58,7 +58,7 @@ static int send_file(THD *thd) // the job old_timeout = thd->net.timeout; thd->net.timeout = thd->inactive_timeout; - + // we need net_flush here because the client will not know it needs to send // us the file name until it has processed the load event entry if (net_flush(net) || (packet_len = my_net_read(net)) == packet_error) @@ -67,16 +67,16 @@ static int send_file(THD *thd) goto err; } - fn_format(fname, (char*)net->read_pos + 1, "", "", 4); + fn_format(fname, (char*)net->read_pos + 1, "", "", 4); if(!strcmp(fname,"/dev/null")) goto end; // this is needed to make replicate-ignore-db // work on the well-known system that does not have a /dev/null :-) - + if ((fd = my_open(fname, O_RDONLY, MYF(MY_WME))) < 0) { errmsg = "Failed on my_open()"; goto err; } - + while ((bytes = (int) my_read(fd, (byte*) buf, sizeof(buf), MYF(MY_WME))) > 0) { @@ -87,7 +87,7 @@ static int send_file(THD *thd) } } - end: + end: if (my_net_write(net, "", 0) || net_flush(net) || (my_net_read(net) == packet_error)) { @@ -95,7 +95,7 @@ static int send_file(THD *thd) goto err; } error = 0; - + err: thd->net.timeout = old_timeout; if(fd >= 0) @@ -104,7 +104,7 @@ static int send_file(THD *thd) { sql_print_error("failed in send_file() : %s", errmsg); DBUG_PRINT("error", (errmsg)); - } + } DBUG_RETURN(error); } @@ -195,12 +195,12 @@ void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags) errmsg = "Binary log is not open"; goto err; } - + if(log_ident[0]) mysql_bin_log.make_log_name(search_file_name, log_ident); else search_file_name[0] = 0; - + if(mysql_bin_log.find_first_log(&linfo, search_file_name)) { errmsg = "Could not find first log"; @@ -219,8 +219,8 @@ void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags) errmsg = "Error on fseek()"; goto err; } - - + + packet->length(0); packet->append("\0", 1); // we need to start a packet with something other than 255 // to distiquish it from error @@ -251,7 +251,7 @@ void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags) errmsg = "error reading log event"; goto err; } - + if(!(flags & BINLOG_DUMP_NON_BLOCK) && mysql_bin_log.is_active(log_file_name)) // block until there is more data in the log // unless non-blocking mode requested @@ -267,10 +267,10 @@ void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags) // if we did not miss anything, we just wait for other threads // to signal us { - pthread_mutex_t *log_lock = mysql_bin_log.get_log_lock(); + pthread_mutex_t *log_lock = mysql_bin_log.get_log_lock(); clearerr(log); - - // tell the kill thread how to wake us up + + // tell the kill thread how to wake us up pthread_mutex_lock(&thd->mysys_var->mutex); thd->mysys_var->current_mutex = log_lock; thd->mysys_var->current_cond = &COND_binlog_update; @@ -283,7 +283,7 @@ void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags) pthread_mutex_lock(log_lock); // no one will update the log while we are reading // now, but we'll be quick and just read one record - + switch(Log_event::read_log_event(log, packet)) { case 0: @@ -300,7 +300,7 @@ void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags) } pthread_mutex_unlock(log_lock); - + pthread_mutex_lock(&thd->mysys_var->mutex); thd->mysys_var->current_mutex= 0; thd->mysys_var->current_cond= 0; @@ -314,7 +314,7 @@ void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags) errmsg = "Failed on my_net_write()"; goto err; } - + if((*packet)[LOG_EVENT_OFFSET+1] == LOAD_EVENT) { if(send_file(thd)) @@ -334,14 +334,14 @@ void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags) errmsg = "error reading log entry"; goto err; } - + clearerr(log); } } else { bool loop_breaker = 0; // need this to break out of the for loop from switch - + switch(mysql_bin_log.find_next_log(&linfo)) { case LOG_INFO_EOF: @@ -367,12 +367,12 @@ void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags) char header[9]; memset(header, 0, 4); // when does not matter header[4] = ROTATE_EVENT; - char* p = strrchr(log_file_name, FN_LIBCHAR); // find the last slash + char* p = strrchr(log_file_name, FN_LIBCHAR); // find the last slash if(p) p++; else p = log_file_name; - + uint ident_len = (uint) strlen(p); ulong event_len = ident_len + sizeof(header); int4store(header + 5, event_len); @@ -388,9 +388,9 @@ void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags) } } } - + (void)my_fclose(log, MYF(MY_WME)); - + send_eof(&thd->net); DBUG_VOID_RETURN; err: @@ -646,7 +646,7 @@ void close_thread_tables(THD *thd, bool locked) VOID(pthread_mutex_lock(&LOCK_open)); DBUG_PRINT("info", ("thd->open_tables=%p", thd->open_tables)); - + for (table=thd->open_tables ; table ; table=next) { next=table->next; @@ -820,7 +820,7 @@ TABLE *unlink_open_table(THD *thd, TABLE *list, TABLE *find) } -/* +/* When we call the following function we must have a lock on LOCK_OPEN ; This lock will be unlocked on return. */ @@ -957,7 +957,7 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name, { MEM_ROOT* glob_alloc; LINT_INIT(glob_alloc); - + if(errno == ENOENT && (glob_alloc = my_pthread_getspecific_ptr(MEM_ROOT*,THR_MALLOC))) // Sasha: needed for replication @@ -1288,7 +1288,7 @@ bool wait_for_tables(THD *thd) while (table_is_used(thd->open_tables) && ! thd->killed) { - (void) pthread_cond_wait(&COND_refresh,&LOCK_open); + (void) pthread_cond_wait(&COND_refresh,&LOCK_open); } if (thd->killed) @@ -1298,7 +1298,7 @@ bool wait_for_tables(THD *thd) /* Now we can open all tables without any interference */ thd->proc_info="Reopen tables"; result=reopen_tables(thd,0,0); - } + } pthread_mutex_unlock(&LOCK_open); thd->proc_info=0; DBUG_RETURN(result); @@ -1744,7 +1744,7 @@ find_item_in_list(Item *find,List<Item> &items) } } } - else if (!table_name && (item->eq(find) || + else if (!table_name && (item->eq(find) || find->name && !my_strcasecmp(item->name,find->name))) { @@ -1824,7 +1824,7 @@ int setup_fields(THD *thd, TABLE_LIST *tables, List<Item> &fields, } DBUG_RETURN(test(thd->fatal_error)); } - + static key_map get_key_map_from_key_list(THD *thd, TABLE *table, List<String> *index_list) @@ -2172,18 +2172,22 @@ bool remove_table_from_cache(THD *thd, const char *db,const char *table_name) DBUG_RETURN(result); } -/* - Will be used for ft-query optimization someday. - SerG. - */ int setup_ftfuncs(THD *thd,TABLE_LIST *tables, List<Item_func_match> &ftfuncs) { - List_iterator<Item_func_match> li(ftfuncs); - Item_func_match *ftf; + List_iterator<Item_func_match> li(ftfuncs), li2(ftfuncs); + Item_func_match *ftf, *ftf2; while ((ftf=li++)) + { if (ftf->fix_index()) return 1; + li2.rewind(); + while ((ftf2=li2++) != ftf) + { + if (ftf->eq(ftf2) && !ftf2->master) + ftf2->master=ftf; + } + } return 0; } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index c779b9f555a..6578e3b717a 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1284,11 +1284,11 @@ add_ft_keys(DYNAMIC_ARRAY *keyuse_array, KEYUSE keyuse; keyuse.table= cond_func->table; - keyuse.val = cond_func->key_item(); + keyuse.val = cond_func; keyuse.key = cond_func->key; #define FT_KEYPART (MAX_REF_PARTS+10) keyuse.keypart=FT_KEYPART; - keyuse.used_tables=keyuse.val->used_tables(); + keyuse.used_tables=cond_func->key_item()->used_tables(); VOID(insert_dynamic(keyuse_array,(gptr) &keyuse)); } @@ -1670,7 +1670,7 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count, else tmp=best_time; // Do nothing } - } /* not ftkey */ + } /* not ft_key */ if (tmp < best_time - records/(double) TIME_FOR_COMPARE) { best_time=tmp + records/(double) TIME_FOR_COMPARE; @@ -1882,26 +1882,29 @@ get_best_combination(JOIN *join) keyinfo=table->key_info+key; if (ftkey) { - ft_tmp=keyuse->val->val_str(&tmp2); + Item_func_match *ifm=(Item_func_match *)keyuse->val; + + ft_tmp=ifm->key_item()->val_str(&tmp2); length=ft_tmp->length(); keyparts=1; + ifm->join_key=1; } else { - keyparts=length=0; - do - { - if (!((~used_tables) & keyuse->used_tables)) - { - if (keyparts == keyuse->keypart) - { - keyparts++; - length+=keyinfo->key_part[keyuse->keypart].length + - test(keyinfo->key_part[keyuse->keypart].null_bit); - } - } - keyuse++; - } while (keyuse->table == table && keyuse->key == key); + keyparts=length=0; + do + { + if (!((~used_tables) & keyuse->used_tables)) + { + if (keyparts == keyuse->keypart) + { + keyparts++; + length+=keyinfo->key_part[keyuse->keypart].length + + test(keyinfo->key_part[keyuse->keypart].null_bit); + } + } + keyuse++; + } while (keyuse->table == table && keyuse->key == key); } /* not ftkey */ /* set up fieldref */ @@ -1924,7 +1927,7 @@ get_best_combination(JOIN *join) byte *key_buff=j->ref.key_buff; if (ftkey) { - j->ref.items[0]=keyuse->val; + j->ref.items[0]=((Item_func*)(keyuse->val))->key_item(); if (!keyuse->used_tables && !(join->select_options & SELECT_DESCRIBE)) { diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index b39299a54e6..a79531535c7 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -137,7 +137,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token CHANGED_FILES %token CHECKSUM_SYM %token CHECK_SYM -%token COLLECTION %token COLUMNS %token COLUMN_SYM %token CONSTRAINT @@ -162,6 +161,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token FOREIGN %token FROM %token FULL +%token FULLTEXT_SYM %token GRANT %token GRANTS %token GREATEST_SYM @@ -457,7 +457,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); expr_list udf_expr_list when_list ident_list %type <key_type> - key_type opt_unique + key_type opt_unique_or_fulltext %type <string_list> key_usage_list @@ -628,7 +628,7 @@ create: } create2 - | CREATE opt_unique INDEX ident ON table_ident + | CREATE opt_unique_or_fulltext INDEX ident ON table_ident { Lex->sql_command= SQLCOM_CREATE_INDEX; if (!add_table_to_list($6,NULL)) @@ -643,21 +643,6 @@ create: Lex->key_list.push_back(new Key($2,$4.str,Lex->col_list)); Lex->col_list.empty(); } - | CREATE COLLECTION ident ON table_ident - { - Lex->sql_command= SQLCOM_CREATE_INDEX; - if (!add_table_to_list($5,NULL)) - YYABORT; - Lex->create_list.empty(); - Lex->key_list.empty(); - Lex->col_list.empty(); - Lex->change=NullS; - } - '(' key_list ')' - { - Lex->key_list.push_back(new Key(Key::FULLTEXT,$3.str,Lex->col_list)); - Lex->col_list.empty(); - } | CREATE DATABASE opt_if_not_exists ident { Lex->sql_command=SQLCOM_CREATE_DB; @@ -964,7 +949,8 @@ delete_option: key_type: opt_constraint PRIMARY_SYM KEY_SYM { $$= Key::PRIMARY; } | key_or_index { $$= Key::MULTIPLE; } - | COLLECTION { $$= Key::FULLTEXT; } + | FULLTEXT_SYM { $$= Key::FULLTEXT; } + | FULLTEXT_SYM key_or_index { $$= Key::FULLTEXT; } | opt_constraint UNIQUE_SYM { $$= Key::UNIQUE; } | opt_constraint UNIQUE_SYM key_or_index { $$= Key::UNIQUE; } @@ -976,9 +962,10 @@ keys_or_index: KEYS {} | INDEX {} -opt_unique: +opt_unique_or_fulltext: /* empty */ { $$= Key::MULTIPLE; } | UNIQUE_SYM { $$= Key::UNIQUE; } + | FULLTEXT_SYM { $$= Key::FULLTEXT; } key_list: key_list ',' key_part order_dir { Lex->col_list.push_back($3); } @@ -2443,7 +2430,6 @@ keyword: | WORK_SYM {} | YEAR_SYM {} | SLAVE {} - | COLLECTION {} /* Option functions */ |