diff --git a/Docs/Support/texi2html b/Docs/Support/texi2html
index 5dda7c8bbd5..8067d8f72ce 100755
--- a/Docs/Support/texi2html
+++ b/Docs/Support/texi2html
@@ -1811,7 +1811,7 @@ sub fix_image
{
my($text) = @_;
my($arg1, $ext);
- $text =~ /^([^,]*)$/;
+ $text =~ /^([^,]*)/;
die "error in image: '$text'" unless defined($1);
$arg1 = $1;
$arg1 =~ s/@@/@/g;
diff --git a/include/sql_common.h b/include/sql_common.h
index cde53786f83..c07a4a831bb 100644
--- a/include/sql_common.h
+++ b/include/sql_common.h
@@ -25,7 +25,6 @@ extern "C" {
MYSQL_FIELD *unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields,
my_bool default_value, uint server_capabilities);
void free_rows(MYSQL_DATA *cur);
-my_bool mysql_autenticate(MYSQL *mysql, const char *passwd);
void free_old_query(MYSQL *mysql);
void end_server(MYSQL *mysql);
my_bool mysql_reconnect(MYSQL *mysql);
diff --git a/innobase/dict/dict0dict.c b/innobase/dict/dict0dict.c
index fd98538d2ad..f670c0dc16d 100644
--- a/innobase/dict/dict0dict.c
+++ b/innobase/dict/dict0dict.c
@@ -2244,7 +2244,7 @@ dict_foreign_add_to_cache(
Scans from pointer onwards. Stops if is at the start of a copy of
'string' where characters are compared without case sensitivity. Stops
also at '\0'. */
-static
+
const char*
dict_scan_to(
/*=========*/
diff --git a/innobase/include/dict0dict.h b/innobase/include/dict0dict.h
index 4dbbd5b4886..ca632691450 100644
--- a/innobase/include/dict0dict.h
+++ b/innobase/include/dict0dict.h
@@ -891,6 +891,18 @@ dict_tables_have_same_db(
const char* name2); /* in: table name in the form
dbname '/' tablename */
+/*************************************************************************
+Scans from pointer onwards. Stops if is at the start of a copy of
+'string' where characters are compared without case sensitivity. Stops
+also at '\0'. */
+
+const char*
+dict_scan_to(
+/*=========*/
+ /* out: scanned up to this */
+ const char* ptr, /* in: scan from */
+ const char* string);/* in: look for this */
+
/* Buffers for storing detailed information about the latest foreign key
and unique key errors */
extern FILE* dict_foreign_err_file;
diff --git a/innobase/row/row0ins.c b/innobase/row/row0ins.c
index 7b0beb9d183..c9c784403c8 100644
--- a/innobase/row/row0ins.c
+++ b/innobase/row/row0ins.c
@@ -50,6 +50,15 @@ innobase_invalidate_query_cache(
ulint full_name_len); /* in: full name length where also the null
chars count */
+/**********************************************************************
+This function returns true if SQL-query in the current thread
+is either REPLACE or LOAD DATA INFILE REPLACE.
+NOTE that /mysql/innobase/row/row0ins.c must contain the
+prototype for this function ! */
+
+ibool
+innobase_query_is_replace(void);
+/*===========================*/
/*************************************************************************
Creates an insert node struct. */
@@ -1482,9 +1491,9 @@ row_ins_scan_sec_index_for_duplicate(
ulint err = DB_SUCCESS;
ibool moved;
mtr_t mtr;
- trx_t *trx;
- ibool success;
-
+ trx_t* trx;
+ const char* ptr;
+
n_unique = dict_index_get_n_unique(index);
/* If the secondary index is unique, but one of the fields in the
@@ -1523,9 +1532,8 @@ row_ins_scan_sec_index_for_duplicate(
trx = thr_get_trx(thr);
ut_ad(trx);
- dict_accept(*trx->mysql_query_str, "REPLACE", &success);
- if (success) {
+ if (innobase_query_is_replace()) {
/* The manual defines the REPLACE semantics that it
is either an INSERT or DELETE(s) for duplicate key
@@ -1605,7 +1613,7 @@ row_ins_duplicate_error_in_clust(
page_t* page;
ulint n_unique;
trx_t* trx = thr_get_trx(thr);
- ibool success;
+ const char* ptr;
UT_NOT_USED(mtr);
@@ -1639,10 +1647,7 @@ row_ins_duplicate_error_in_clust(
sure that in roll-forward we get the same duplicate
errors as in original execution */
- dict_accept(*trx->mysql_query_str, "REPLACE",
- &success);
-
- if (success) {
+ if (innobase_query_is_replace()) {
/* The manual defines the REPLACE semantics
that it is either an INSERT or DELETE(s)
@@ -1683,15 +1688,9 @@ row_ins_duplicate_error_in_clust(
/* The manual defines the REPLACE semantics that it
is either an INSERT or DELETE(s) for duplicate key
+ INSERT. Therefore, we should take X-lock for
- duplicates.
- */
+ duplicates. */
- /* Is the first word in MySQL query REPLACE ? */
-
- dict_accept(*trx->mysql_query_str, "REPLACE",
- &success);
-
- if (success) {
+ if (innobase_query_is_replace()) {
err = row_ins_set_exclusive_rec_lock(
LOCK_REC_NOT_GAP,
diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c
index 3ff94c8f238..740241fa210 100644
--- a/innobase/row/row0sel.c
+++ b/innobase/row/row0sel.c
@@ -2794,7 +2794,7 @@ row_search_for_mysql(
rec_t* index_rec;
rec_t* clust_rec;
rec_t* old_vers;
- ulint err;
+ ulint err = DB_SUCCESS;
ibool moved;
ibool cons_read_requires_clust_rec;
ibool was_lock_wait;
@@ -3203,26 +3203,20 @@ rec_loop:
if (prebuilt->select_lock_type != LOCK_NONE
&& set_also_gap_locks) {
- /* Try to place a lock on the index record */
+ /* Try to place a lock on the index record */
- /* If innodb_locks_unsafe_for_binlog option is used,
- we lock only the record, i.e. next-key locking is
- not used.
- */
- if ( srv_locks_unsafe_for_binlog )
- {
- err = sel_set_rec_lock(rec, index,
- prebuilt->select_lock_type,
- LOCK_REC_NOT_GAP, thr);
- }
- else
+ /* If innodb_locks_unsafe_for_binlog option is used,
+ we do not lock gaps. Supremum record is really
+ a gap and therefore we do not set locks there. */
+
+ if ( srv_locks_unsafe_for_binlog == FALSE )
{
- err = sel_set_rec_lock(rec, index,
+ err = sel_set_rec_lock(rec, index,
prebuilt->select_lock_type,
LOCK_ORDINARY, thr);
}
-
- if (err != DB_SUCCESS) {
+
+ if (err != DB_SUCCESS) {
goto lock_wait_or_error;
}
diff --git a/libmysql/manager.c b/libmysql/manager.c
index f030eb17889..631bfa26cb2 100644
--- a/libmysql/manager.c
+++ b/libmysql/manager.c
@@ -237,7 +237,7 @@ int STDCALL mysql_manager_fetch_line(MYSQL_MANAGER* con, char* res_buf,
char* res_buf_end=res_buf+res_buf_size;
char* net_buf=(char*) con->net.read_pos, *net_buf_end;
int res_buf_shift=RES_BUF_SHIFT;
- uint num_bytes;
+ ulong num_bytes;
if (res_buf_size) returns varying results
#
+--disable_warnings
SET NAMES utf8;
--disable_warnings
CREATE TABLE t1 (
diff --git a/mysql-test/t/ps_11bugs.test b/mysql-test/t/ps_11bugs.test
index 53afc8b5a78..d0aeaf265bb 100644
--- a/mysql-test/t/ps_11bugs.test
+++ b/mysql-test/t/ps_11bugs.test
@@ -3,19 +3,25 @@
# Prepared Statements #
# re-testing bug DB entries #
# #
+# The bugs are reported as "closed". #
+# Command sequences taken from bug report. #
+# No other test contains the bug# as comment. #
+# #
+# Tests drop/create tables 't1', 't2', ... #
+# #
###############################################
-use test;
+--disable_warnings
+drop table if exists t1, t2;
+--enable_warnings
# bug#1180: optimized away part of WHERE clause cause incorect prepared satatement results
-drop table if exists test_select;
+CREATE TABLE t1(session_id char(9) NOT NULL);
+INSERT INTO t1 VALUES ("abc");
+SELECT * FROM t1;
-CREATE TABLE test_select(session_id char(9) NOT NULL);
-INSERT INTO test_select VALUES ("abc");
-SELECT * FROM test_select;
-
-prepare st_1180 from 'SELECT * FROM test_select WHERE ?="1111" and session_id = "abc"';
+prepare st_1180 from 'SELECT * FROM t1 WHERE ?="1111" and session_id = "abc"';
# Must not find a row
set @arg1= 'abc';
@@ -29,4 +35,97 @@ execute st_1180 using @arg1;
set @arg1= 'abc';
execute st_1180 using @arg1;
-drop table test_select;
+drop table t1;
+
+# end of bug#1180
+
+
+# bug#1644: Insertion of more than 3 NULL columns with parameter binding fails
+
+# Using prepared statements, insertion of more than three columns with NULL
+# values fails to insert additional NULLS. After the third column NULLS will
+# be inserted into the database as zeros.
+# First insert four columns of a value (i.e. 22) to verify binding is working
+# correctly. Then Bind to each columns bind parameter an is_null value of 1.
+# Then insert four more columns of integers, just for sanity.
+# A subsequent select on the server will result in this:
+# mysql> select * from foo_dfr;
+# +------+------+------+------+
+# | col1 | col2 | col3 | col4 |
+# +------+------+------+------+
+# | 22 | 22 | 22 | 22 |
+# | NULL | NULL | NULL | 0 |
+# | 88 | 88 | 88 | 88 |
+# +------+------+------+------+
+
+# Test is extended to more columns - code stores bit vector in bytes.
+
+create table t1 (
+ c_01 char(6), c_02 integer, c_03 real, c_04 int(3), c_05 varchar(20),
+ c_06 date, c_07 char(1), c_08 real, c_09 int(11), c_10 time,
+ c_11 char(6), c_12 integer, c_13 real, c_14 int(3), c_15 varchar(20),
+ c_16 date, c_17 char(1), c_18 real, c_19 int(11), c_20 text);
+# Do not use "timestamp" type, because it has a non-NULL default as of 4.1.2
+
+prepare st_1644 from 'insert into t1 values ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)';
+
+set @arg01= 'row_1'; set @arg02= 1; set @arg03= 1.1; set @arg04= 111; set @arg05= 'row_one';
+set @arg06= '2004-10-12'; set @arg07= '1'; set @arg08= 1.1; set @arg09= '100100100'; set @arg10= '12:34:56';
+set @arg11= 'row_1'; set @arg12= 1; set @arg13= 1.1; set @arg14= 111; set @arg15= 'row_one';
+set @arg16= '2004-10-12'; set @arg17= '1'; set @arg18= 1.1; set @arg19= '100100100'; set @arg20= '12:34:56';
+execute st_1644 using @arg01, @arg02, @arg03, @arg04, @arg05, @arg06, @arg07, @arg08, @arg09, @arg10,
+ @arg11, @arg12, @arg13, @arg14, @arg15, @arg16, @arg17, @arg18, @arg19, @arg20;
+
+set @arg01= NULL; set @arg02= NULL; set @arg03= NULL; set @arg04= NULL; set @arg05= NULL;
+set @arg06= NULL; set @arg07= NULL; set @arg08= NULL; set @arg09= NULL; set @arg10= NULL;
+set @arg11= NULL; set @arg12= NULL; set @arg13= NULL; set @arg14= NULL; set @arg15= NULL;
+set @arg16= NULL; set @arg17= NULL; set @arg18= NULL; set @arg19= NULL; set @arg20= NULL;
+execute st_1644 using @arg01, @arg02, @arg03, @arg04, @arg05, @arg06, @arg07, @arg08, @arg09, @arg10,
+ @arg11, @arg12, @arg13, @arg14, @arg15, @arg16, @arg17, @arg18, @arg19, @arg20;
+
+set @arg01= 'row_3'; set @arg02= 3; set @arg03= 3.3; set @arg04= 333; set @arg05= 'row_three';
+set @arg06= '2004-10-12'; set @arg07= '3'; set @arg08= 3.3; set @arg09= '300300300'; set @arg10= '12:34:56';
+set @arg11= 'row_3'; set @arg12= 3; set @arg13= 3.3; set @arg14= 333; set @arg15= 'row_three';
+set @arg16= '2004-10-12'; set @arg17= '3'; set @arg18= 3.3; set @arg19= '300300300'; set @arg20= '12:34:56';
+execute st_1644 using @arg01, @arg02, @arg03, @arg04, @arg05, @arg06, @arg07, @arg08, @arg09, @arg10,
+ @arg11, @arg12, @arg13, @arg14, @arg15, @arg16, @arg17, @arg18, @arg19, @arg20;
+
+select * from t1;
+
+drop table t1;
+
+# end of bug#1644
+
+
+# bug#1677: Prepared statement two-table join returns no rows when one is expected
+
+create table t1(
+ cola varchar(50) not null,
+ colb varchar(8) not null,
+ colc varchar(12) not null,
+ cold varchar(2) not null,
+ primary key (cola, colb, cold));
+
+create table t2(
+ cola varchar(50) not null,
+ colb varchar(8) not null,
+ colc varchar(2) not null,
+ cold float,
+ primary key (cold));
+
+insert into t1 values ('aaaa', 'yyyy', 'yyyy-dd-mm', 'R');
+
+insert into t2 values ('aaaa', 'yyyy', 'R', 203), ('bbbb', 'zzzz', 'C', 201);
+
+prepare st_1676 from 'select a.cola, a.colb, a.cold from t1 a, t2 b where a.cola = ? and a.colb = ? and a.cold = ? and b.cola = a.cola and b.colb = a.colb and b.colc = a.cold';
+
+set @arg0= "aaaa";
+set @arg1= "yyyy";
+set @arg2= "R";
+
+execute st_1676 using @arg0, @arg1, @arg2;
+
+drop table t1, t2;
+
+# end of bug#1676
+
diff --git a/sql/examples/ha_example.cc b/sql/examples/ha_example.cc
index 097abd48e05..cb0780ea74d 100644
--- a/sql/examples/ha_example.cc
+++ b/sql/examples/ha_example.cc
@@ -263,8 +263,8 @@ int ha_example::write_row(byte * buf)
clause was used. Consecutive ordering is not guarenteed.
Currently new_data will not have an updated auto_increament record, or
and updated timestamp field. You can do these for example by doing these:
- if (table->timestamp_on_update_now)
- update_timestamp(new_row+table->timestamp_on_update_now-1);
+ if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
+ table->timestamp_field->set_time();
if (table->next_number_field && record == table->record[0])
update_auto_increment();
diff --git a/sql/examples/ha_tina.cc b/sql/examples/ha_tina.cc
index 06a19e478ae..0345a170c3c 100644
--- a/sql/examples/ha_tina.cc
+++ b/sql/examples/ha_tina.cc
@@ -428,8 +428,8 @@ int ha_tina::write_row(byte * buf)
statistic_increment(ha_write_count,&LOCK_status);
- if (table->timestamp_default_now)
- update_timestamp(buf+table->timestamp_default_now-1);
+ if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
+ table->timestamp_field->set_time();
size= encode_quote(buf);
@@ -464,8 +464,8 @@ int ha_tina::update_row(const byte * old_data, byte * new_data)
statistic_increment(ha_update_count,&LOCK_status);
- if (table->timestamp_default_now)
- update_timestamp(new_data+table->timestamp_default_now-1);
+ if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
+ table->timestamp_field->set_time();
size= encode_quote(new_data);
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index d748c005d02..28f95611ae7 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -5468,4 +5468,29 @@ innobase_get_at_most_n_mbchars(
}
}
+extern "C" {
+/**********************************************************************
+This function returns true if SQL-query in the current thread
+is either REPLACE or LOAD DATA INFILE REPLACE.
+NOTE that /mysql/innobase/row/row0ins.c must contain the
+prototype for this function ! */
+
+ibool
+innobase_query_is_replace(void)
+/*===========================*/
+{
+ THD* thd;
+
+ thd = (THD *)innobase_current_thd();
+
+ if ( thd->lex->sql_command == SQLCOM_REPLACE ||
+ ( thd->lex->sql_command == SQLCOM_LOAD &&
+ thd->lex->duplicates == DUP_REPLACE )) {
+ return true;
+ } else {
+ return false;
+ }
+}
+}
+
#endif /* HAVE_INNOBASE_DB */
diff --git a/sql/password.c b/sql/password.c
index 0ac91346a55..b9f3a07e596 100644
--- a/sql/password.c
+++ b/sql/password.c
@@ -35,7 +35,7 @@
update user set password=PASSWORD("hello") where user="test"
This saves a hashed number as a string in the password field.
- The new autentication is performed in following manner:
+ The new authentication is performed in following manner:
SERVER: public_seed=create_random_string()
send(public_seed)
diff --git a/strings/ctype-mb.c b/strings/ctype-mb.c
index a41449d5e50..e7527b418f5 100644
--- a/strings/ctype-mb.c
+++ b/strings/ctype-mb.c
@@ -123,8 +123,7 @@ int my_strcasecmp_mb(CHARSET_INFO * cs,const char *s, const char *t)
** 1 if matched with wildcard
*/
-#define INC_PTR(cs,A,B) A+=((use_mb_flag && \
- my_ismbchar(cs,A,B)) ? my_ismbchar(cs,A,B) : 1)
+#define INC_PTR(cs,A,B) A+=(my_ismbchar(cs,A,B) ? my_ismbchar(cs,A,B) : 1)
#define likeconv(s,A) (uchar) (s)->sort_order[(uchar) (A)]
@@ -135,8 +134,6 @@ int my_wildcmp_mb(CHARSET_INFO *cs,
{
int result= -1; /* Not found, using wildcards */
- bool use_mb_flag=use_mb(cs);
-
while (wildstr != wildend)
{
while (*wildstr != w_many && *wildstr != w_one)
@@ -144,8 +141,7 @@ int my_wildcmp_mb(CHARSET_INFO *cs,
int l;
if (*wildstr == escape && wildstr+1 != wildend)
wildstr++;
- if (use_mb_flag &&
- (l = my_ismbchar(cs, wildstr, wildend)))
+ if ((l = my_ismbchar(cs, wildstr, wildend)))
{
if (str+l > str_end || memcmp(str, wildstr, l) != 0)
return 1;
@@ -200,41 +196,30 @@ int my_wildcmp_mb(CHARSET_INFO *cs,
cmp= *++wildstr;
mb=wildstr;
- LINT_INIT(mblen);
- if (use_mb_flag)
- mblen = my_ismbchar(cs, wildstr, wildend);
+ mblen= my_ismbchar(cs, wildstr, wildend);
INC_PTR(cs,wildstr,wildend); /* This is compared trough cmp */
cmp=likeconv(cs,cmp);
do
{
- if (use_mb_flag)
- {
- for (;;)
+ for (;;)
+ {
+ if (str >= str_end)
+ return -1;
+ if (mblen)
{
- if (str >= str_end)
- return -1;
- if (mblen)
+ if (str+mblen <= str_end && memcmp(str, mb, mblen) == 0)
{
- if (str+mblen <= str_end && memcmp(str, mb, mblen) == 0)
- {
- str += mblen;
- break;
- }
- }
- else if (!my_ismbchar(cs, str, str_end) &&
- likeconv(cs,*str) == cmp)
- {
- str++;
+ str += mblen;
break;
}
- INC_PTR(cs,str, str_end);
}
- }
- else
- {
- while (str != str_end && likeconv(cs,*str) != cmp)
+ else if (!my_ismbchar(cs, str, str_end) &&
+ likeconv(cs,*str) == cmp)
+ {
str++;
- if (str++ == str_end) return (-1);
+ break;
+ }
+ INC_PTR(cs,str, str_end);
}
{
int tmp=my_wildcmp_mb(cs,str,str_end,wildstr,wildend,escape,w_one,
@@ -555,8 +540,6 @@ static int my_wildcmp_mb_bin(CHARSET_INFO *cs,
{
int result= -1; /* Not found, using wildcards */
- bool use_mb_flag=use_mb(cs);
-
while (wildstr != wildend)
{
while (*wildstr != w_many && *wildstr != w_one)
@@ -564,8 +547,7 @@ static int my_wildcmp_mb_bin(CHARSET_INFO *cs,
int l;
if (*wildstr == escape && wildstr+1 != wildend)
wildstr++;
- if (use_mb_flag &&
- (l = my_ismbchar(cs, wildstr, wildend)))
+ if ((l = my_ismbchar(cs, wildstr, wildend)))
{
if (str+l > str_end || memcmp(str, wildstr, l) != 0)
return 1;
@@ -620,39 +602,28 @@ static int my_wildcmp_mb_bin(CHARSET_INFO *cs,
cmp= *++wildstr;
mb=wildstr;
- LINT_INIT(mblen);
- if (use_mb_flag)
- mblen = my_ismbchar(cs, wildstr, wildend);
+ mblen= my_ismbchar(cs, wildstr, wildend);
INC_PTR(cs,wildstr,wildend); /* This is compared trough cmp */
do
{
- if (use_mb_flag)
- {
- for (;;)
+ for (;;)
+ {
+ if (str >= str_end)
+ return -1;
+ if (mblen)
{
- if (str >= str_end)
- return -1;
- if (mblen)
+ if (str+mblen <= str_end && memcmp(str, mb, mblen) == 0)
{
- if (str+mblen <= str_end && memcmp(str, mb, mblen) == 0)
- {
- str += mblen;
- break;
- }
- }
- else if (!my_ismbchar(cs, str, str_end) && *str == cmp)
- {
- str++;
+ str += mblen;
break;
}
- INC_PTR(cs,str, str_end);
}
- }
- else
- {
- while (str != str_end && *str != cmp)
+ else if (!my_ismbchar(cs, str, str_end) && *str == cmp)
+ {
str++;
- if (str++ == str_end) return (-1);
+ break;
+ }
+ INC_PTR(cs,str, str_end);
}
{
int tmp=my_wildcmp_mb_bin(cs,str,str_end,wildstr,wildend,escape,w_one,w_many);