Commit ab266824 authored by unknown's avatar unknown

Merge bk-internal:/home/bk/mysql-5.0

into serg.mylan:/usr/home/serg/Abk/mysql-5.0


sql/sql_parse.cc:
  Auto merged
parents ba2c213b eec84895
...@@ -845,7 +845,8 @@ extern char *get_charsets_dir(char *buf); ...@@ -845,7 +845,8 @@ extern char *get_charsets_dir(char *buf);
extern my_bool my_charset_same(CHARSET_INFO *cs1, CHARSET_INFO *cs2); extern my_bool my_charset_same(CHARSET_INFO *cs1, CHARSET_INFO *cs2);
extern my_bool init_compiled_charsets(myf flags); extern my_bool init_compiled_charsets(myf flags);
extern void add_compiled_collation(CHARSET_INFO *cs); extern void add_compiled_collation(CHARSET_INFO *cs);
extern ulong escape_string_for_mysql(CHARSET_INFO *charset_info, char *to, extern ulong escape_string_for_mysql(CHARSET_INFO *charset_info,
char *to, ulong to_length,
const char *from, ulong length); const char *from, ulong length);
extern void thd_increment_bytes_sent(ulong length); extern void thd_increment_bytes_sent(ulong length);
......
...@@ -390,8 +390,9 @@ struct trx_struct{ ...@@ -390,8 +390,9 @@ struct trx_struct{
dulint table_id; /* table id if the preceding field is dulint table_id; /* table id if the preceding field is
TRUE */ TRUE */
/*------------------------------*/ /*------------------------------*/
int active_trans; /* whether a transaction in MySQL int active_trans; /* 1 - if a transaction in MySQL
is active */ is active. 2 - if prepare_commit_mutex
was taken */
void* mysql_thd; /* MySQL thread handle corresponding void* mysql_thd; /* MySQL thread handle corresponding
to this trx, or NULL */ to this trx, or NULL */
char** mysql_query_str;/* pointer to the field in mysqld_thd char** mysql_query_str;/* pointer to the field in mysqld_thd
......
...@@ -1575,14 +1575,14 @@ mysql_hex_string(char *to, const char *from, ulong length) ...@@ -1575,14 +1575,14 @@ mysql_hex_string(char *to, const char *from, ulong length)
ulong STDCALL ulong STDCALL
mysql_escape_string(char *to,const char *from,ulong length) mysql_escape_string(char *to,const char *from,ulong length)
{ {
return escape_string_for_mysql(default_charset_info, to, from, length); return escape_string_for_mysql(default_charset_info, to, 0, from, length);
} }
ulong STDCALL ulong STDCALL
mysql_real_escape_string(MYSQL *mysql, char *to,const char *from, mysql_real_escape_string(MYSQL *mysql, char *to,const char *from,
ulong length) ulong length)
{ {
return escape_string_for_mysql(mysql->charset, to, from, length); return escape_string_for_mysql(mysql->charset, to, 0, from, length);
} }
......
...@@ -10,3 +10,4 @@ create temporary table mysqltest.t2 (n int); ...@@ -10,3 +10,4 @@ create temporary table mysqltest.t2 (n int);
show status like 'Slave_open_temp_tables'; show status like 'Slave_open_temp_tables';
Variable_name Value Variable_name Value
Slave_open_temp_tables 0 Slave_open_temp_tables 0
drop database mysqltest;
...@@ -11,3 +11,6 @@ disconnect master; ...@@ -11,3 +11,6 @@ disconnect master;
connection slave; connection slave;
--real_sleep 3; # time for DROP to be written --real_sleep 3; # time for DROP to be written
show status like 'Slave_open_temp_tables'; show status like 'Slave_open_temp_tables';
connection default;
drop database mysqltest;
...@@ -561,21 +561,34 @@ CHARSET_INFO *get_charset_by_csname(const char *cs_name, ...@@ -561,21 +561,34 @@ CHARSET_INFO *get_charset_by_csname(const char *cs_name,
DBUG_RETURN(cs); DBUG_RETURN(cs);
} }
/*
ulong escape_string_for_mysql(CHARSET_INFO *charset_info, char *to, NOTE
to keep old C API, to_length may be 0 to mean "big enough"
RETURN
the length of the escaped string or ~0 if it did not fit.
*/
ulong escape_string_for_mysql(CHARSET_INFO *charset_info,
char *to, ulong to_length,
const char *from, ulong length) const char *from, ulong length)
{ {
const char *to_start= to; const char *to_start= to;
const char *end; const char *end, *to_end=to_start + (to_length ? to_length-1 : 2*length);
my_bool overflow=0;
#ifdef USE_MB #ifdef USE_MB
my_bool use_mb_flag= use_mb(charset_info); my_bool use_mb_flag= use_mb(charset_info);
#endif #endif
for (end= from + length; from != end; from++) for (end= from + length; from < end; from++)
{ {
char escape=0;
#ifdef USE_MB #ifdef USE_MB
int l; int l;
if (use_mb_flag && (l= my_ismbchar(charset_info, from, end))) if (use_mb_flag && (l= my_ismbchar(charset_info, from, end)))
{ {
if (to + l >= to_end)
{
overflow=1;
break;
}
while (l--) while (l--)
*to++= *from++; *to++= *from++;
from--; from--;
...@@ -593,45 +606,53 @@ ulong escape_string_for_mysql(CHARSET_INFO *charset_info, char *to, ...@@ -593,45 +606,53 @@ ulong escape_string_for_mysql(CHARSET_INFO *charset_info, char *to,
a valid GBK character, but 0xbf5c is. (0x27 = ', 0x5c = \) a valid GBK character, but 0xbf5c is. (0x27 = ', 0x5c = \)
*/ */
if (use_mb_flag && (l= my_mbcharlen(charset_info, *from)) > 1) if (use_mb_flag && (l= my_mbcharlen(charset_info, *from)) > 1)
{ escape= *from;
*to++= '\\'; else
*to++= *from;
continue;
}
#endif #endif
switch (*from) { switch (*from) {
case 0: /* Must be escaped for 'mysql' */ case 0: /* Must be escaped for 'mysql' */
*to++= '\\'; escape= '0';
*to++= '0';
break; break;
case '\n': /* Must be escaped for logs */ case '\n': /* Must be escaped for logs */
*to++= '\\'; escape= 'n';
*to++= 'n';
break; break;
case '\r': case '\r':
*to++= '\\'; escape= 'r';
*to++= 'r';
break; break;
case '\\': case '\\':
*to++= '\\'; escape= '\\';
*to++= '\\';
break; break;
case '\'': case '\'':
*to++= '\\'; escape= '\'';
*to++= '\'';
break; break;
case '"': /* Better safe than sorry */ case '"': /* Better safe than sorry */
*to++= '\\'; escape= '"';
*to++= '"';
break; break;
case '\032': /* This gives problems on Win32 */ case '\032': /* This gives problems on Win32 */
escape= 'Z';
break;
}
if (escape)
{
if (to + 2 >= to_end)
{
overflow=1;
break;
}
*to++= '\\'; *to++= '\\';
*to++= 'Z'; *to++= escape;
}
else
{
if (to + 1 >= to_end)
{
overflow=1;
break; break;
default: }
*to++= *from; *to++= *from;
} }
} }
*to= 0; *to= 0;
return (ulong) (to - to_start); return overflow ? (ulong)~0 : (ulong) (to - to_start);
} }
...@@ -752,25 +752,22 @@ bool Field::quote_data(String *unquoted_string) ...@@ -752,25 +752,22 @@ bool Field::quote_data(String *unquoted_string)
{ {
char escaped_string[IO_SIZE]; char escaped_string[IO_SIZE];
char *unquoted_string_buffer= (char *)(unquoted_string->ptr()); char *unquoted_string_buffer= (char *)(unquoted_string->ptr());
uint need_quotes;
DBUG_ENTER("Field::quote_data"); DBUG_ENTER("Field::quote_data");
// this is the same call that mysql_real_escape_string() calls if (!needs_quotes())
escape_string_for_mysql(&my_charset_bin, (char *)escaped_string,
unquoted_string->ptr(), unquoted_string->length());
need_quotes= needs_quotes();
if (need_quotes == 0)
DBUG_RETURN(0); DBUG_RETURN(0);
// this is the same call that mysql_real_escape_string() calls
if (escape_string_for_mysql(&my_charset_bin, (char *)escaped_string,
sizeof(escaped_string), unquoted_string->ptr(),
unquoted_string->length()) == (ulong)~0)
DBUG_RETURN(1);
// reset string, then re-append with quotes and escaped values // reset string, then re-append with quotes and escaped values
unquoted_string->length(0); unquoted_string->length(0);
if (unquoted_string->append('\'')) if (unquoted_string->append('\'') ||
DBUG_RETURN(1); unquoted_string->append((char *)escaped_string) ||
if (unquoted_string->append((char *)escaped_string)) unquoted_string->append('\''))
DBUG_RETURN(1);
if (unquoted_string->append('\''))
DBUG_RETURN(1); DBUG_RETURN(1);
DBUG_RETURN(0); DBUG_RETURN(0);
} }
......
...@@ -469,6 +469,7 @@ static int check_foreign_data_source(FEDERATED_SHARE *share) ...@@ -469,6 +469,7 @@ static int check_foreign_data_source(FEDERATED_SHARE *share)
*/ */
query.append("SHOW TABLES LIKE '"); query.append("SHOW TABLES LIKE '");
escape_string_for_mysql(&my_charset_bin, (char *)escaped_table_base_name, escape_string_for_mysql(&my_charset_bin, (char *)escaped_table_base_name,
sizeof(escaped_table_base_name),
share->table_base_name, share->table_base_name,
share->table_base_name_length); share->table_base_name_length);
query.append(escaped_table_base_name); query.append(escaped_table_base_name);
......
...@@ -45,7 +45,8 @@ have disables the InnoDB inlining in this file. */ ...@@ -45,7 +45,8 @@ have disables the InnoDB inlining in this file. */
#include "ha_innodb.h" #include "ha_innodb.h"
pthread_mutex_t innobase_mutex; pthread_mutex_t innobase_share_mutex, // to protect innobase_open_files
prepare_commit_mutex; // to force correct commit order in binlog
bool innodb_inited= 0; bool innodb_inited= 0;
/* Store MySQL definition of 'byte': in Linux it is char while InnoDB /* Store MySQL definition of 'byte': in Linux it is char while InnoDB
...@@ -1268,7 +1269,8 @@ innobase_init(void) ...@@ -1268,7 +1269,8 @@ innobase_init(void)
(void) hash_init(&innobase_open_tables,system_charset_info, 32, 0, 0, (void) hash_init(&innobase_open_tables,system_charset_info, 32, 0, 0,
(hash_get_key) innobase_get_key, 0, 0); (hash_get_key) innobase_get_key, 0, 0);
pthread_mutex_init(&innobase_mutex, MY_MUTEX_INIT_FAST); pthread_mutex_init(&innobase_share_mutex, MY_MUTEX_INIT_FAST);
pthread_mutex_init(&prepare_commit_mutex, MY_MUTEX_INIT_FAST);
innodb_inited= 1; innodb_inited= 1;
/* If this is a replication slave and we needed to do a crash recovery, /* If this is a replication slave and we needed to do a crash recovery,
...@@ -1322,7 +1324,8 @@ innobase_end(void) ...@@ -1322,7 +1324,8 @@ innobase_end(void)
hash_free(&innobase_open_tables); hash_free(&innobase_open_tables);
my_free(internal_innobase_data_file_path, my_free(internal_innobase_data_file_path,
MYF(MY_ALLOW_ZERO_PTR)); MYF(MY_ALLOW_ZERO_PTR));
pthread_mutex_destroy(&innobase_mutex); pthread_mutex_destroy(&innobase_share_mutex);
pthread_mutex_destroy(&prepare_commit_mutex);
} }
DBUG_RETURN(err); DBUG_RETURN(err);
...@@ -1480,9 +1483,20 @@ innobase_commit( ...@@ -1480,9 +1483,20 @@ innobase_commit(
/* We were instructed to commit the whole transaction, or /* We were instructed to commit the whole transaction, or
this is an SQL statement end and autocommit is on */ this is an SQL statement end and autocommit is on */
/* We need current binlog position for ibbackup to work.
Note, the position is current because of prepare_commit_mutex */
trx->mysql_log_file_name = mysql_bin_log.get_log_fname();
trx->mysql_log_offset =
(ib_longlong)mysql_bin_log.get_log_file()->pos_in_file;
innobase_commit_low(trx); innobase_commit_low(trx);
if (trx->active_trans == 2) {
pthread_mutex_unlock(&prepare_commit_mutex);
}
trx->active_trans = 0; trx->active_trans = 0;
} else { } else {
/* We just mark the SQL statement ended and do not do a /* We just mark the SQL statement ended and do not do a
transaction commit */ transaction commit */
...@@ -5953,7 +5967,7 @@ static mysql_byte* innobase_get_key(INNOBASE_SHARE *share,uint *length, ...@@ -5953,7 +5967,7 @@ static mysql_byte* innobase_get_key(INNOBASE_SHARE *share,uint *length,
static INNOBASE_SHARE *get_share(const char *table_name) static INNOBASE_SHARE *get_share(const char *table_name)
{ {
INNOBASE_SHARE *share; INNOBASE_SHARE *share;
pthread_mutex_lock(&innobase_mutex); pthread_mutex_lock(&innobase_share_mutex);
uint length=(uint) strlen(table_name); uint length=(uint) strlen(table_name);
if (!(share=(INNOBASE_SHARE*) hash_search(&innobase_open_tables, if (!(share=(INNOBASE_SHARE*) hash_search(&innobase_open_tables,
(mysql_byte*) table_name, (mysql_byte*) table_name,
...@@ -5967,7 +5981,7 @@ static INNOBASE_SHARE *get_share(const char *table_name) ...@@ -5967,7 +5981,7 @@ static INNOBASE_SHARE *get_share(const char *table_name)
strmov(share->table_name,table_name); strmov(share->table_name,table_name);
if (my_hash_insert(&innobase_open_tables, (mysql_byte*) share)) if (my_hash_insert(&innobase_open_tables, (mysql_byte*) share))
{ {
pthread_mutex_unlock(&innobase_mutex); pthread_mutex_unlock(&innobase_share_mutex);
my_free((gptr) share,0); my_free((gptr) share,0);
return 0; return 0;
} }
...@@ -5976,13 +5990,13 @@ static INNOBASE_SHARE *get_share(const char *table_name) ...@@ -5976,13 +5990,13 @@ static INNOBASE_SHARE *get_share(const char *table_name)
} }
} }
share->use_count++; share->use_count++;
pthread_mutex_unlock(&innobase_mutex); pthread_mutex_unlock(&innobase_share_mutex);
return share; return share;
} }
static void free_share(INNOBASE_SHARE *share) static void free_share(INNOBASE_SHARE *share)
{ {
pthread_mutex_lock(&innobase_mutex); pthread_mutex_lock(&innobase_share_mutex);
if (!--share->use_count) if (!--share->use_count)
{ {
hash_delete(&innobase_open_tables, (mysql_byte*) share); hash_delete(&innobase_open_tables, (mysql_byte*) share);
...@@ -5990,7 +6004,7 @@ static void free_share(INNOBASE_SHARE *share) ...@@ -5990,7 +6004,7 @@ static void free_share(INNOBASE_SHARE *share)
pthread_mutex_destroy(&share->mutex); pthread_mutex_destroy(&share->mutex);
my_free((gptr) share, MYF(0)); my_free((gptr) share, MYF(0));
} }
pthread_mutex_unlock(&innobase_mutex); pthread_mutex_unlock(&innobase_share_mutex);
} }
/********************************************************************* /*********************************************************************
...@@ -6454,15 +6468,38 @@ innobase_xa_prepare( ...@@ -6454,15 +6468,38 @@ innobase_xa_prepare(
FALSE - the current SQL statement ended */ FALSE - the current SQL statement ended */
{ {
int error = 0; int error = 0;
trx_t* trx; trx_t* trx = check_trx_exists(thd);
if (thd->lex->sql_command != SQLCOM_XA_PREPARE) {
/* For ibbackup to work the order of transactions in binlog
and InnoDB must be the same. Consider the situation
thread1> prepare; write to binlog; ...
<context switch>
thread2> prepare; write to binlog; commit
thread1> ... commit
To ensure this will not happen we're taking the mutex on
prepare, and releasing it on commit.
Note: only do it for normal commits, done via ha_commit_trans.
If 2pc protocol is executed by external transaction
coordinator, it will be just a regular MySQL client
executing XA PREPARE and XA COMMIT commands.
In this case we cannot know how many minutes or hours
will be between XA PREPARE and XA COMMIT, and we don't want
to block for undefined period of time.
*/
pthread_mutex_lock(&prepare_commit_mutex);
trx->active_trans = 2;
}
if (!thd->variables.innodb_support_xa) { if (!thd->variables.innodb_support_xa) {
return(0); return(0);
} }
trx = check_trx_exists(thd);
trx->xid=thd->transaction.xid; trx->xid=thd->transaction.xid;
/* Release a possible FIFO ticket and search latch. Since we will /* Release a possible FIFO ticket and search latch. Since we will
......
...@@ -526,7 +526,6 @@ void trans_register_ha(THD *thd, bool all, handlerton *ht_arg) ...@@ -526,7 +526,6 @@ void trans_register_ha(THD *thd, bool all, handlerton *ht_arg)
/* /*
RETURN RETURN
-1 - cannot prepare
0 - ok 0 - ok
1 - error, transaction was rolled back 1 - error, transaction was rolled back
*/ */
...@@ -539,8 +538,6 @@ int ha_prepare(THD *thd) ...@@ -539,8 +538,6 @@ int ha_prepare(THD *thd)
#ifdef USING_TRANSACTIONS #ifdef USING_TRANSACTIONS
if (trans->nht) if (trans->nht)
{ {
if (trans->no_2pc)
DBUG_RETURN(-1);
for (; *ht; ht++) for (; *ht; ht++)
{ {
int err; int err;
......
...@@ -2050,7 +2050,7 @@ const String *Item_param::query_val_str(String* str) const ...@@ -2050,7 +2050,7 @@ const String *Item_param::query_val_str(String* str) const
buf= str->c_ptr_quick(); buf= str->c_ptr_quick();
ptr= buf; ptr= buf;
*ptr++= '\''; *ptr++= '\'';
ptr+= escape_string_for_mysql(str_value.charset(), ptr, ptr+= escape_string_for_mysql(str_value.charset(), ptr, 0,
str_value.ptr(), str_value.length()); str_value.ptr(), str_value.length());
*ptr++= '\''; *ptr++= '\'';
str->length(ptr - buf); str->length(ptr - buf);
......
...@@ -1720,7 +1720,7 @@ void Item_func_coalesce::fix_length_and_dec() ...@@ -1720,7 +1720,7 @@ void Item_func_coalesce::fix_length_and_dec()
decimals= 0; decimals= 0;
break; break;
case ROW_RESULT: case ROW_RESULT:
defaullt: default:
DBUG_ASSERT(0); DBUG_ASSERT(0);
} }
} }
......
...@@ -2012,6 +2012,7 @@ int Format_description_log_event::exec_event(struct st_relay_log_info* rli) ...@@ -2012,6 +2012,7 @@ int Format_description_log_event::exec_event(struct st_relay_log_info* rli)
delete rli->relay_log.description_event_for_exec; delete rli->relay_log.description_event_for_exec;
rli->relay_log.description_event_for_exec= this; rli->relay_log.description_event_for_exec= this;
#ifdef USING_TRANSACTIONS
/* /*
As a transaction NEVER spans on 2 or more binlogs: As a transaction NEVER spans on 2 or more binlogs:
if we have an active transaction at this point, the master died if we have an active transaction at this point, the master died
...@@ -2033,6 +2034,7 @@ int Format_description_log_event::exec_event(struct st_relay_log_info* rli) ...@@ -2033,6 +2034,7 @@ int Format_description_log_event::exec_event(struct st_relay_log_info* rli)
"to its binary log."); "to its binary log.");
end_trans(thd, ROLLBACK); end_trans(thd, ROLLBACK);
} }
#endif
/* /*
If this event comes from ourselves, there is no cleaning task to perform, If this event comes from ourselves, there is no cleaning task to perform,
we don't call Start_log_event_v3::exec_event() (this was just to update the we don't call Start_log_event_v3::exec_event() (this was just to update the
......
...@@ -865,7 +865,7 @@ static bool insert_params_from_vars_with_log(Prepared_statement *stmt, ...@@ -865,7 +865,7 @@ static bool insert_params_from_vars_with_log(Prepared_statement *stmt,
*ptr++= '\''; *ptr++= '\'';
ptr+= ptr+=
escape_string_for_mysql(&my_charset_utf8_general_ci, escape_string_for_mysql(&my_charset_utf8_general_ci,
ptr, entry->name.str, entry->name.length); ptr, 0, entry->name.str, entry->name.length);
*ptr++= '\''; *ptr++= '\'';
str.length(ptr - buf); str.length(ptr - buf);
......
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