Merge MariaDB 5.2->5.3

This commit is contained in:
unknown 2012-11-20 13:57:49 +01:00
commit ecf04668a2
17 changed files with 223 additions and 46 deletions

View File

@ -1689,4 +1689,10 @@ SELECT length(CAST(b AS CHAR)) FROM ubig;
length(CAST(b AS CHAR)) length(CAST(b AS CHAR))
20 20
DROP TABLE ubig; DROP TABLE ubig;
select 1 from information_schema.tables where table_schema=repeat('a', 2000);
1
grant usage on *.* to mysqltest_1@localhost;
select 1 from information_schema.tables where table_schema=repeat('a', 2000);
1
drop user mysqltest_1@localhost;
End of 5.1 tests. End of 5.1 tests.

View File

@ -108,3 +108,44 @@ select * from t1;
drop table t1,t2; drop table t1,t2;
drop procedure p1; drop procedure p1;
--echo #
--echo # Bug mdev-3845: values of virtual columns are not computed for triggers
--echo #
CREATE TABLE t1 (
a INTEGER UNSIGNED NULL DEFAULT NULL,
b INTEGER UNSIGNED GENERATED ALWAYS AS (a) VIRTUAL
);
CREATE TABLE t2 (c INTEGER UNSIGNED NOT NULL);
DELIMITER |;
CREATE TRIGGER t1_ins_aft
AFTER INSERT
ON t1
FOR EACH ROW
BEGIN
INSERT INTO t2 (c) VALUES (NEW.b);
END |
CREATE TRIGGER t1_del_bef
BEFORE DELETE
ON t1
FOR EACH ROW
BEGIN
INSERT INTO t2 (c) VALUES (OLD.b);
END |
DELIMITER ;|
INSERT INTO t1 (a) VALUES (1), (2), (3);
SELECT * FROM t2;
DELETE FROM t1;
SELECT * FROM t2;
DROP TRIGGER t1_ins_aft;
DROP TRIGGER t1_del_bef;
DROP TABLE t1,t2;

View File

@ -85,3 +85,43 @@ a b c
300 30 30 300 30 30
drop table t1,t2; drop table t1,t2;
drop procedure p1; drop procedure p1;
#
# Bug mdev-3845: values of virtual columns are not computed for triggers
#
CREATE TABLE t1 (
a INTEGER UNSIGNED NULL DEFAULT NULL,
b INTEGER UNSIGNED GENERATED ALWAYS AS (a) VIRTUAL
);
CREATE TABLE t2 (c INTEGER UNSIGNED NOT NULL);
CREATE TRIGGER t1_ins_aft
AFTER INSERT
ON t1
FOR EACH ROW
BEGIN
INSERT INTO t2 (c) VALUES (NEW.b);
END |
CREATE TRIGGER t1_del_bef
BEFORE DELETE
ON t1
FOR EACH ROW
BEGIN
INSERT INTO t2 (c) VALUES (OLD.b);
END |
INSERT INTO t1 (a) VALUES (1), (2), (3);
SELECT * FROM t2;
c
1
2
3
DELETE FROM t1;
SELECT * FROM t2;
c
1
2
3
1
2
3
DROP TRIGGER t1_ins_aft;
DROP TRIGGER t1_del_bef;
DROP TABLE t1,t2;

View File

@ -85,3 +85,43 @@ a b c
300 30 30 300 30 30
drop table t1,t2; drop table t1,t2;
drop procedure p1; drop procedure p1;
#
# Bug mdev-3845: values of virtual columns are not computed for triggers
#
CREATE TABLE t1 (
a INTEGER UNSIGNED NULL DEFAULT NULL,
b INTEGER UNSIGNED GENERATED ALWAYS AS (a) VIRTUAL
);
CREATE TABLE t2 (c INTEGER UNSIGNED NOT NULL);
CREATE TRIGGER t1_ins_aft
AFTER INSERT
ON t1
FOR EACH ROW
BEGIN
INSERT INTO t2 (c) VALUES (NEW.b);
END |
CREATE TRIGGER t1_del_bef
BEFORE DELETE
ON t1
FOR EACH ROW
BEGIN
INSERT INTO t2 (c) VALUES (OLD.b);
END |
INSERT INTO t1 (a) VALUES (1), (2), (3);
SELECT * FROM t2;
c
1
2
3
DELETE FROM t1;
SELECT * FROM t2;
c
1
2
3
1
2
3
DROP TRIGGER t1_ins_aft;
DROP TRIGGER t1_del_bef;
DROP TABLE t1,t2;

View File

@ -1441,6 +1441,17 @@ SELECT length(CAST(b AS CHAR)) FROM ubig;
DROP TABLE ubig; DROP TABLE ubig;
#
# Bug #13889741: HANDLE_FATAL_SIGNAL IN _DB_ENTER_ | HANDLE_FATAL_SIGNAL IN STRNLEN
#
select 1 from information_schema.tables where table_schema=repeat('a', 2000);
grant usage on *.* to mysqltest_1@localhost;
connect (con1, localhost, mysqltest_1,,);
connection con1;
select 1 from information_schema.tables where table_schema=repeat('a', 2000);
connection default;
disconnect con1;
drop user mysqltest_1@localhost;
--echo End of 5.1 tests. --echo End of 5.1 tests.

View File

@ -35,7 +35,7 @@ void pack_dirname(char * to, const char *from)
int cwd_err; int cwd_err;
size_t d_length,length,UNINIT_VAR(buff_length); size_t d_length,length,UNINIT_VAR(buff_length);
char * start; char * start;
char buff[FN_REFLEN]; char buff[FN_REFLEN + 1];
DBUG_ENTER("pack_dirname"); DBUG_ENTER("pack_dirname");
(void) intern_filename(to,from); /* Change to intern name */ (void) intern_filename(to,from); /* Change to intern name */
@ -132,7 +132,7 @@ size_t cleanup_dirname(register char *to, const char *from)
reg3 char * from_ptr; reg3 char * from_ptr;
reg4 char * start; reg4 char * start;
char parent[5], /* for "FN_PARENTDIR" */ char parent[5], /* for "FN_PARENTDIR" */
buff[FN_REFLEN+1],*end_parentdir; buff[FN_REFLEN + 1],*end_parentdir;
#ifdef BACKSLASH_MBTAIL #ifdef BACKSLASH_MBTAIL
CHARSET_INFO *fs= fs_character_set(); CHARSET_INFO *fs= fs_character_set();
#endif #endif
@ -245,7 +245,7 @@ my_bool my_use_symdir=0; /* Set this if you want to use symdirs */
#ifdef USE_SYMDIR #ifdef USE_SYMDIR
void symdirget(char *dir) void symdirget(char *dir)
{ {
char buff[FN_REFLEN+1]; char buff[FN_REFLEN + 1];
char *pos=strend(dir); char *pos=strend(dir);
if (dir[0] && pos[-1] != FN_DEVCHAR && my_access(dir, F_OK)) if (dir[0] && pos[-1] != FN_DEVCHAR && my_access(dir, F_OK))
{ {
@ -295,7 +295,7 @@ void symdirget(char *dir)
size_t normalize_dirname(char *to, const char *from) size_t normalize_dirname(char *to, const char *from)
{ {
size_t length; size_t length;
char buff[FN_REFLEN]; char buff[FN_REFLEN + 1];
DBUG_ENTER("normalize_dirname"); DBUG_ENTER("normalize_dirname");
/* /*
@ -423,7 +423,7 @@ static char * NEAR_F expand_tilde(char * *path)
size_t unpack_filename(char * to, const char *from) size_t unpack_filename(char * to, const char *from)
{ {
size_t length, n_length, buff_length; size_t length, n_length, buff_length;
char buff[FN_REFLEN]; char buff[FN_REFLEN + 1];
DBUG_ENTER("unpack_filename"); DBUG_ENTER("unpack_filename");
length=dirname_part(buff, from, &buff_length);/* copy & convert dirname */ length=dirname_part(buff, from, &buff_length);/* copy & convert dirname */
@ -459,7 +459,7 @@ size_t system_filename(char * to, const char *from)
int libchar_found; int libchar_found;
size_t length; size_t length;
char * to_pos,from_pos,pos; char * to_pos,from_pos,pos;
char buff[FN_REFLEN]; char buff[FN_REFLEN + 1];
DBUG_ENTER("system_filename"); DBUG_ENTER("system_filename");
libchar_found=0; libchar_found=0;
@ -516,7 +516,7 @@ size_t system_filename(char * to, const char *from)
char *intern_filename(char *to, const char *from) char *intern_filename(char *to, const char *from)
{ {
size_t length, to_length; size_t length, to_length;
char buff[FN_REFLEN]; char buff[FN_REFLEN + 1];
if (from == to) if (from == to)
{ /* Dirname may destroy from */ { /* Dirname may destroy from */
strmov(buff,from); strmov(buff,from);

View File

@ -258,18 +258,21 @@ int Url_http::send(const char* data, size_t data_length)
Extract the first string between <h1>...</h1> tags Extract the first string between <h1>...</h1> tags
and put it as a server reply into the error log. and put it as a server reply into the error log.
*/ */
len= 0;
for (;;) for (;;)
{ {
size_t i= vio_read(vio, (uchar*)buf + len, sizeof(buf) - len - 1); size_t i= sizeof(buf) - len - 1;
if (i)
i= vio_read(vio, (uchar*)buf + len, i);
if ((int)i <= 0) if ((int)i <= 0)
break; break;
len+= i; len+= i;
} }
if (len && len < sizeof(buf)) if (len)
{ {
char *from; char *from;
buf[len+1]= 0; // safety buf[len]= 0; // safety
if ((from= strstr(buf, "<h1>"))) if ((from= strstr(buf, "<h1>")))
{ {

View File

@ -6322,8 +6322,9 @@ int TC_LOG_MMAP::open(const char *opt_name)
syncing= 0; syncing= 0;
active=pages; active=pages;
DBUG_ASSERT(npages >= 2);
pool=pages+1; pool=pages+1;
pool_last=pages+npages-1; pool_last_ptr= &((pages+npages-1)->next);
commit_ordered_queue= NULL; commit_ordered_queue= NULL;
commit_ordered_queue_busy= false; commit_ordered_queue_busy= false;
@ -6356,8 +6357,8 @@ void TC_LOG_MMAP::get_active_from_pool()
do do
{ {
best_p= p= &pool; best_p= p= &pool;
if ((*p)->waiters == 0) // can the first page be used ? if ((*p)->waiters == 0 && (*p)->free > 0) // can the first page be used ?
break; // yes - take it. break; // yes - take it.
best_free=0; // no - trying second strategy best_free=0; // no - trying second strategy
for (p=&(*p)->next; *p; p=&(*p)->next) for (p=&(*p)->next; *p; p=&(*p)->next)
@ -6374,10 +6375,10 @@ void TC_LOG_MMAP::get_active_from_pool()
safe_mutex_assert_owner(&LOCK_active); safe_mutex_assert_owner(&LOCK_active);
active=*best_p; active=*best_p;
if ((*best_p)->next) // unlink the page from the pool /* Unlink the page from the pool. */
*best_p=(*best_p)->next; if (!(*best_p)->next)
else pool_last_ptr= best_p;
pool_last=*best_p; *best_p=(*best_p)->next;
pthread_mutex_unlock(&LOCK_pool); pthread_mutex_unlock(&LOCK_pool);
pthread_mutex_lock(&active->lock); pthread_mutex_lock(&active->lock);
@ -6484,12 +6485,9 @@ int TC_LOG_MMAP::log_one_transaction(my_xid xid)
pthread_mutex_unlock(&LOCK_active); pthread_mutex_unlock(&LOCK_active);
pthread_mutex_lock(&p->lock); pthread_mutex_lock(&p->lock);
p->waiters++; p->waiters++;
for (;;) while (p->state == DIRTY && syncing)
{ {
int not_dirty = p->state != DIRTY;
pthread_mutex_unlock(&p->lock); pthread_mutex_unlock(&p->lock);
if (not_dirty || !syncing)
break;
pthread_cond_wait(&p->cond, &LOCK_sync); pthread_cond_wait(&p->cond, &LOCK_sync);
pthread_mutex_lock(&p->lock); pthread_mutex_lock(&p->lock);
} }
@ -6541,8 +6539,8 @@ int TC_LOG_MMAP::sync()
/* page is synced. let's move it to the pool */ /* page is synced. let's move it to the pool */
pthread_mutex_lock(&LOCK_pool); pthread_mutex_lock(&LOCK_pool);
pool_last->next=syncing; (*pool_last_ptr)=syncing;
pool_last=syncing; pool_last_ptr=&(syncing->next);
syncing->next=0; syncing->next=0;
syncing->state= err ? ERROR : POOL; syncing->state= err ? ERROR : POOL;
pthread_cond_signal(&COND_pool); // in case somebody's waiting pthread_cond_signal(&COND_pool); // in case somebody's waiting

View File

@ -129,7 +129,7 @@ class TC_LOG_MMAP: public TC_LOG
my_off_t file_length; my_off_t file_length;
uint npages, inited; uint npages, inited;
uchar *data; uchar *data;
struct st_page *pages, *syncing, *active, *pool, *pool_last; struct st_page *pages, *syncing, *active, *pool, **pool_last_ptr;
/* /*
note that, e.g. LOCK_active is only used to protect note that, e.g. LOCK_active is only used to protect
'active' pointer, to protect the content of the active page 'active' pointer, to protect the content of the active page

View File

@ -1517,7 +1517,8 @@ find_field_in_table(THD *thd, TABLE *table, const char *name, uint length,
bool allow_rowid, uint *cached_field_index_ptr); bool allow_rowid, uint *cached_field_index_ptr);
Field * Field *
find_field_in_table_sef(TABLE *table, const char *name); find_field_in_table_sef(TABLE *table, const char *name);
int update_virtual_fields(THD *thd, TABLE *table, bool ignore_stored= FALSE); int update_virtual_fields(THD *thd, TABLE *table,
enum enum_vcol_update_mode vcol_update_mode= VCOL_UPDATE_FOR_READ);
int dynamic_column_error_message(enum_dyncol_func_result rc); int dynamic_column_error_message(enum_dyncol_func_result rc);
#endif /* MYSQL_SERVER */ #endif /* MYSQL_SERVER */

View File

@ -1352,14 +1352,20 @@ ulong acl_get(const char *host, const char *ip,
acl_entry *entry; acl_entry *entry;
DBUG_ENTER("acl_get"); DBUG_ENTER("acl_get");
VOID(pthread_mutex_lock(&acl_cache->lock)); tmp_db= strmov(strmov(key, ip ? ip : "") + 1, user) + 1;
end=strmov((tmp_db=strmov(strmov(key, ip ? ip : "")+1,user)+1),db); end= strnmov(tmp_db, db, key + sizeof(key) - tmp_db);
if (end >= key + sizeof(key)) // db name was truncated
DBUG_RETURN(0); // no privileges for an invalid db name
if (lower_case_table_names) if (lower_case_table_names)
{ {
my_casedn_str(files_charset_info, tmp_db); my_casedn_str(files_charset_info, tmp_db);
db=tmp_db; db=tmp_db;
} }
key_length= (size_t) (end-key); key_length= (size_t) (end-key);
VOID(pthread_mutex_lock(&acl_cache->lock));
if (!db_is_pattern && (entry=(acl_entry*) acl_cache->search((uchar*) key, if (!db_is_pattern && (entry=(acl_entry*) acl_cache->search((uchar*) key,
key_length))) key_length)))
{ {
@ -4365,11 +4371,17 @@ static bool check_grant_db_routine(THD *thd, const char *db, HASH *hash)
bool check_grant_db(THD *thd,const char *db) bool check_grant_db(THD *thd,const char *db)
{ {
Security_context *sctx= thd->security_ctx; Security_context *sctx= thd->security_ctx;
char helping [SAFE_NAME_LEN + USERNAME_LENGTH+2]; char helping [SAFE_NAME_LEN + USERNAME_LENGTH+2], *end;
uint len; uint len;
bool error= TRUE; bool error= TRUE;
len= (uint) (strmov(strmov(helping, sctx->priv_user) + 1, db) - helping) + 1; end= strmov(helping, sctx->priv_user) + 1;
end= strnmov(end, db, helping + sizeof(helping) - end);
if (end >= helping + sizeof(helping)) // db name was truncated
return 1; // no privileges for an invalid db name
len= (uint) (end - helping) + 1;
rw_rdlock(&LOCK_grant); rw_rdlock(&LOCK_grant);

View File

@ -8707,7 +8707,9 @@ fill_record(THD * thd, List<Item> &fields, List<Item> &values,
/* Update virtual fields*/ /* Update virtual fields*/
thd->abort_on_warning= FALSE; thd->abort_on_warning= FALSE;
if (vcol_table && vcol_table->vfield && if (vcol_table && vcol_table->vfield &&
update_virtual_fields(thd, vcol_table, TRUE)) update_virtual_fields(thd, vcol_table,
vcol_table->triggers ? VCOL_UPDATE_ALL :
VCOL_UPDATE_FOR_WRITE))
goto err; goto err;
thd->abort_on_warning= save_abort_on_warning; thd->abort_on_warning= save_abort_on_warning;
thd->no_errors= save_no_errors; thd->no_errors= save_no_errors;
@ -8772,7 +8774,9 @@ fill_record_n_invoke_before_triggers(THD *thd, List<Item> &fields,
if (item_field && item_field->field && if (item_field && item_field->field &&
(table= item_field->field->table) && (table= item_field->field->table) &&
table->vfield) table->vfield)
result= update_virtual_fields(thd, table, TRUE); result= update_virtual_fields(thd, table,
table->triggers ? VCOL_UPDATE_ALL :
VCOL_UPDATE_FOR_WRITE);
} }
} }
return result; return result;
@ -8856,7 +8860,10 @@ fill_record(THD *thd, Field **ptr, List<Item> &values, bool ignore_errors,
} }
/* Update virtual fields*/ /* Update virtual fields*/
thd->abort_on_warning= FALSE; thd->abort_on_warning= FALSE;
if (table->vfield && update_virtual_fields(thd, table, TRUE)) if (table->vfield &&
update_virtual_fields(thd, table,
table->triggers ? VCOL_UPDATE_ALL :
VCOL_UPDATE_FOR_WRITE))
goto err; goto err;
thd->abort_on_warning= abort_on_warning_saved; thd->abort_on_warning= abort_on_warning_saved;
DBUG_RETURN(thd->is_error()); DBUG_RETURN(thd->is_error());
@ -8909,7 +8916,9 @@ fill_record_n_invoke_before_triggers(THD *thd, Field **ptr,
{ {
TABLE *table= (*ptr)->table; TABLE *table= (*ptr)->table;
if (table->vfield) if (table->vfield)
result= update_virtual_fields(thd, table, TRUE); result= update_virtual_fields(thd, table,
table->triggers ? VCOL_UPDATE_ALL :
VCOL_UPDATE_FOR_WRITE);
} }
return result; return result;

View File

@ -333,7 +333,9 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
! thd->is_error()) ! thd->is_error())
{ {
if (table->vfield) if (table->vfield)
update_virtual_fields(thd, table); update_virtual_fields(thd, table,
triggers_applicable ? VCOL_UPDATE_ALL :
VCOL_UPDATE_FOR_READ);
thd->examined_row_count++; thd->examined_row_count++;
// thd->is_error() is tested to disallow delete row on error // thd->is_error() is tested to disallow delete row on error
if (!select || select->skip_record(thd) > 0) if (!select || select->skip_record(thd) > 0)

View File

@ -8109,7 +8109,7 @@ copy_data_between_tables(THD *thd, TABLE *from,TABLE *to,
} }
prev_insert_id= to->file->next_insert_id; prev_insert_id= to->file->next_insert_id;
if (to->vfield) if (to->vfield)
update_virtual_fields(thd, to, TRUE); update_virtual_fields(thd, to, VCOL_UPDATE_FOR_WRITE);
if (thd->is_error()) if (thd->is_error())
{ {
error= 1; error= 1;

View File

@ -507,7 +507,9 @@ int mysql_update(THD *thd,
while (!(error=info.read_record(&info)) && !thd->killed) while (!(error=info.read_record(&info)) && !thd->killed)
{ {
if (table->vfield) if (table->vfield)
update_virtual_fields(thd, table); update_virtual_fields(thd, table,
table->triggers ? VCOL_UPDATE_ALL :
VCOL_UPDATE_FOR_READ);
thd->examined_row_count++; thd->examined_row_count++;
if (!select || (error= select->skip_record(thd)) > 0) if (!select || (error= select->skip_record(thd)) > 0)
{ {
@ -623,7 +625,9 @@ int mysql_update(THD *thd,
while (!(error=info.read_record(&info)) && !thd->killed) while (!(error=info.read_record(&info)) && !thd->killed)
{ {
if (table->vfield) if (table->vfield)
update_virtual_fields(thd, table); update_virtual_fields(thd, table,
table->triggers ? VCOL_UPDATE_ALL :
VCOL_UPDATE_FOR_READ);
thd->examined_row_count++; thd->examined_row_count++;
if (!select || select->skip_record(thd) > 0) if (!select || select->skip_record(thd) > 0)
{ {

View File

@ -5801,14 +5801,16 @@ size_t max_row_length(TABLE *table, const uchar *data)
@param thd Thread handle @param thd Thread handle
@param table The TABLE object @param table The TABLE object
@param for_write Requests to compute only fields needed for write @param vcol_update_mode Specifies what virtual column are computed
@details @details
The function computes the values of the virtual columns of the table and The function computes the values of the virtual columns of the table and
stores them in the table record buffer. stores them in the table record buffer.
Only fields from vcol_set are computed, and, when the flag for_write is not If vcol_update_mode is set to VCOL_UPDATE_ALL then all virtual column are
set to TRUE, a virtual field is computed only if it's not stored. computed. Otherwise, only fields from vcol_set are computed: all of them,
The flag for_write is set to TRUE for row insert/update operations. if vcol_update_mode is set to VCOL_UPDATE_FOR_WRITE, and, only those with
the stored_in_db flag set to false, if vcol_update_mode is equal to
VCOL_UPDATE_FOR_READ.
@retval @retval
0 Success 0 Success
@ -5816,7 +5818,8 @@ size_t max_row_length(TABLE *table, const uchar *data)
>0 Error occurred when storing a virtual field value >0 Error occurred when storing a virtual field value
*/ */
int update_virtual_fields(THD *thd, TABLE *table, bool for_write) int update_virtual_fields(THD *thd, TABLE *table,
enum enum_vcol_update_mode vcol_update_mode)
{ {
DBUG_ENTER("update_virtual_fields"); DBUG_ENTER("update_virtual_fields");
Field **vfield_ptr, *vfield; Field **vfield_ptr, *vfield;
@ -5829,9 +5832,9 @@ int update_virtual_fields(THD *thd, TABLE *table, bool for_write)
{ {
vfield= (*vfield_ptr); vfield= (*vfield_ptr);
DBUG_ASSERT(vfield->vcol_info && vfield->vcol_info->expr_item); DBUG_ASSERT(vfield->vcol_info && vfield->vcol_info->expr_item);
/* Only update those fields that are marked in the vcol_set bitmap */ if ((bitmap_is_set(table->vcol_set, vfield->field_index) &&
if (bitmap_is_set(table->vcol_set, vfield->field_index) && (vcol_update_mode == VCOL_UPDATE_FOR_WRITE || !vfield->stored_in_db)) ||
(for_write || !vfield->stored_in_db)) vcol_update_mode == VCOL_UPDATE_ALL)
{ {
/* Compute the actual value of the virtual fields */ /* Compute the actual value of the virtual fields */
error= vfield->vcol_info->expr_item->save_in_field(vfield, 0); error= vfield->vcol_info->expr_item->save_in_field(vfield, 0);

View File

@ -157,6 +157,13 @@ enum frm_type_enum
enum release_type { RELEASE_NORMAL, RELEASE_WAIT_FOR_DROP }; enum release_type { RELEASE_NORMAL, RELEASE_WAIT_FOR_DROP };
enum enum_vcol_update_mode
{
VCOL_UPDATE_FOR_READ= 0,
VCOL_UPDATE_FOR_WRITE,
VCOL_UPDATE_ALL
};
typedef struct st_filesort_info typedef struct st_filesort_info
{ {
IO_CACHE *io_cache; /* If sorted through filesort */ IO_CACHE *io_cache; /* If sorted through filesort */