Commit db2032fd authored by unknown's avatar unknown

Merge work:/home/bk/mysql-4.0 into hundin.mysql.fi:/my/bk/mysql-4.0


Docs/manual.texi:
  Auto merged
parents df2c241d 733d8837
...@@ -52,7 +52,7 @@ diff -r -c --exclude=*.info* glibc-2.2.4/nss/nsswitch.c glibc-2.2.4-new/nss/nssw ...@@ -52,7 +52,7 @@ diff -r -c --exclude=*.info* glibc-2.2.4/nss/nsswitch.c glibc-2.2.4-new/nss/nssw
while (isspace (line[0])) while (isspace (line[0]))
++line; ++line;
*************** ***************
*** 510,522 **** 522
if (name == line) if (name == line)
return result; return result;
...@@ -86,7 +86,7 @@ diff -r -c --exclude=*.info* glibc-2.2.4/nss/nsswitch.c glibc-2.2.4-new/nss/nssw ...@@ -86,7 +86,7 @@ diff -r -c --exclude=*.info* glibc-2.2.4/nss/nsswitch.c glibc-2.2.4-new/nss/nssw
if (new_service == NULL) if (new_service == NULL)
return result; return result;
! *((char *) __mempcpy (new_service->name, name, name_alloc_len)) = '\0'; ! *((char *) __mempcpy (new_service->name, name, name_alloc_len-1)) = '\0';
/* Set default actions. */ /* Set default actions. */
new_service->actions[2 + NSS_STATUS_TRYAGAIN] = NSS_ACTION_CONTINUE; new_service->actions[2 + NSS_STATUS_TRYAGAIN] = NSS_ACTION_CONTINUE;
......
...@@ -26723,6 +26723,12 @@ In the first statement, the @code{LIKE} value begins with a wildcard ...@@ -26723,6 +26723,12 @@ In the first statement, the @code{LIKE} value begins with a wildcard
character. In the second statement, the @code{LIKE} value is not a character. In the second statement, the @code{LIKE} value is not a
constant. constant.
MySQL 4.0 does another optimization on @code{LIKE}. If you are using
@code{... LIKE "%string%"} and @code{string} is longer than 3 characters
then MySQL will use the turbo-boyer-more algorithm to once initialize
the pattern for the string and then use this pattern to quickly search
after the given string.
@findex IS NULL, and indexes @findex IS NULL, and indexes
@cindex indexes, and @code{IS NULL} @cindex indexes, and @code{IS NULL}
Searching using @code{column_name IS NULL} will use indexes if column_name Searching using @code{column_name IS NULL} will use indexes if column_name
...@@ -49305,6 +49311,8 @@ Our TODO section contains what we plan to have in 4.0. @xref{TODO MySQL 4.0}. ...@@ -49305,6 +49311,8 @@ Our TODO section contains what we plan to have in 4.0. @xref{TODO MySQL 4.0}.
@itemize @bullet @itemize @bullet
@item @item
Use turbo-boyer-more to speed up @code{LIKE "%keyword%"} searches.
@item
Fixed bug in @code{DROP DATABASE} with symlink. Fixed bug in @code{DROP DATABASE} with symlink.
@item @item
Fixed crash in @code{REPAIR ... USE_FRM}. Fixed crash in @code{REPAIR ... USE_FRM}.
...@@ -49789,6 +49797,8 @@ not yet 100% confident in this code. ...@@ -49789,6 +49797,8 @@ not yet 100% confident in this code.
@appendixsubsec Changes in release 3.23.51 @appendixsubsec Changes in release 3.23.51
@itemize @bullet @itemize @bullet
@item @item
Fixed bug in @code{CONCAT_WS()} that cut the result.
@item
Changed name of variables @code{Com_show_master_stat} to Changed name of variables @code{Com_show_master_stat} to
@code{Com_show_master_status} and @code{Com_show_slave_stat} to @code{Com_show_master_status} and @code{Com_show_slave_stat} to
@code{Com_show_slave_status}. @code{Com_show_slave_status}.
...@@ -24,7 +24,7 @@ EXTRA_DIST = INSTALL-SOURCE README \ ...@@ -24,7 +24,7 @@ EXTRA_DIST = INSTALL-SOURCE README \
SUBDIRS = include @docs_dirs@ @readline_dir@ \ SUBDIRS = include @docs_dirs@ @readline_dir@ \
@thread_dirs@ pstack @sql_client_dirs@ \ @thread_dirs@ pstack @sql_client_dirs@ \
@sql_server_dirs@ @libmysqld_dirs@ scripts man \ @sql_server_dirs@ @libmysqld_dirs@ scripts man \
tests BUILD \ tests BUILD os2 \
@bench_dirs@ support-files @fs_dirs@ @tools_dirs@ @bench_dirs@ support-files @fs_dirs@ @tools_dirs@
# Relink after clean # Relink after clean
......
...@@ -2364,7 +2364,7 @@ AC_OUTPUT(Makefile extra/Makefile mysys/Makefile isam/Makefile \ ...@@ -2364,7 +2364,7 @@ AC_OUTPUT(Makefile extra/Makefile mysys/Makefile isam/Makefile \
myisam/Makefile myisammrg/Makefile \ myisam/Makefile myisammrg/Makefile \
man/Makefile BUILD/Makefile readline/Makefile vio/Makefile \ man/Makefile BUILD/Makefile readline/Makefile vio/Makefile \
libmysql_r/Makefile libmysqld/Makefile libmysqld/examples/Makefile \ libmysql_r/Makefile libmysqld/Makefile libmysqld/examples/Makefile \
libmysql/Makefile client/Makefile \ libmysql/Makefile client/Makefile os2/Makefile \
pstack/Makefile pstack/aout/Makefile sql/Makefile sql/share/Makefile \ pstack/Makefile pstack/aout/Makefile sql/Makefile sql/share/Makefile \
merge/Makefile dbug/Makefile scripts/Makefile \ merge/Makefile dbug/Makefile scripts/Makefile \
include/Makefile sql-bench/Makefile tools/Makefile \ include/Makefile sql-bench/Makefile tools/Makefile \
......
number alpha new
1413006 idlfmv 1413006<---->idlfmv
1413065 smpsfz 1413065<---->smpsfz
1413127 sljrhx 1413127<---->sljrhx
1413304 qerfnd 1413304<---->qerfnd
new
1413006<---->idlfmv
number alpha new
1413006 idlfmv 1413006<->idlfmv
number alpha new
1413006 idlfmv 1413006-idlfmv-idlfmv-idlfmv-idlfmv-idlfmv-idlfmv-idlfmv
number alpha new
1413006 idlfmv 1413006<------------------>idlfmv
...@@ -15,4 +15,15 @@ test ...@@ -15,4 +15,15 @@ test
select * from t1 where a like "te_t"; select * from t1 where a like "te_t";
a a
test test
select * from t1 where a like "%a%";
a
a
abc
abcd
select * from t1 where a like "%abcd%";
a
abcd
select * from t1 where a like "%abc\d%";
a
abcd
drop table t1; drop table t1;
#
# Test of problem with CONCAT_WS() and long separators.
#
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 ( number INT NOT NULL, alpha CHAR(6) NOT NULL );
INSERT INTO t1 VALUES (1413006,'idlfmv'),
(1413065,'smpsfz'),(1413127,'sljrhx'),(1413304,'qerfnd');
SELECT number, alpha, CONCAT_WS('<---->',number,alpha) AS new
FROM t1 GROUP BY number;
SELECT CONCAT_WS('<---->',number,alpha) AS new
FROM t1 GROUP BY new LIMIT 1;
SELECT number, alpha, CONCAT_WS('<->',number,alpha) AS new
FROM t1 GROUP BY new LIMIT 1;
SELECT number, alpha, CONCAT_WS('-',number,alpha,alpha,alpha,alpha,alpha,alpha,alpha) AS new
FROM t1 GROUP BY new LIMIT 1;
SELECT number, alpha, CONCAT_WS('<------------------>',number,alpha) AS new
FROM t1 GROUP BY new LIMIT 1;
drop table t1;
...@@ -9,4 +9,12 @@ select * from t1 where a like "abc%"; ...@@ -9,4 +9,12 @@ select * from t1 where a like "abc%";
select * from t1 where a like "ABC%"; select * from t1 where a like "ABC%";
select * from t1 where a like "test%"; select * from t1 where a like "test%";
select * from t1 where a like "te_t"; select * from t1 where a like "te_t";
#
# The following will test the boyer-more code
#
select * from t1 where a like "%a%";
select * from t1 where a like "%abcd%";
select * from t1 where a like "%abc\d%";
drop table t1; drop table t1;
...@@ -432,6 +432,7 @@ int my_pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, ...@@ -432,6 +432,7 @@ int my_pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
} }
#endif #endif
#ifdef HPUX #ifdef HPUX
int my_pthread_mutex_trylock(pthread_mutex_t *mutex) int my_pthread_mutex_trylock(pthread_mutex_t *mutex)
{ {
......
# Copyright (C) 2002 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
## Process this file with automake to create Makefile.in
EXTRA_DIST = BldLevel.cmd BldLevel.rc BldLevelInf.cmd ChangeLog.os2 \
MySQL-All.icc MySQL-Client.icc MySQL-Client.irs \
MySQL-Lib.icc MySQL-Opt.icc MySQL-ReadLine.icc \
MySQL-Source.icc MySQL-Sql.icc MySQL-Util.icc MySQL-Util.irs \
MySQL-binlog.icc MySQL-binlog.irs MySQL-sql.irs ReadMe.txt \
build-all.cmd build-all.log mysql-inf.wis mysql.base \
mysql.ih mysql.wis mysqlalt.wis readme.os2 rint.cmd rint.obj \
rint.s
# Don't update the files from bitkeeper
%::SCCS/s.%
...@@ -1228,23 +1228,23 @@ void Item_func_like::fix_length_and_dec() ...@@ -1228,23 +1228,23 @@ void Item_func_like::fix_length_and_dec()
// cmp_type=STRING_RESULT; // For quick select // cmp_type=STRING_RESULT; // For quick select
} }
longlong Item_func_like::val_int() longlong Item_func_like::val_int()
{ {
String *res,*res2; String* res = args[0]->val_str(&tmp_value1);
res=args[0]->val_str(&tmp_value1);
if (args[0]->null_value) if (args[0]->null_value)
{ {
null_value=1; null_value=1;
return 0; return 0;
} }
res2=args[1]->val_str(&tmp_value2); String* res2 = args[1]->val_str(&tmp_value2);
if (args[1]->null_value) if (args[1]->null_value)
{ {
null_value=1; null_value=1;
return 0; return 0;
} }
null_value=0; null_value=0;
if (canDoTurboBM)
return turboBM_matches(res->ptr(), res->length()) ? 1 : 0;
if (binary) if (binary)
return wild_compare(*res,*res2,escape) ? 0 : 1; return wild_compare(*res,*res2,escape) ? 0 : 1;
else else
...@@ -1268,6 +1268,51 @@ Item_func::optimize_type Item_func_like::select_optimize() const ...@@ -1268,6 +1268,51 @@ Item_func::optimize_type Item_func_like::select_optimize() const
return OPTIMIZE_NONE; return OPTIMIZE_NONE;
} }
bool Item_func_like::fix_fields(THD *thd,struct st_table_list *tlist)
{
if (Item_bool_func2::fix_fields(thd, tlist))
return 1;
/*
TODO--we could do it for non-const, but we'd have to
recompute the tables for each row--probably not worth it.
*/
if (args[1]->const_item() && !(specialflag & SPECIAL_NO_NEW_FUNC))
{
String* res2 = args[1]->val_str(&tmp_value2);
const size_t len = res2->length();
const char* first = res2->ptr();
const char* last = first + len - 1;
/*
len must be > 2 ('%pattern%')
heuristic: only do TurboBM for pattern_len > 2
*/
if (len > MIN_TURBOBM_PATTERN_LEN + 2 &&
*first == wild_many &&
*last == wild_many)
{
const char* tmp = first + 1;
for ( ; *tmp != wild_many && *tmp != wild_one && *tmp != escape; tmp++) ;
canDoTurboBM = tmp == last;
}
if (canDoTurboBM)
{
pattern = first + 1;
pattern_len = len - 2;
DBUG_PRINT("TurboBM", ("Initializing pattern: '%s'...", first));
int* suff = (int*)thd->alloc(sizeof(int[pattern_len + 1]));
bmGs = (int*)thd->alloc(sizeof(int[pattern_len + 1]));
bmBc = (int*)thd->alloc(sizeof(int[alphabet_size]));
turboBM_compute_good_suffix_shifts(suff);
turboBM_compute_bad_character_shifts();
DBUG_PRINT("turboBM",("done"));
}
}
return 0;
}
#ifdef USE_REGEX #ifdef USE_REGEX
bool bool
...@@ -1307,7 +1352,6 @@ Item_func_regex::fix_fields(THD *thd,TABLE_LIST *tables) ...@@ -1307,7 +1352,6 @@ Item_func_regex::fix_fields(THD *thd,TABLE_LIST *tables)
return 0; return 0;
} }
longlong Item_func_regex::val_int() longlong Item_func_regex::val_int()
{ {
char buff[MAX_FIELD_WIDTH]; char buff[MAX_FIELD_WIDTH];
...@@ -1364,3 +1408,215 @@ Item_func_regex::~Item_func_regex() ...@@ -1364,3 +1408,215 @@ Item_func_regex::~Item_func_regex()
} }
#endif /* USE_REGEX */ #endif /* USE_REGEX */
#ifdef LIKE_CMP_TOUPPER
#define likeconv(A) (uchar) toupper(A)
#else
#define likeconv(A) (uchar) my_sort_order[(uchar) (A)]
#endif
/**********************************************************************
turboBM_compute_suffixes()
Precomputation dependent only on pattern_len.
**********************************************************************/
void Item_func_like::turboBM_compute_suffixes(int* suff)
{
const int plm1 = pattern_len - 1;
int f = 0;
int g = plm1;
int* const splm1 = suff + plm1;
*splm1 = pattern_len;
if (binary)
{
int i;
for (i = pattern_len - 2; i >= 0; i--)
{
int tmp = *(splm1 + i - f);
if (g < i && tmp < i - g)
suff[i] = tmp;
else
{
if (i < g)
g = i; // g = min(i, g)
f = i;
while (g >= 0 && pattern[g] == pattern[g + plm1 - f])
g--;
suff[i] = f - g;
}
}
}
else
{
int i;
for (i = pattern_len - 2; 0 <= i; --i)
{
int tmp = *(splm1 + i - f);
if (g < i && tmp < i - g)
suff[i] = tmp;
else
{
if (i < g)
g = i; // g = min(i, g)
f = i;
while (g >= 0 && likeconv(pattern[g]) == likeconv(pattern[g + plm1 - f]))
g--;
suff[i] = f - g;
}
}
}
}
/**********************************************************************
turboBM_compute_good_suffix_shifts()
Precomputation dependent only on pattern_len.
**********************************************************************/
void Item_func_like::turboBM_compute_good_suffix_shifts(int* suff)
{
turboBM_compute_suffixes(suff);
int* end = bmGs + pattern_len;
int* k;
for (k = bmGs; k < end; k++)
*k = pattern_len;
int tmp;
int i;
int j = 0;
const int plm1 = pattern_len - 1;
for (i = plm1; i > -1; i--)
{
if (suff[i] == i + 1)
{
for (tmp = plm1 - i; j < tmp; j++)
{
int* tmp2 = bmGs + j;
if (*tmp2 == pattern_len)
*tmp2 = tmp;
}
}
}
int* tmp2;
for (tmp = plm1 - i; j < tmp; j++)
{
tmp2 = bmGs + j;
if (*tmp2 == pattern_len)
*tmp2 = tmp;
}
tmp2 = bmGs + plm1;
for (i = 0; i <= pattern_len - 2; i++)
*(tmp2 - suff[i]) = plm1 - i;
}
/**********************************************************************
turboBM_compute_bad_character_shifts()
Precomputation dependent on pattern_len.
**********************************************************************/
void Item_func_like::turboBM_compute_bad_character_shifts()
{
int* i;
int* end = bmBc + alphabet_size;
for (i = bmBc; i < end; i++)
*i = pattern_len;
int j;
const int plm1 = pattern_len - 1;
if (binary)
for (j = 0; j < plm1; j++)
bmBc[pattern[j]] = plm1 - j;
else
for (j = 0; j < plm1; j++)
bmBc[likeconv(pattern[j])] = plm1 - j;
}
/**********************************************************************
turboBM_matches()
Search for pattern in text, returns true/false for match/no match
**********************************************************************/
bool Item_func_like::turboBM_matches(const char* text, int text_len) const
{
register int bcShift;
register int turboShift;
int shift = pattern_len;
int j = 0;
int u = 0;
const int plm1 = pattern_len - 1;
const int tlmpl = text_len - pattern_len;
/* Searching */
if (binary)
{
while (j <= tlmpl)
{
register int i = plm1;
while (i >= 0 && pattern[i] == text[i + j])
{
i--;
if (i == plm1 - shift)
i -= u;
}
if (i < 0)
return true;
register const int v = plm1 - i;
turboShift = u - v;
bcShift = bmBc[text[i + j]] - plm1 + i;
shift = max(turboShift, bcShift);
shift = max(shift, bmGs[i]);
if (shift == bmGs[i])
u = min(pattern_len - shift, v);
else
{
if (turboShift < bcShift)
shift = max(shift, u + 1);
u = 0;
}
j += shift;
}
return false;
}
else
{
while (j <= tlmpl)
{
register int i = plm1;
while (i >= 0 && likeconv(pattern[i]) == likeconv(text[i + j]))
{
i--;
if (i == plm1 - shift)
i -= u;
}
if (i < 0)
return true;
register const int v = plm1 - i;
turboShift = u - v;
bcShift = bmBc[likeconv(text[i + j])] - plm1 + i;
shift = max(turboShift, bcShift);
shift = max(shift, bmGs[i]);
if (shift == bmGs[i])
u = min(pattern_len - shift, v);
else
{
if (turboShift < bcShift)
shift = max(shift, u + 1);
u = 0;
}
j += shift;
}
return false;
}
}
...@@ -478,15 +478,40 @@ class Item_func_isnotnull :public Item_bool_func ...@@ -478,15 +478,40 @@ class Item_func_isnotnull :public Item_bool_func
class Item_func_like :public Item_bool_func2 class Item_func_like :public Item_bool_func2
{ {
char escape; char escape;
public:
Item_func_like(Item *a,Item *b, char* escape_arg) :Item_bool_func2(a,b),escape(*escape_arg) // Turbo Boyer-Moore data
bool canDoTurboBM; // pattern is '%abcd%' case
const char* pattern;
int pattern_len;
// TurboBM buffers, *this is owner
int* bmGs; // good suffix shift table, size is pattern_len + 1
int* bmBc; // bad character shift table, size is alphabet_size
void turboBM_compute_suffixes(int* suff);
void turboBM_compute_good_suffix_shifts(int* suff);
void turboBM_compute_bad_character_shifts();
bool turboBM_matches(const char* text, int text_len) const;
enum { alphabet_size = 256 };
public:
Item_func_like::Item_func_like(Item *a,Item *b, char* escape_arg) :
Item_bool_func2(a,b),
escape(*escape_arg),
canDoTurboBM(false),
pattern(0),
pattern_len(0),
bmGs(0),
bmBc(0)
{} {}
longlong val_int(); longlong val_int();
enum Functype functype() const { return LIKE_FUNC; } enum Functype functype() const { return LIKE_FUNC; }
optimize_type select_optimize() const; optimize_type select_optimize() const;
cond_result eq_cmp_result() const { return COND_TRUE; } cond_result eq_cmp_result() const { return COND_TRUE; }
const char *func_name() const { return "like"; } const char *func_name() const { return "like"; }
void fix_length_and_dec(); void fix_length_and_dec();
bool fix_fields(THD *thd,struct st_table_list *tlist);
}; };
#ifdef USE_REGEX #ifdef USE_REGEX
......
...@@ -475,7 +475,7 @@ String *Item_func_concat_ws::val_str(String *str) ...@@ -475,7 +475,7 @@ String *Item_func_concat_ws::val_str(String *str)
void Item_func_concat_ws::fix_length_and_dec() void Item_func_concat_ws::fix_length_and_dec()
{ {
max_length=0; max_length=separator->max_length*(arg_count-1);
for (uint i=0 ; i < arg_count ; i++) for (uint i=0 ; i < arg_count ; i++)
max_length+=args[i]->max_length; max_length+=args[i]->max_length;
if (max_length > MAX_BLOB_WIDTH) if (max_length > MAX_BLOB_WIDTH)
......
This diff is collapsed.
...@@ -209,16 +209,16 @@ ...@@ -209,16 +209,16 @@
"E' scaduto il timeout per l'attesa del lock", "E' scaduto il timeout per l'attesa del lock",
"Il numero totale di lock e' maggiore della grandezza della tabella di lock", "Il numero totale di lock e' maggiore della grandezza della tabella di lock",
"I lock di aggiornamento non possono essere acquisiti durante una transazione 'READ UNCOMMITTED'", "I lock di aggiornamento non possono essere acquisiti durante una transazione 'READ UNCOMMITTED'",
"DROP DATABASE not allowed while thread is holding global read lock", "DROP DATABASE non e' permesso mentre il thread ha un lock globale di lettura",
"CREATE DATABASE not allowed while thread is holding global read lock", "CREATE DATABASE non e' permesso mentre il thread ha un lock globale di lettura",
"Wrong arguments to %s", "Argomenti errati a %s",
"%-.32s@%-.64s is not allowed to create new users", "A %-.32s@%-.64s non e' permesso creare nuovi utenti",
"Incorrect table definition; All MERGE tables must be in the same database", "Definizione della tabella errata; tutte le tabelle di tipo MERGE devono essere nello stesso database",
"Deadlock found when trying to get lock; Try restarting transaction", "Trovato deadlock durante il lock; Provare a far ripartire la transazione",
"The used table type doesn't support FULLTEXT indexes", "La tabella usata non supporta gli indici FULLTEXT",
"Cannot add foreign key constraint", "Impossibile aggiungere il vincolo di integrita' referenziale (foreign key constraint)",
"Cannot add a child row: a foreign key constraint fails", "Impossibile aggiungere la riga: un vincolo d'integrita' referenziale non e' soddisfatto",
"Cannot delete a parent row: a foreign key constraint fails", "Impossibile cancellare la riga: un vincolo d'integrita' referenziale non e' soddisfatto",
"Error connecting to master: %-.128s", "Error connecting to master: %-.128s",
"Error running query on master: %-.128s", "Error running query on master: %-.128s",
"Error when executing command %s: %-.128s", "Error when executing command %s: %-.128s",
......
...@@ -122,6 +122,13 @@ bfill((A)->null_flags,(A)->null_bytes,255);\ ...@@ -122,6 +122,13 @@ bfill((A)->null_flags,(A)->null_bytes,255);\
#define TE_INFO_LENGTH 3 #define TE_INFO_LENGTH 3
#define MTYP_NOEMPTY_BIT 128 #define MTYP_NOEMPTY_BIT 128
/*
* Minimum length pattern before Turbo Boyer-Moore is used
* for SELECT "text" LIKE "%pattern%", excluding the two
* wildcards in class Item_func_like.
*/
#define MIN_TURBOBM_PATTERN_LEN 3
/* Include prototypes for unireg */ /* Include prototypes for unireg */
#include "mysqld_error.h" #include "mysqld_error.h"
......
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