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.
parent 6236dfc7
...@@ -11670,7 +11670,6 @@ to restart @code{mysqld} with @code{--skip-grant-tables} to be able to run ...@@ -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 * GRANT:: @code{GRANT} and @code{REVOKE} syntax
* CREATE INDEX:: @code{CREATE INDEX} syntax * CREATE INDEX:: @code{CREATE INDEX} syntax
* DROP INDEX:: @code{DROP INDEX} syntax * DROP INDEX:: @code{DROP INDEX} syntax
* CREATE COLLECTION:: @code{CREATE COLLECTION} syntax
* Comments:: Comment syntax * Comments:: Comment syntax
* CREATE FUNCTION:: @code{CREATE FUNCTION} syntax * CREATE FUNCTION:: @code{CREATE FUNCTION} syntax
* Reserved words:: Is @strong{MySQL} picky about reserved words? * Reserved words:: Is @strong{MySQL} picky about reserved words?
...@@ -13436,9 +13435,9 @@ mysql> CREATE TABLE test ( ...@@ -13436,9 +13435,9 @@ mysql> CREATE TABLE test (
For @code{BLOB} and @code{TEXT} columns, you must index a prefix of the For @code{BLOB} and @code{TEXT} columns, you must index a prefix of the
column, you cannot index the entire thing. column, you cannot index the entire thing.
In @strong{MySQL} 3.23.23 or later, you can also create special indexes In @strong{MySQL} 3.23.23 or later, you can also create special
called @strong{collections}. They are used for full-text search. Only @strong{fulltext} indexes. They are used for full-text search. Only
@code{MyISAM} table type supports collections. Collection can be created @code{MyISAM} table type supports fulltext indexes. They can be created
only from @code{VARCHAR}, @code{BLOB}, and @code{TEXT} columns. only from @code{VARCHAR}, @code{BLOB}, and @code{TEXT} columns.
Indexing always happens over the entire column, partial indexing is not Indexing always happens over the entire column, partial indexing is not
supported. See @ref{MySQL full-text search} for details of operation. supported. See @ref{MySQL full-text search} for details of operation.
...@@ -14165,7 +14164,7 @@ mysql> select STRCMP('text', 'text'); ...@@ -14165,7 +14164,7 @@ mysql> select STRCMP('text', 'text');
relevance - similarity measure between the text in columns relevance - similarity measure between the text in columns
@code{(col1,col2,...)} and the query @code{expr}. Relevance is a @code{(col1,col2,...)} and the query @code{expr}. Relevance is a
positive floating point number. Zero relevance means no similarity. 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}}. must be created first. @xref{CREATE TABLE, , @code{CREATE TABLE}}.
@code{MATCH ... AGAINST()} is available in @code{MySQL} 3.23.23 or later. @code{MATCH ... AGAINST()} is available in @code{MySQL} 3.23.23 or later.
For details and usage examples see @xref{MySQL full-text search}. For details and usage examples see @xref{MySQL full-text search}.
...@@ -16178,7 +16177,7 @@ create_definition: ...@@ -16178,7 +16177,7 @@ create_definition:
or KEY [index_name] (index_col_name,...) or KEY [index_name] (index_col_name,...)
or INDEX [index_name] (index_col_name,...) or INDEX [index_name] (index_col_name,...)
or UNIQUE [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,...) or [CONSTRAINT symbol] FOREIGN KEY index_name (index_col_name,...)
[reference_definition] [reference_definition]
or CHECK (expr) or CHECK (expr)
...@@ -16422,10 +16421,10 @@ When you use @code{ORDER BY} or @code{GROUP BY} with a @code{TEXT} or ...@@ -16422,10 +16421,10 @@ When you use @code{ORDER BY} or @code{GROUP BY} with a @code{TEXT} or
@xref{BLOB, , @code{BLOB}}. @xref{BLOB, , @code{BLOB}}.
@item @item
In @strong{MySQL} 3.23.23 or later, you can also create special indexes In @strong{MySQL} 3.23.23 or later, you can also create special
called @strong{collections}. They are used for full-text search. Only @strong{fulltext} indexes. They are used for full-text search. Only
@code{MyISAM} table type supports collections. Collection can be created @code{MyISAM} table type supports fulltext indexes. They can be created
from any mix of @code{VARCHAR}, @code{BLOB}, and @code{TEXT} columns. only from @code{VARCHAR}, @code{BLOB}, and @code{TEXT} columns.
Indexing always happens over the entire column, partial indexing is not Indexing always happens over the entire column, partial indexing is not
supported. See @ref{MySQL full-text search} for details of operation. supported. See @ref{MySQL full-text search} for details of operation.
...@@ -16598,7 +16597,7 @@ alter_specification: ...@@ -16598,7 +16597,7 @@ alter_specification:
or ADD INDEX [index_name] (index_col_name,...) or ADD INDEX [index_name] (index_col_name,...)
or ADD PRIMARY KEY (index_col_name,...) or ADD PRIMARY KEY (index_col_name,...)
or ADD UNIQUE [index_name] (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 ALTER [COLUMN] col_name @{SET DEFAULT literal | DROP DEFAULT@}
or CHANGE [COLUMN] old_col_name create_definition or CHANGE [COLUMN] old_col_name create_definition
or MODIFY [COLUMN] create_definition or MODIFY [COLUMN] create_definition
...@@ -19769,7 +19768,7 @@ dropped only with explicit @code{REVOKE} commands or by manipulating the ...@@ -19769,7 +19768,7 @@ dropped only with explicit @code{REVOKE} commands or by manipulating the
@section @code{CREATE INDEX} syntax @section @code{CREATE INDEX} syntax
@example @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 @end example
The @code{CREATE INDEX} statement doesn't do anything in @strong{MySQL} prior 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} ...@@ -19803,15 +19802,19 @@ which could save a lot of disk space and might also speed up @code{INSERT}
operations! operations!
Note that you can only add an index on a column that can have @code{NULL} 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} @strong{MySQL} version 3.23.2 or newer and are using the @code{MyISAM}
table type. table type.
For more information about how @strong{MySQL} uses indexes, see For more information about how @strong{MySQL} uses indexes, see
@ref{MySQL indexes, , @strong{MySQL} indexes}. @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 @findex DROP INDEX
@node DROP INDEX, CREATE COLLECTION, CREATE INDEX, Reference @node DROP INDEX, Comments, CREATE INDEX, Reference
@section @code{DROP INDEX} syntax @section @code{DROP INDEX} syntax
@example @example
...@@ -19824,30 +19827,8 @@ prior to version 3.22. In 3.22 or later, @code{DROP INDEX} is mapped to an ...@@ -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. @code{ALTER TABLE} statement to drop the index.
@xref{ALTER TABLE, , @code{ALTER TABLE}}. @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 @findex Comment syntax
@node Comments, CREATE FUNCTION, CREATE COLLECTION, Reference @node Comments, CREATE FUNCTION, DROP INDEX, Reference
@section Comment syntax @section Comment syntax
The @strong{MySQL} server supports the @code{# to end of line}, @code{-- The @strong{MySQL} server supports the @code{# to end of line}, @code{--
...@@ -34106,14 +34087,14 @@ DELAYED} threads. ...@@ -34106,14 +34087,14 @@ DELAYED} threads.
@section MySQL full-text search @section MySQL full-text search
Since version 3.23.23, @strong{MySQL} has support for full-text indexing 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 and searching. Full-text index in @strong{MySQL} is an
called @strong{collection}. Collections can be created from @code{VARCHAR}, index of type @code{FULLTEXT}. Fulltext indexes can be created from
@code{TEXT}, and @code{BLOB} columns at @code{CREATE TABLE} @code{VARCHAR}, @code{TEXT}, and @code{BLOB} columns at
time or added later with @code{ALTER TABLE} or @code{CREATE COLLECTION}. @code{CREATE TABLE} time or added later with @code{ALTER TABLE} or
Collection is queried with @code{MATCH} function. @code{CREATE INDEX}. Full-text search is performed with @code{MATCH} function.
@example @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) Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO t VALUES mysql> INSERT INTO t VALUES
-> ('MySQL has now support', 'for full-text search'), -> ('MySQL has now support', 'for full-text search'),
...@@ -34145,15 +34126,16 @@ mysql> SELECT *,MATCH a,b AGAINST ('collections support') as x FROM t; ...@@ -34145,15 +34126,16 @@ mysql> SELECT *,MATCH a,b AGAINST ('collections support') as x FROM t;
@end example @end example
Function @code{MATCH} matches a natural language query @code{AGAINST} a 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 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} are part of the collection) and the query. When it used in a
clause (see example above) the rows returned are automatically sorted @code{WHERE} clause (see example above) the rows returned are
with relevance decreasing. Relevance is a non-negative floating point automatically sorted with relevance decreasing. Relevance is a non-
number. Zero relevance means no similarity. Relevance is computed based negative floating point number. Zero relevance means no similarity.
on number of words in the row and number of unique words in that row, Relevance is computed based on number of words in the row and number of
total number of words in the collection, number of documents (rows), unique words in that row, total number of words in the collection,
that contain a particular word, etc. number of documents (rows), that contain a particular word, etc.
MySQL uses very simple parser to split text into words. "Word" is MySQL uses very simple parser to split text into words. "Word" is
any sequence of letters, numbers, @code{'}, and @code{_}. Any "word" any sequence of letters, numbers, @code{'}, and @code{_}. Any "word"
...@@ -158,6 +158,7 @@ FT_DOCLIST * ft_init_search(void *info, uint keynr, byte *key, ...@@ -158,6 +158,7 @@ FT_DOCLIST * ft_init_search(void *info, uint keynr, byte *key,
ALL_IN_ONE aio; ALL_IN_ONE aio;
FT_DOCLIST *dlist; FT_DOCLIST *dlist;
FT_DOC *dptr; FT_DOC *dptr;
my_off_t saved_lastpos;
/* black magic ON */ /* black magic ON */
if ((int) (keynr = _mi_check_index((MI_INFO *)info,keynr)) < 0) 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, ...@@ -173,6 +174,8 @@ FT_DOCLIST * ft_init_search(void *info, uint keynr, byte *key,
aio.keyinfo=aio.info->s->keyinfo+keynr; aio.keyinfo=aio.info->s->keyinfo+keynr;
aio.key_root=aio.info->s->state.key_root[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; if(!(wtree=ft_parse(NULL,key,key_len))) return NULL;
init_tree(&aio.dtree,0,sizeof(FT_SUPERDOC),(qsort_cmp)&FT_SUPERDOC_cmp,0, 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, ...@@ -199,6 +202,7 @@ FT_DOCLIST * ft_init_search(void *info, uint keynr, byte *key,
} }
err: err:
aio.info->lastpos=saved_lastpos;
delete_tree(&aio.dtree); delete_tree(&aio.dtree);
delete_tree(wtree); delete_tree(wtree);
free(wtree); free(wtree);
...@@ -217,7 +221,8 @@ int ft_read_next(FT_DOCLIST *handler, char *record) ...@@ -217,7 +221,8 @@ int ft_read_next(FT_DOCLIST *handler, char *record)
info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); 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 */ info->update|= HA_STATE_AKTIV; /* Record is read */
return 0; return 0;
......
...@@ -1141,7 +1141,13 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info, ...@@ -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++) for (i=0 ; i < share->state.header.max_block_size ; i++)
share->state.key_del[i]= HA_OFFSET_ERROR; 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; info->state->key_file_length=share->base.keystart;
...@@ -1935,6 +1941,11 @@ static int sort_key_read(SORT_INFO *sort_info, void *key) ...@@ -1935,6 +1941,11 @@ static int sort_key_read(SORT_INFO *sort_info, void *key)
"Found too many records; Can`t continue"); "Found too many records; Can`t continue");
DBUG_RETURN(1); 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 ) if (sort_info->keyinfo->flag & HA_FULLTEXT )
{ {
mi_check_print_error(sort_info->param, mi_check_print_error(sort_info->param,
...@@ -3009,6 +3020,13 @@ my_bool mi_test_if_sort_rep(MI_INFO *info, ha_rows rows) ...@@ -3009,6 +3020,13 @@ my_bool mi_test_if_sort_rep(MI_INFO *info, ha_rows rows)
return FALSE; /* Can't use sort */ return FALSE; /* Can't use sort */
for (i=0 ; i < share->base.keys ; i++,key++) 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)) if (mi_too_big_key_for_sort(key,rows) || (key->flag & HA_FULLTEXT))
return FALSE; return FALSE;
} }
......
...@@ -1837,26 +1837,8 @@ err: ...@@ -1837,26 +1837,8 @@ err:
double Item_func_match::val() double Item_func_match::val()
{ {
my_off_t docid=table->file->row_position(); // HAVE to do it here...
if (first_call) if (first_call)
{ init_search();
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;
}
// Don't know how to return an error from val(), so NULL will be returned // Don't know how to return an error from val(), so NULL will be returned
if ((null_value=(ft_handler==NULL))) if ((null_value=(ft_handler==NULL)))
...@@ -1873,6 +1855,7 @@ double Item_func_match::val() ...@@ -1873,6 +1855,7 @@ double Item_func_match::val()
int a,b,c; int a,b,c;
FT_DOC *docs=ft_handler->doc; FT_DOC *docs=ft_handler->doc;
my_off_t docid=table->file->row_position();
if ((null_value=(docid==HA_OFFSET_ERROR))) if ((null_value=(docid==HA_OFFSET_ERROR)))
return 0.0; return 0.0;
...@@ -1893,6 +1876,36 @@ double Item_func_match::val() ...@@ -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) bool Item_func_match::fix_fields(THD *thd,struct st_table_list *tlist)
{ {
List_iterator<Item> li(fields); List_iterator<Item> li(fields);
...@@ -1982,6 +1995,24 @@ bool Item_func_match::fix_index() ...@@ -1982,6 +1995,24 @@ bool Item_func_match::fix_index()
this->key=max_key; this->key=max_key;
first_call=1; first_call=1;
maybe_null=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; return 0;
} }
......
...@@ -839,19 +839,28 @@ public: ...@@ -839,19 +839,28 @@ public:
TABLE *table; TABLE *table;
uint key; uint key;
bool first_call, join_key; bool first_call, join_key;
Item_func_match *master;
FT_DOCLIST *ft_handler; FT_DOCLIST *ft_handler;
Item_func_match(List<Item> &a, Item *b): Item_real_func(b), Item_func_match(List<Item> &a, Item *b): Item_real_func(b),
fields(a), table(0), ft_handler(0) fields(a), table(0), ft_handler(0), master(0) {}
{} ~Item_func_match()
~Item_func_match() { ft_close_search(ft_handler); {
if(join_key) table->file->ft_handler=0; } if (!master)
{
ft_close_search(ft_handler);
if(join_key)
table->file->ft_handler=0;
}
}
const char *func_name() const { return "match"; } const char *func_name() const { return "match"; }
enum Functype functype() const { return FT_FUNC; } enum Functype functype() const { return FT_FUNC; }
void update_used_tables() {} void update_used_tables() {}
bool fix_fields(THD *thd,struct st_table_list *tlist); bool fix_fields(THD *thd,struct st_table_list *tlist);
bool fix_index(); bool eq(const Item *) const;
double val(); double val();
longlong val_int() { return val()!=0.0; } longlong val_int() { return val()!=0.0; }
bool fix_index();
void init_search();
}; };
/* 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 */
...@@ -81,7 +81,6 @@ static SYMBOL symbols[] = { ...@@ -81,7 +81,6 @@ static SYMBOL symbols[] = {
{ "CHANGED", SYM(CHANGED),0,0}, { "CHANGED", SYM(CHANGED),0,0},
{ "CHECK", SYM(CHECK_SYM),0,0}, { "CHECK", SYM(CHECK_SYM),0,0},
{ "CHECKSUM", SYM(CHECKSUM_SYM),0,0}, { "CHECKSUM", SYM(CHECKSUM_SYM),0,0},
{ "COLLECTION", SYM(COLLECTION),0,0},
{ "COLUMN", SYM(COLUMN_SYM),0,0}, { "COLUMN", SYM(COLUMN_SYM),0,0},
{ "COLUMNS", SYM(COLUMNS),0,0}, { "COLUMNS", SYM(COLUMNS),0,0},
{ "COMMENT", SYM(COMMENT_SYM),0,0}, { "COMMENT", SYM(COMMENT_SYM),0,0},
...@@ -142,6 +141,7 @@ static SYMBOL symbols[] = { ...@@ -142,6 +141,7 @@ static SYMBOL symbols[] = {
{ "FROM", SYM(FROM),0,0}, { "FROM", SYM(FROM),0,0},
{ "FOR", SYM(FOR_SYM),0,0}, { "FOR", SYM(FOR_SYM),0,0},
{ "FULL", SYM(FULL),0,0}, { "FULL", SYM(FULL),0,0},
{ "FULLTEXT", SYM(FULLTEXT_SYM),0,0},
{ "FUNCTION", SYM(UDF_SYM),0,0}, { "FUNCTION", SYM(UDF_SYM),0,0},
{ "GRANT", SYM(GRANT),0,0}, { "GRANT", SYM(GRANT),0,0},
{ "GRANTS", SYM(GRANTS),0,0}, { "GRANTS", SYM(GRANTS),0,0},
...@@ -191,14 +191,14 @@ static SYMBOL symbols[] = { ...@@ -191,14 +191,14 @@ static SYMBOL symbols[] = {
{ "LONGBLOB", SYM(LONGBLOB),0,0}, { "LONGBLOB", SYM(LONGBLOB),0,0},
{ "LONGTEXT", SYM(LONGTEXT),0,0}, { "LONGTEXT", SYM(LONGTEXT),0,0},
{ "LOW_PRIORITY", SYM(LOW_PRIORITY),0,0}, { "LOW_PRIORITY", SYM(LOW_PRIORITY),0,0},
{ "MASTER", SYM(MASTER_SYM),0,0}, { "MASTER", SYM(MASTER_SYM),0,0},
{ "MASTER_CONNECT_RETRY", SYM(MASTER_CONNECT_RETRY_SYM),0,0}, { "MASTER_CONNECT_RETRY", SYM(MASTER_CONNECT_RETRY_SYM),0,0},
{ "MASTER_HOST", SYM(MASTER_HOST_SYM),0,0}, { "MASTER_HOST", SYM(MASTER_HOST_SYM),0,0},
{ "MASTER_LOG_FILE", SYM(MASTER_LOG_FILE_SYM),0,0}, { "MASTER_LOG_FILE", SYM(MASTER_LOG_FILE_SYM),0,0},
{ "MASTER_LOG_POS", SYM(MASTER_LOG_POS_SYM),0,0}, { "MASTER_LOG_POS", SYM(MASTER_LOG_POS_SYM),0,0},
{ "MASTER_PASSWORD", SYM(MASTER_PASSWORD_SYM),0,0}, { "MASTER_PASSWORD", SYM(MASTER_PASSWORD_SYM),0,0},
{ "MASTER_PORT", SYM(MASTER_PORT_SYM),0,0}, { "MASTER_PORT", SYM(MASTER_PORT_SYM),0,0},
{ "MASTER_USER", SYM(MASTER_USER_SYM),0,0}, { "MASTER_USER", SYM(MASTER_USER_SYM),0,0},
{ "MAX_ROWS", SYM(MAX_ROWS),0,0}, { "MAX_ROWS", SYM(MAX_ROWS),0,0},
{ "MATCH", SYM(MATCH),0,0}, { "MATCH", SYM(MATCH),0,0},
{ "MEDIUMBLOB", SYM(MEDIUMBLOB),0,0}, { "MEDIUMBLOB", SYM(MEDIUMBLOB),0,0},
......
/* 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 */
...@@ -58,7 +58,7 @@ static int send_file(THD *thd) ...@@ -58,7 +58,7 @@ static int send_file(THD *thd)
// the job // the job
old_timeout = thd->net.timeout; old_timeout = thd->net.timeout;
thd->net.timeout = thd->inactive_timeout; thd->net.timeout = thd->inactive_timeout;
// we need net_flush here because the client will not know it needs to send // 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 // us the file name until it has processed the load event entry
if (net_flush(net) || (packet_len = my_net_read(net)) == packet_error) if (net_flush(net) || (packet_len = my_net_read(net)) == packet_error)
...@@ -67,16 +67,16 @@ static int send_file(THD *thd) ...@@ -67,16 +67,16 @@ static int send_file(THD *thd)
goto err; 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 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 :-) // work on the well-known system that does not have a /dev/null :-)
if ((fd = my_open(fname, O_RDONLY, MYF(MY_WME))) < 0) if ((fd = my_open(fname, O_RDONLY, MYF(MY_WME))) < 0)
{ {
errmsg = "Failed on my_open()"; errmsg = "Failed on my_open()";
goto err; goto err;
} }
while ((bytes = (int) my_read(fd, (byte*) buf, sizeof(buf), while ((bytes = (int) my_read(fd, (byte*) buf, sizeof(buf),
MYF(MY_WME))) > 0) MYF(MY_WME))) > 0)
{ {
...@@ -87,7 +87,7 @@ static int send_file(THD *thd) ...@@ -87,7 +87,7 @@ static int send_file(THD *thd)
} }
} }
end: end:
if (my_net_write(net, "", 0) || net_flush(net) || if (my_net_write(net, "", 0) || net_flush(net) ||
(my_net_read(net) == packet_error)) (my_net_read(net) == packet_error))
{ {
...@@ -95,7 +95,7 @@ static int send_file(THD *thd) ...@@ -95,7 +95,7 @@ static int send_file(THD *thd)
goto err; goto err;
} }
error = 0; error = 0;
err: err:
thd->net.timeout = old_timeout; thd->net.timeout = old_timeout;
if(fd >= 0) if(fd >= 0)
...@@ -104,7 +104,7 @@ static int send_file(THD *thd) ...@@ -104,7 +104,7 @@ static int send_file(THD *thd)
{ {
sql_print_error("failed in send_file() : %s", errmsg); sql_print_error("failed in send_file() : %s", errmsg);
DBUG_PRINT("error", (errmsg)); DBUG_PRINT("error", (errmsg));
} }
DBUG_RETURN(error); DBUG_RETURN(error);
} }
...@@ -195,12 +195,12 @@ void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags) ...@@ -195,12 +195,12 @@ void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags)
errmsg = "Binary log is not open"; errmsg = "Binary log is not open";
goto err; goto err;
} }
if(log_ident[0]) if(log_ident[0])
mysql_bin_log.make_log_name(search_file_name, log_ident); mysql_bin_log.make_log_name(search_file_name, log_ident);
else else
search_file_name[0] = 0; search_file_name[0] = 0;
if(mysql_bin_log.find_first_log(&linfo, search_file_name)) if(mysql_bin_log.find_first_log(&linfo, search_file_name))
{ {
errmsg = "Could not find first log"; errmsg = "Could not find first log";
...@@ -219,8 +219,8 @@ void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags) ...@@ -219,8 +219,8 @@ void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags)
errmsg = "Error on fseek()"; errmsg = "Error on fseek()";
goto err; goto err;
} }
packet->length(0); packet->length(0);
packet->append("\0", 1); // we need to start a packet with something other than 255 packet->append("\0", 1); // we need to start a packet with something other than 255
// to distiquish it from error // to distiquish it from error
...@@ -251,7 +251,7 @@ void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags) ...@@ -251,7 +251,7 @@ void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags)
errmsg = "error reading log event"; errmsg = "error reading log event";
goto err; goto err;
} }
if(!(flags & BINLOG_DUMP_NON_BLOCK) && mysql_bin_log.is_active(log_file_name)) if(!(flags & BINLOG_DUMP_NON_BLOCK) && mysql_bin_log.is_active(log_file_name))
// block until there is more data in the log // block until there is more data in the log
// unless non-blocking mode requested // unless non-blocking mode requested
...@@ -267,10 +267,10 @@ void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags) ...@@ -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 // if we did not miss anything, we just wait for other threads
// to signal us // 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); 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); pthread_mutex_lock(&thd->mysys_var->mutex);
thd->mysys_var->current_mutex = log_lock; thd->mysys_var->current_mutex = log_lock;
thd->mysys_var->current_cond = &COND_binlog_update; 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) ...@@ -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 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 // now, but we'll be quick and just read one record
switch(Log_event::read_log_event(log, packet)) switch(Log_event::read_log_event(log, packet))
{ {
case 0: case 0:
...@@ -300,7 +300,7 @@ void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags) ...@@ -300,7 +300,7 @@ void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags)
} }
pthread_mutex_unlock(log_lock); pthread_mutex_unlock(log_lock);
pthread_mutex_lock(&thd->mysys_var->mutex); pthread_mutex_lock(&thd->mysys_var->mutex);
thd->mysys_var->current_mutex= 0; thd->mysys_var->current_mutex= 0;
thd->mysys_var->current_cond= 0; thd->mysys_var->current_cond= 0;
...@@ -314,7 +314,7 @@ void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags) ...@@ -314,7 +314,7 @@ void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags)
errmsg = "Failed on my_net_write()"; errmsg = "Failed on my_net_write()";
goto err; goto err;
} }
if((*packet)[LOG_EVENT_OFFSET+1] == LOAD_EVENT) if((*packet)[LOG_EVENT_OFFSET+1] == LOAD_EVENT)
{ {
if(send_file(thd)) if(send_file(thd))
...@@ -334,14 +334,14 @@ void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags) ...@@ -334,14 +334,14 @@ void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags)
errmsg = "error reading log entry"; errmsg = "error reading log entry";
goto err; goto err;
} }
clearerr(log); clearerr(log);
} }
} }
else else
{ {
bool loop_breaker = 0; // need this to break out of the for loop from switch bool loop_breaker = 0; // need this to break out of the for loop from switch
switch(mysql_bin_log.find_next_log(&linfo)) switch(mysql_bin_log.find_next_log(&linfo))
{ {
case LOG_INFO_EOF: case LOG_INFO_EOF:
...@@ -367,12 +367,12 @@ void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags) ...@@ -367,12 +367,12 @@ void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags)
char header[9]; char header[9];
memset(header, 0, 4); // when does not matter memset(header, 0, 4); // when does not matter
header[4] = ROTATE_EVENT; 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) if(p)
p++; p++;
else else
p = log_file_name; p = log_file_name;
uint ident_len = (uint) strlen(p); uint ident_len = (uint) strlen(p);
ulong event_len = ident_len + sizeof(header); ulong event_len = ident_len + sizeof(header);
int4store(header + 5, event_len); int4store(header + 5, event_len);
...@@ -388,9 +388,9 @@ void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags) ...@@ -388,9 +388,9 @@ void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags)
} }
} }
} }
(void)my_fclose(log, MYF(MY_WME)); (void)my_fclose(log, MYF(MY_WME));
send_eof(&thd->net); send_eof(&thd->net);
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
err: err:
...@@ -646,7 +646,7 @@ void close_thread_tables(THD *thd, bool locked) ...@@ -646,7 +646,7 @@ void close_thread_tables(THD *thd, bool locked)
VOID(pthread_mutex_lock(&LOCK_open)); VOID(pthread_mutex_lock(&LOCK_open));
DBUG_PRINT("info", ("thd->open_tables=%p", thd->open_tables)); DBUG_PRINT("info", ("thd->open_tables=%p", thd->open_tables));
for (table=thd->open_tables ; table ; table=next) for (table=thd->open_tables ; table ; table=next)
{ {
next=table->next; next=table->next;
...@@ -820,7 +820,7 @@ TABLE *unlink_open_table(THD *thd, TABLE *list, TABLE *find) ...@@ -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 When we call the following function we must have a lock on
LOCK_OPEN ; This lock will be unlocked on return. 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, ...@@ -957,7 +957,7 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name,
{ {
MEM_ROOT* glob_alloc; MEM_ROOT* glob_alloc;
LINT_INIT(glob_alloc); LINT_INIT(glob_alloc);
if(errno == ENOENT && if(errno == ENOENT &&
(glob_alloc = my_pthread_getspecific_ptr(MEM_ROOT*,THR_MALLOC))) (glob_alloc = my_pthread_getspecific_ptr(MEM_ROOT*,THR_MALLOC)))
// Sasha: needed for replication // Sasha: needed for replication
...@@ -1288,7 +1288,7 @@ bool wait_for_tables(THD *thd) ...@@ -1288,7 +1288,7 @@ bool wait_for_tables(THD *thd)
while (table_is_used(thd->open_tables) && ! thd->killed) 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) if (thd->killed)
...@@ -1298,7 +1298,7 @@ bool wait_for_tables(THD *thd) ...@@ -1298,7 +1298,7 @@ bool wait_for_tables(THD *thd)
/* Now we can open all tables without any interference */ /* Now we can open all tables without any interference */
thd->proc_info="Reopen tables"; thd->proc_info="Reopen tables";
result=reopen_tables(thd,0,0); result=reopen_tables(thd,0,0);
} }
pthread_mutex_unlock(&LOCK_open); pthread_mutex_unlock(&LOCK_open);
thd->proc_info=0; thd->proc_info=0;
DBUG_RETURN(result); DBUG_RETURN(result);
...@@ -1744,7 +1744,7 @@ find_item_in_list(Item *find,List<Item> &items) ...@@ -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 && find->name &&
!my_strcasecmp(item->name,find->name))) !my_strcasecmp(item->name,find->name)))
{ {
...@@ -1824,7 +1824,7 @@ int setup_fields(THD *thd, TABLE_LIST *tables, List<Item> &fields, ...@@ -1824,7 +1824,7 @@ int setup_fields(THD *thd, TABLE_LIST *tables, List<Item> &fields,
} }
DBUG_RETURN(test(thd->fatal_error)); DBUG_RETURN(test(thd->fatal_error));
} }
static key_map get_key_map_from_key_list(THD *thd, TABLE *table, static key_map get_key_map_from_key_list(THD *thd, TABLE *table,
List<String> *index_list) List<String> *index_list)
...@@ -2172,18 +2172,22 @@ bool remove_table_from_cache(THD *thd, const char *db,const char *table_name) ...@@ -2172,18 +2172,22 @@ bool remove_table_from_cache(THD *thd, const char *db,const char *table_name)
DBUG_RETURN(result); 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) int setup_ftfuncs(THD *thd,TABLE_LIST *tables, List<Item_func_match> &ftfuncs)
{ {
List_iterator<Item_func_match> li(ftfuncs); List_iterator<Item_func_match> li(ftfuncs), li2(ftfuncs);
Item_func_match *ftf; Item_func_match *ftf, *ftf2;
while ((ftf=li++)) while ((ftf=li++))
{
if (ftf->fix_index()) if (ftf->fix_index())
return 1; return 1;
li2.rewind();
while ((ftf2=li2++) != ftf)
{
if (ftf->eq(ftf2) && !ftf2->master)
ftf2->master=ftf;
}
}
return 0; return 0;
} }
...@@ -1284,11 +1284,11 @@ add_ft_keys(DYNAMIC_ARRAY *keyuse_array, ...@@ -1284,11 +1284,11 @@ add_ft_keys(DYNAMIC_ARRAY *keyuse_array,
KEYUSE keyuse; KEYUSE keyuse;
keyuse.table= cond_func->table; keyuse.table= cond_func->table;
keyuse.val = cond_func->key_item(); keyuse.val = cond_func;
keyuse.key = cond_func->key; keyuse.key = cond_func->key;
#define FT_KEYPART (MAX_REF_PARTS+10) #define FT_KEYPART (MAX_REF_PARTS+10)
keyuse.keypart=FT_KEYPART; 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)); VOID(insert_dynamic(keyuse_array,(gptr) &keyuse));
} }
...@@ -1670,7 +1670,7 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count, ...@@ -1670,7 +1670,7 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
else else
tmp=best_time; // Do nothing tmp=best_time; // Do nothing
} }
} /* not ftkey */ } /* not ft_key */
if (tmp < best_time - records/(double) TIME_FOR_COMPARE) if (tmp < best_time - records/(double) TIME_FOR_COMPARE)
{ {
best_time=tmp + records/(double) TIME_FOR_COMPARE; best_time=tmp + records/(double) TIME_FOR_COMPARE;
...@@ -1882,26 +1882,29 @@ get_best_combination(JOIN *join) ...@@ -1882,26 +1882,29 @@ get_best_combination(JOIN *join)
keyinfo=table->key_info+key; keyinfo=table->key_info+key;
if (ftkey) 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(); length=ft_tmp->length();
keyparts=1; keyparts=1;
ifm->join_key=1;
} }
else else
{ {
keyparts=length=0; keyparts=length=0;
do do
{ {
if (!((~used_tables) & keyuse->used_tables)) if (!((~used_tables) & keyuse->used_tables))
{ {
if (keyparts == keyuse->keypart) if (keyparts == keyuse->keypart)
{ {
keyparts++; keyparts++;
length+=keyinfo->key_part[keyuse->keypart].length + length+=keyinfo->key_part[keyuse->keypart].length +
test(keyinfo->key_part[keyuse->keypart].null_bit); test(keyinfo->key_part[keyuse->keypart].null_bit);
} }
} }
keyuse++; keyuse++;
} while (keyuse->table == table && keyuse->key == key); } while (keyuse->table == table && keyuse->key == key);
} /* not ftkey */ } /* not ftkey */
/* set up fieldref */ /* set up fieldref */
...@@ -1924,7 +1927,7 @@ get_best_combination(JOIN *join) ...@@ -1924,7 +1927,7 @@ get_best_combination(JOIN *join)
byte *key_buff=j->ref.key_buff; byte *key_buff=j->ref.key_buff;
if (ftkey) if (ftkey)
{ {
j->ref.items[0]=keyuse->val; j->ref.items[0]=((Item_func*)(keyuse->val))->key_item();
if (!keyuse->used_tables && if (!keyuse->used_tables &&
!(join->select_options & SELECT_DESCRIBE)) !(join->select_options & SELECT_DESCRIBE))
{ {
......
...@@ -137,7 +137,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); ...@@ -137,7 +137,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token CHANGED_FILES %token CHANGED_FILES
%token CHECKSUM_SYM %token CHECKSUM_SYM
%token CHECK_SYM %token CHECK_SYM
%token COLLECTION
%token COLUMNS %token COLUMNS
%token COLUMN_SYM %token COLUMN_SYM
%token CONSTRAINT %token CONSTRAINT
...@@ -162,6 +161,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); ...@@ -162,6 +161,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token FOREIGN %token FOREIGN
%token FROM %token FROM
%token FULL %token FULL
%token FULLTEXT_SYM
%token GRANT %token GRANT
%token GRANTS %token GRANTS
%token GREATEST_SYM %token GREATEST_SYM
...@@ -457,7 +457,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); ...@@ -457,7 +457,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
expr_list udf_expr_list when_list ident_list expr_list udf_expr_list when_list ident_list
%type <key_type> %type <key_type>
key_type opt_unique key_type opt_unique_or_fulltext
%type <string_list> %type <string_list>
key_usage_list key_usage_list
...@@ -628,7 +628,7 @@ create: ...@@ -628,7 +628,7 @@ create:
} }
create2 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; Lex->sql_command= SQLCOM_CREATE_INDEX;
if (!add_table_to_list($6,NULL)) if (!add_table_to_list($6,NULL))
...@@ -643,21 +643,6 @@ create: ...@@ -643,21 +643,6 @@ create:
Lex->key_list.push_back(new Key($2,$4.str,Lex->col_list)); Lex->key_list.push_back(new Key($2,$4.str,Lex->col_list));
Lex->col_list.empty(); 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 | CREATE DATABASE opt_if_not_exists ident
{ {
Lex->sql_command=SQLCOM_CREATE_DB; Lex->sql_command=SQLCOM_CREATE_DB;
...@@ -964,7 +949,8 @@ delete_option: ...@@ -964,7 +949,8 @@ delete_option:
key_type: key_type:
opt_constraint PRIMARY_SYM KEY_SYM { $$= Key::PRIMARY; } opt_constraint PRIMARY_SYM KEY_SYM { $$= Key::PRIMARY; }
| key_or_index { $$= Key::MULTIPLE; } | 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::UNIQUE; }
| opt_constraint UNIQUE_SYM key_or_index { $$= Key::UNIQUE; } | opt_constraint UNIQUE_SYM key_or_index { $$= Key::UNIQUE; }
...@@ -976,9 +962,10 @@ keys_or_index: ...@@ -976,9 +962,10 @@ keys_or_index:
KEYS {} KEYS {}
| INDEX {} | INDEX {}
opt_unique: opt_unique_or_fulltext:
/* empty */ { $$= Key::MULTIPLE; } /* empty */ { $$= Key::MULTIPLE; }
| UNIQUE_SYM { $$= Key::UNIQUE; } | UNIQUE_SYM { $$= Key::UNIQUE; }
| FULLTEXT_SYM { $$= Key::FULLTEXT; }
key_list: key_list:
key_list ',' key_part order_dir { Lex->col_list.push_back($3); } key_list ',' key_part order_dir { Lex->col_list.push_back($3); }
...@@ -2443,7 +2430,6 @@ keyword: ...@@ -2443,7 +2430,6 @@ keyword:
| WORK_SYM {} | WORK_SYM {}
| YEAR_SYM {} | YEAR_SYM {}
| SLAVE {} | SLAVE {}
| COLLECTION {}
/* Option functions */ /* Option functions */
......
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