Commit 23924a98 authored by paul@ice.snake.net's avatar paul@ice.snake.net

Merge paul@bk-internal.mysql.com:/home/bk/mysql-4.1

into ice.snake.net:/Volumes/ice2/MySQL/bk/mysql-4.1
parents 317524ce ac688684
......@@ -784,3 +784,5 @@ vio/test-ssl
vio/test-sslclient
vio/test-sslserver
vio/viotest-ssl
extra/tztime.cc
extra/mysql_tzinfo_to_sql
......@@ -14,7 +14,8 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
INCLUDES = @MT_INCLUDES@ -I$(top_srcdir)/include @ndbcluster_includes@
INCLUDES = @MT_INCLUDES@ -I$(top_srcdir)/include \
@ndbcluster_includes@ -I$(top_srcdir)/sql
LDADD = @CLIENT_EXTRA_LDFLAGS@ ../mysys/libmysys.a \
../dbug/libdbug.a ../strings/libmystrings.a
bin_PROGRAMS = replace comp_err perror resolveip my_print_defaults \
......
......@@ -3245,32 +3245,32 @@ static void send_data_str(MYSQL_BIND *param, char *value, uint length)
{
short data= (short)my_strntol(&my_charset_latin1,value,length,10,NULL,
&err);
int2store(buffer, data);
shortstore(buffer, data);
break;
}
case MYSQL_TYPE_LONG:
{
int32 data= (int32)my_strntol(&my_charset_latin1,value,length,10,NULL,
&err);
int4store(buffer, data);
longstore(buffer, data);
break;
}
case MYSQL_TYPE_LONGLONG:
{
longlong data= my_strntoll(&my_charset_latin1,value,length,10,NULL,&err);
int8store(buffer, data);
longlongstore(buffer, data);
break;
}
case MYSQL_TYPE_FLOAT:
{
float data = (float)my_strntod(&my_charset_latin1,value,length,NULL,&err);
float4store(buffer, data);
floatstore(buffer, data);
break;
}
case MYSQL_TYPE_DOUBLE:
{
double data= my_strntod(&my_charset_latin1,value,length,NULL,&err);
float8store(buffer, data);
doublestore(buffer, data);
break;
}
case MYSQL_TYPE_TINY_BLOB:
......
......@@ -45,6 +45,12 @@ a\b
select * from t1 where a like 'a\\%' escape '#' and a like 'a\\\\b';
a
a\b
prepare stmt1 from 'select * from t1 where a like \'a\\%\' escape ?';
set @esc='#';
execute stmt1 using @esc;
a
a\b
deallocate prepare stmt1;
drop table t1;
create table t1 (a datetime);
insert into t1 values ('2004-03-11 12:00:21');
......
......@@ -25,14 +25,23 @@ select * from t1 where a like "%abc\d%";
drop table t1;
create table t1 (a varchar(10), key(a));
#
# Bug #2231
#
create table t1 (a varchar(10), key(a));
insert into t1 values ('a'), ('a\\b');
select * from t1 where a like 'a\\%' escape '#';
select * from t1 where a like 'a\\%' escape '#' and a like 'a\\\\b';
#
# Bug #4200: Prepared statement parameter as argument to ESCAPE
#
prepare stmt1 from 'select * from t1 where a like \'a\\%\' escape ?';
set @esc='#';
execute stmt1 using @esc;
deallocate prepare stmt1;
drop table t1;
#
......
......@@ -26,7 +26,6 @@ INCLUDES = @MT_INCLUDES@ \
WRAPLIBS= @WRAPLIBS@
SUBDIRS = share
libexec_PROGRAMS = mysqld
bin_PROGRAMS = mysql_tzinfo_to_sql
noinst_PROGRAMS = gen_lex_hash
gen_lex_hash_LDFLAGS = @NOINST_LDFLAGS@
LDADD = @isam_libs@ \
......@@ -93,10 +92,6 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc \
gen_lex_hash_SOURCES = gen_lex_hash.cc
gen_lex_hash_LDADD = $(LDADD) $(CXXLDFLAGS)
mysql_tzinfo_to_sql_SOURCES = tztime.cc tzfile.h
mysql_tzinfo_to_sql_CPPFLAGS = -DTZINFO2SQL $(AM_CPPFLAGS)
mysql_tzinfo_to_sql_LDADD = $(LDADD) $(CXXLDFLAGS)
DEFS = -DMYSQL_SERVER \
-DDEFAULT_MYSQL_HOME="\"$(MYSQLBASEdir)\"" \
-DDATADIR="\"$(MYSQLDATAdir)\"" \
......
......@@ -2151,49 +2151,62 @@ Item_func::optimize_type Item_func_like::select_optimize() const
bool Item_func_like::fix_fields(THD *thd, TABLE_LIST *tlist, Item ** ref)
{
DBUG_ASSERT(fixed == 0);
if (Item_bool_func2::fix_fields(thd, tlist, ref))
if (Item_bool_func2::fix_fields(thd, tlist, ref) ||
escape_item->fix_fields(thd, tlist, &escape_item))
return 1;
/*
We could also do boyer-more for non-const items, but as we would have to
recompute the tables for each row it's not worth it.
*/
if (args[1]->const_item() && !use_strnxfrm(collation.collation) &&
!(specialflag & SPECIAL_NO_NEW_FUNC))
if (!escape_item->const_during_execution())
{
String* res2 = args[1]->val_str(&tmp_value2);
if (!res2)
return 0; // Null argument
const size_t len = res2->length();
const char* first = res2->ptr();
const char* last = first + len - 1;
my_error(ER_WRONG_ARGUMENTS,MYF(0),"ESCAPE");
return 1;
}
if (escape_item->const_item())
{
/* If we are on execution stage */
String *escape_str= escape_item->val_str(&tmp_value1);
escape= escape_str ? *(escape_str->ptr()) : '\\';
/*
len must be > 2 ('%pattern%')
heuristic: only do TurboBM for pattern_len > 2
We could also do boyer-more for non-const items, but as we would have to
recompute the tables for each row it's not worth it.
*/
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) && !use_mb(args[0]->collation.collation);
}
if (canDoTurboBM)
if (args[1]->const_item() && !use_strnxfrm(collation.collation) &&
!(specialflag & SPECIAL_NO_NEW_FUNC))
{
pattern = first + 1;
pattern_len = len - 2;
DBUG_PRINT("info", ("Initializing pattern: '%s'", first));
int *suff = (int*) thd->alloc(sizeof(int)*((pattern_len + 1)*2+
alphabet_size));
bmGs = suff + pattern_len + 1;
bmBc = bmGs + pattern_len + 1;
turboBM_compute_good_suffix_shifts(suff);
turboBM_compute_bad_character_shifts();
DBUG_PRINT("info",("done"));
String* res2 = args[1]->val_str(&tmp_value2);
if (!res2)
return 0; // Null argument
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) && !use_mb(args[0]->collation.collation);
}
if (canDoTurboBM)
{
pattern = first + 1;
pattern_len = len - 2;
DBUG_PRINT("info", ("Initializing pattern: '%s'", first));
int *suff = (int*) thd->alloc(sizeof(int)*((pattern_len + 1)*2+
alphabet_size));
bmGs = suff + pattern_len + 1;
bmBc = bmGs + pattern_len + 1;
turboBM_compute_good_suffix_shifts(suff);
turboBM_compute_bad_character_shifts();
DBUG_PRINT("info",("done"));
}
}
}
return 0;
......
......@@ -841,12 +841,14 @@ class Item_func_like :public Item_bool_func2
bool turboBM_matches(const char* text, int text_len) const;
enum { alphabet_size = 256 };
Item *escape_item;
public:
char escape;
Item_func_like(Item *a,Item *b, char* escape_arg)
Item_func_like(Item *a,Item *b, Item *escape_arg)
:Item_bool_func2(a,b), canDoTurboBM(false), pattern(0), pattern_len(0),
bmGs(0), bmBc(0), escape(*escape_arg) {}
bmGs(0), bmBc(0), escape_item(escape_arg) {}
longlong val_int();
enum Functype functype() const { return LIKE_FUNC; }
optimize_type select_optimize() const;
......
......@@ -626,7 +626,7 @@ SQL_SELECT *prepare_select_for_name(THD *thd, const char *mask, uint mlen,
{
Item *cond= new Item_func_like(new Item_field(pfname),
new Item_string(mask,mlen,pfname->charset()),
(char*) "\\");
new Item_string("\\",1,&my_charset_latin1));
if (thd->is_fatal_error)
return 0; // OOM
return prepare_simple_select(thd,cond,tables,table,error);
......
......@@ -606,7 +606,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%type <simple_string>
remember_name remember_end opt_ident opt_db text_or_password
opt_escape opt_constraint constraint
opt_constraint constraint
%type <string>
text_string opt_gconcat_separator
......@@ -634,7 +634,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
using_list expr_or_default set_expr_or_default interval_expr
param_marker singlerow_subselect singlerow_subselect_init
exists_subselect exists_subselect_init geometry_function
signed_literal now_or_signed_literal
signed_literal now_or_signed_literal opt_escape
%type <item_num>
NUM_literal
......@@ -3576,8 +3576,12 @@ having_clause:
;
opt_escape:
ESCAPE_SYM TEXT_STRING_literal { $$= $2.str; }
| /* empty */ { $$= (char*) "\\"; };
ESCAPE_SYM simple_expr { $$= $2; }
| /* empty */
{
$$= new Item_string("\\", 1, &my_charset_latin1);
}
;
/*
......
......@@ -177,7 +177,8 @@ static void client_connect()
int rc;
myheader_r("client_connect");
fprintf(stdout, "\n Establishing a connection to '%s' ...", opt_host);
fprintf(stdout, "\n Establishing a connection to '%s' ...",
opt_host ? opt_host : "");
if (!(mysql= mysql_init(NULL)))
{
......@@ -3226,8 +3227,11 @@ static void bind_fetch(int row_count)
{
MYSQL_STMT *stmt;
int rc, i, count= row_count;
ulong bit;
long data[10];
int8 i8_data;
int16 i16_data;
int32 i32_data;
longlong i64_data;
float f_data;
double d_data;
char s_data[10];
......@@ -3283,9 +3287,16 @@ static void bind_fetch(int row_count)
}
bind[0].buffer_type= MYSQL_TYPE_TINY;
bind[0].buffer= (char *)&i8_data;
bind[1].buffer_type= MYSQL_TYPE_SHORT;
bind[1].buffer= (char *)&i16_data;
bind[2].buffer_type= MYSQL_TYPE_LONG;
bind[2].buffer= (char *)&i32_data;
bind[3].buffer_type= MYSQL_TYPE_LONGLONG;
bind[3].buffer= (char *)&i64_data;
bind[4].buffer_type= MYSQL_TYPE_FLOAT;
bind[4].buffer= (char *)&f_data;
......@@ -3312,36 +3323,47 @@ static void bind_fetch(int row_count)
check_execute(stmt, rc);
fprintf(stdout, "\n");
fprintf(stdout, "\n tiny : %ld(%lu)", data[0], length[0]);
fprintf(stdout, "\n short : %ld(%lu)", data[1], length[1]);
fprintf(stdout, "\n int : %ld(%lu)", data[2], length[2]);
fprintf(stdout, "\n longlong : %ld(%lu)", data[3], length[3]);
fprintf(stdout, "\n tiny : %ld(%lu)", (ulong) i8_data, length[0]);
fprintf(stdout, "\n short : %ld(%lu)", (ulong) i16_data, length[1]);
fprintf(stdout, "\n int : %ld(%lu)", (ulong) i32_data, length[2]);
fprintf(stdout, "\n longlong : %ld(%lu)", (ulong) i64_data, length[3]);
fprintf(stdout, "\n float : %f(%lu)", f_data, length[4]);
fprintf(stdout, "\n double : %g(%lu)", d_data, length[5]);
fprintf(stdout, "\n char : %s(%lu)", s_data, length[6]);
bit= 1;
rc= 10+row_count;
for (i= 0; i < 4; i++)
{
assert(data[i] == rc+i);
assert(length[i] == bit);
bit<<= 1;
rc+= 12;
}
/* TINY */
assert((int) i8_data == rc);
assert(length[0] == 1);
rc+= 13;
/* SHORT */
assert((int) i16_data == rc);
assert(length[1] == 2);
rc+= 13;
/* LONG */
assert((int) i32_data == rc);
assert(length[2] == 4);
rc+= 13;
/* LONGLONG */
assert((int) i64_data == rc);
assert(length[3] == 8);
rc+= 13;
/* FLOAT */
rc+= i;
assert((int)f_data == rc);
assert(length[4] == 4);
rc+= 13;
/* DOUBLE */
rc+= 13;
assert((int)d_data == rc);
assert(length[5] == 8);
rc+= 13;
/* CHAR */
rc+= 13;
{
char buff[20];
long len= my_sprintf(buff, (buff, "%d", rc));
......@@ -4523,7 +4545,8 @@ static void test_multi_stmt()
{
MYSQL_STMT *stmt, *stmt1, *stmt2;
int rc, id;
int rc;
ulong id;
char name[50];
MYSQL_BIND bind[2];
ulong length[2];
......@@ -4555,7 +4578,7 @@ static void test_multi_stmt()
*/
bzero((char*) bind, sizeof(bind));
bind[0].buffer_type= MYSQL_TYPE_SHORT;
bind[0].buffer_type= MYSQL_TYPE_LONG;
bind[0].buffer= (char *)&id;
bind[0].is_null= &is_null[0];
bind[0].length= &length[0];
......@@ -4582,7 +4605,7 @@ static void test_multi_stmt()
rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
fprintf(stdout, "\n int_data: %d(%lu)", id, length[0]);
fprintf(stdout, "\n int_data: %lu(%lu)", id, length[0]);
fprintf(stdout, "\n str_data: %s(%lu)", name, length[1]);
assert(id == 10);
assert(strcmp(name, "mysql") == 0);
......@@ -4611,7 +4634,7 @@ static void test_multi_stmt()
rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
fprintf(stdout, "\n int_data: %d(%lu)", id, length[0]);
fprintf(stdout, "\n int_data: %lu(%lu)", id, length[0]);
fprintf(stdout, "\n str_data: %s(%lu)", name, length[1]);
assert(id == 10);
assert(strcmp(name, "updated") == 0);
......
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