summaryrefslogtreecommitdiff
path: root/storage
diff options
context:
space:
mode:
authorunknown <tsmith@ramayana.hindu.god>2007-07-17 11:33:26 -0600
committerunknown <tsmith@ramayana.hindu.god>2007-07-17 11:33:26 -0600
commit3e09e4adce41d2d92792a70b4736f4afaa959b57 (patch)
treefa600ff5ab435234ed89e8b62b93eb17e01bb5a3 /storage
parentba6b937620a1502b42a4e841e8e787b6fac4c653 (diff)
parent8bbaf6addd99a477a66c8322d44177dbdac4e4e8 (diff)
downloadmariadb-git-3e09e4adce41d2d92792a70b4736f4afaa959b57.tar.gz
Merge ramayana.hindu.god:/home/tsmith/m/bk/51
into ramayana.hindu.god:/home/tsmith/m/bk/maint/51 mysql-test/suite/rpl_ndb/t/disabled.def: Auto merged mysql-test/t/disabled.def: Auto merged sql/mysql_priv.h: Auto merged sql/sql_class.cc: Auto merged sql/sql_class.h: Auto merged sql/sql_insert.cc: Auto merged
Diffstat (limited to 'storage')
-rw-r--r--storage/myisam/ft_boolean_search.c36
-rw-r--r--storage/myisam/ft_parser.c16
-rw-r--r--storage/myisam/ha_myisam.cc75
-rw-r--r--storage/myisam/ha_myisam.h7
4 files changed, 120 insertions, 14 deletions
diff --git a/storage/myisam/ft_boolean_search.c b/storage/myisam/ft_boolean_search.c
index f38561a76dd..c881f7a7480 100644
--- a/storage/myisam/ft_boolean_search.c
+++ b/storage/myisam/ft_boolean_search.c
@@ -23,8 +23,14 @@
inside plus subtree. max_docid could be used by any word in plus
subtree, but it could be updated by plus-word only.
+ Fulltext "smarter index merge" optimization assumes that rows
+ it gets are ordered by doc_id. That is not the case when we
+ search for a word with truncation operator. It may return
+ rows in random order. Thus we may not use "smarter index merge"
+ optimization with "trunc-words".
+
The idea is: there is no need to search for docid smaller than
- biggest docid inside current plus subtree.
+ biggest docid inside current plus subtree or any upper plus subtree.
Examples:
+word1 word2
@@ -36,6 +42,13 @@
+(word1 -word2) +(+word3 word4)
share same max_docid
max_docid updated by word3
+ +word1 word2 (+word3 word4 (+word5 word6))
+ three subexpressions (including the top-level one),
+ every one has its own max_docid, updated by its plus word.
+ but for the search word6 uses
+ max(word1.max_docid, word3.max_docid, word5.max_docid),
+ while word4 uses, accordingly,
+ max(word1.max_docid, word3.max_docid).
*/
#define FT_CORE
@@ -104,7 +117,7 @@ typedef struct st_ftb_word
/* ^^^^^^^^^^^^^^^^^^ FTB_{EXPR,WORD} common section */
my_off_t docid[2]; /* for index search and for scan */
my_off_t key_root;
- my_off_t *max_docid;
+ FTB_EXPR *max_docid_expr;
MI_KEYDEF *keyinfo;
struct st_ftb_word *prev;
float weight;
@@ -208,7 +221,7 @@ static int ftb_query_add_word(MYSQL_FTPARSER_PARAM *param,
for (tmp_expr= ftb_param->ftbe; tmp_expr->up; tmp_expr= tmp_expr->up)
if (! (tmp_expr->flags & FTB_FLAG_YES))
break;
- ftbw->max_docid= &tmp_expr->max_docid;
+ ftbw->max_docid_expr= tmp_expr;
/* fall through */
case FT_TOKEN_STOPWORD:
if (! ftb_param->up_quot) break;
@@ -347,11 +360,17 @@ static int _ft2_search(FTB *ftb, FTB_WORD *ftbw, my_bool init_search)
else
{
uint sflag= SEARCH_BIGGER;
- if (ftbw->docid[0] < *ftbw->max_docid)
+ my_off_t max_docid=0;
+ FTB_EXPR *tmp;
+
+ for (tmp= ftbw->max_docid_expr; tmp; tmp= tmp->up)
+ set_if_bigger(max_docid, tmp->max_docid);
+
+ if (ftbw->docid[0] < max_docid)
{
sflag|= SEARCH_SAME;
_mi_dpointer(info, (uchar *)(ftbw->word + ftbw->len + HA_FT_WLEN),
- *ftbw->max_docid);
+ max_docid);
}
r=_mi_search(info, ftbw->keyinfo, (uchar*) lastkey_buf,
USE_WHOLE_KEY, sflag, ftbw->key_root);
@@ -430,8 +449,8 @@ static int _ft2_search(FTB *ftb, FTB_WORD *ftbw, my_bool init_search)
memcpy(lastkey_buf+off, info->lastkey, info->lastkey_length);
}
ftbw->docid[0]=info->lastpos;
- if (ftbw->flags & FTB_FLAG_YES)
- *ftbw->max_docid= info->lastpos;
+ if (ftbw->flags & FTB_FLAG_YES && !(ftbw->flags & FTB_FLAG_TRUNC))
+ ftbw->max_docid_expr->max_docid= info->lastpos;
return 0;
}
@@ -474,7 +493,8 @@ static void _ftb_init_index_search(FT_INFO *ftb)
ftbe->up->flags|= FTB_FLAG_TRUNC, ftbe=ftbe->up)
{
if (ftbe->flags & FTB_FLAG_NO || /* 2 */
- ftbe->up->ythresh - ftbe->up->yweaks >1) /* 1 */
+ ftbe->up->ythresh - ftbe->up->yweaks >
+ (uint) test(ftbe->flags & FTB_FLAG_YES)) /* 1 */
{
FTB_EXPR *top_ftbe=ftbe->up;
ftbw->docid[0]=HA_OFFSET_ERROR;
diff --git a/storage/myisam/ft_parser.c b/storage/myisam/ft_parser.c
index ba858c37aee..befe2bab066 100644
--- a/storage/myisam/ft_parser.c
+++ b/storage/myisam/ft_parser.c
@@ -111,7 +111,8 @@ uchar ft_get_word(CHARSET_INFO *cs, uchar **start, uchar *end,
{
uchar *doc=*start;
int ctype;
- uint mwc, length, mbl;
+ uint mwc, length;
+ int mbl;
param->yesno=(FTB_YES==' ') ? 1 : (param->quot != 0);
param->weight_adjust= param->wasign= 0;
@@ -119,7 +120,7 @@ uchar ft_get_word(CHARSET_INFO *cs, uchar **start, uchar *end,
while (doc<end)
{
- for (; doc < end; doc+= (mbl > 0 ? mbl : 1))
+ for (; doc < end; doc+= (mbl > 0 ? mbl : (mbl < 0 ? -mbl : 1)))
{
mbl= cs->cset->ctype(cs, &ctype, (uchar*)doc, (uchar*)end);
if (true_word_char(ctype, *doc))
@@ -157,7 +158,8 @@ uchar ft_get_word(CHARSET_INFO *cs, uchar **start, uchar *end,
}
mwc=length=0;
- for (word->pos= doc; doc < end; length++, doc+= (mbl > 0 ? mbl : 1))
+ for (word->pos= doc; doc < end; length++,
+ doc+= (mbl > 0 ? mbl : (mbl < 0 ? -mbl : 1)))
{
mbl= cs->cset->ctype(cs, &ctype, (uchar*)doc, (uchar*)end);
if (true_word_char(ctype, *doc))
@@ -200,13 +202,14 @@ uchar ft_simple_get_word(CHARSET_INFO *cs, uchar **start, const uchar *end,
FT_WORD *word, my_bool skip_stopwords)
{
uchar *doc= *start;
- uint mwc, length, mbl;
+ uint mwc, length;
+ int mbl;
int ctype;
DBUG_ENTER("ft_simple_get_word");
do
{
- for (;; doc+= (mbl > 0 ? mbl : 1))
+ for (;; doc+= (mbl > 0 ? mbl : (mbl < 0 ? -mbl : 1)))
{
if (doc >= end)
DBUG_RETURN(0);
@@ -216,7 +219,8 @@ uchar ft_simple_get_word(CHARSET_INFO *cs, uchar **start, const uchar *end,
}
mwc= length= 0;
- for (word->pos= doc; doc < end; length++, doc+= (mbl > 0 ? mbl : 1))
+ for (word->pos= doc; doc < end; length++,
+ doc+= (mbl > 0 ? mbl : (mbl < 0 ? -mbl : 1)))
{
mbl= cs->cset->ctype(cs, &ctype, (uchar*)doc, (uchar*)end);
if (true_word_char(ctype, *doc))
diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc
index 98f74247707..20f55545282 100644
--- a/storage/myisam/ha_myisam.cc
+++ b/storage/myisam/ha_myisam.cc
@@ -2075,3 +2075,78 @@ mysql_declare_plugin(myisam)
}
mysql_declare_plugin_end;
+
+#ifdef HAVE_QUERY_CACHE
+/**
+ @brief Register a named table with a call back function to the query cache.
+
+ @param thd The thread handle
+ @param table_key A pointer to the table name in the table cache
+ @param key_length The length of the table name
+ @param[out] engine_callback The pointer to the storage engine call back
+ function, currently 0
+ @param[out] engine_data Engine data will be set to 0.
+
+ @note Despite the name of this function, it is used to check each statement
+ before it is cached and not to register a table or callback function.
+
+ @see handler::register_query_cache_table
+
+ @return The error code. The engine_data and engine_callback will be set to 0.
+ @retval TRUE Success
+ @retval FALSE An error occured
+*/
+
+my_bool ha_myisam::register_query_cache_table(THD *thd, char *table_name,
+ uint table_name_len,
+ qc_engine_callback
+ *engine_callback,
+ ulonglong *engine_data)
+{
+ /*
+ No call back function is needed to determine if a cached statement
+ is valid or not.
+ */
+ *engine_callback= 0;
+
+ /*
+ No engine data is needed.
+ */
+ *engine_data= 0;
+
+ /*
+ If a concurrent INSERT has happened just before the currently processed
+ SELECT statement, the total size of the table is unknown.
+
+ To determine if the table size is known, the current thread's snap shot of
+ the table size with the actual table size are compared.
+
+ If the table size is unknown the SELECT statement can't be cached.
+ */
+ ulonglong actual_data_file_length;
+ ulonglong current_data_file_length;
+
+ /*
+ POSIX visibility rules specify that "2. Whatever memory values a
+ thread can see when it unlocks a mutex <...> can also be seen by any
+ thread that later locks the same mutex". In this particular case,
+ concurrent insert thread had modified the data_file_length in
+ MYISAM_SHARE before it has unlocked (or even locked)
+ structure_guard_mutex. So, here we're guaranteed to see at least that
+ value after we've locked the same mutex. We can see a later value
+ (modified by some other thread) though, but it's ok, as we only want
+ to know if the variable was changed, the actual new value doesn't matter
+ */
+ actual_data_file_length= file->s->state.state.data_file_length;
+ current_data_file_length= file->save_state.data_file_length;
+
+ if (current_data_file_length != actual_data_file_length)
+ {
+ /* Don't cache current statement. */
+ return FALSE;
+ }
+
+ /* It is ok to try to cache current statement. */
+ return TRUE;
+}
+#endif
diff --git a/storage/myisam/ha_myisam.h b/storage/myisam/ha_myisam.h
index 6cc9f4811b0..024675075c2 100644
--- a/storage/myisam/ha_myisam.h
+++ b/storage/myisam/ha_myisam.h
@@ -137,4 +137,11 @@ class ha_myisam: public handler
int dump(THD* thd, int fd);
int net_read_dump(NET* net);
#endif
+#ifdef HAVE_QUERY_CACHE
+ my_bool register_query_cache_table(THD *thd, char *table_key,
+ uint key_length,
+ qc_engine_callback
+ *engine_callback,
+ ulonglong *engine_data);
+#endif
};