summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorserg@infomag.ape.relarn.ru <>2000-08-28 17:43:58 +0400
committerserg@infomag.ape.relarn.ru <>2000-08-28 17:43:58 +0400
commiteb8ad15751606cf9203caff2515ac868dd03c8d0 (patch)
tree485c3b99b43fae8c2b58b7a5ab72b383265423d2
parent6236dfc7a34cd528b5d11fad4ce32d230720ce44 (diff)
downloadmariadb-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.texi84
-rw-r--r--myisam/ft_search.c7
-rw-r--r--myisam/mi_check.c20
-rw-r--r--sql/item_func.cc69
-rw-r--r--sql/item_func.h21
-rw-r--r--sql/lex.h24
-rw-r--r--sql/sql_base.cc84
-rw-r--r--sql/sql_select.cc41
-rw-r--r--sql/sql_yacc.yy28
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 */