diff options
author | unknown <knielsen@knielsen-hq.org> | 2012-11-20 13:57:49 +0100 |
---|---|---|
committer | unknown <knielsen@knielsen-hq.org> | 2012-11-20 13:57:49 +0100 |
commit | ecf04668a2db3d7fc91e421e68eeb5ab25064aa0 (patch) | |
tree | 67fb1a5b050c913ad21f9c30628ff3ef0fd81f2c | |
parent | dd2d59924e06afb29e36a6dda56f6fb393ef6c6e (diff) | |
parent | cbae294396429682a22371f23a048dcd0d4c71da (diff) | |
download | mariadb-git-ecf04668a2db3d7fc91e421e68eeb5ab25064aa0.tar.gz |
Merge MariaDB 5.2->5.3
-rw-r--r-- | mysql-test/r/information_schema.result | 6 | ||||
-rw-r--r-- | mysql-test/suite/vcol/inc/vcol_trigger_sp.inc | 41 | ||||
-rw-r--r-- | mysql-test/suite/vcol/r/vcol_trigger_sp_innodb.result | 40 | ||||
-rw-r--r-- | mysql-test/suite/vcol/r/vcol_trigger_sp_myisam.result | 40 | ||||
-rw-r--r-- | mysql-test/t/information_schema.test | 11 | ||||
-rw-r--r-- | mysys/mf_pack.c | 14 | ||||
-rw-r--r-- | plugin/feedback/url_http.cc | 9 | ||||
-rw-r--r-- | sql/log.cc | 24 | ||||
-rw-r--r-- | sql/log.h | 2 | ||||
-rw-r--r-- | sql/mysql_priv.h | 3 | ||||
-rw-r--r-- | sql/sql_acl.cc | 20 | ||||
-rw-r--r-- | sql/sql_base.cc | 17 | ||||
-rw-r--r-- | sql/sql_delete.cc | 4 | ||||
-rw-r--r-- | sql/sql_table.cc | 2 | ||||
-rw-r--r-- | sql/sql_update.cc | 8 | ||||
-rw-r--r-- | sql/table.cc | 21 | ||||
-rw-r--r-- | sql/table.h | 7 |
17 files changed, 223 insertions, 46 deletions
diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result index 886b6f4d7f3..a9dd69ef698 100644 --- a/mysql-test/r/information_schema.result +++ b/mysql-test/r/information_schema.result @@ -1689,4 +1689,10 @@ SELECT length(CAST(b AS CHAR)) FROM ubig; length(CAST(b AS CHAR)) 20 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. diff --git a/mysql-test/suite/vcol/inc/vcol_trigger_sp.inc b/mysql-test/suite/vcol/inc/vcol_trigger_sp.inc index ddf13fef6a1..eb7e6ad32b9 100644 --- a/mysql-test/suite/vcol/inc/vcol_trigger_sp.inc +++ b/mysql-test/suite/vcol/inc/vcol_trigger_sp.inc @@ -108,3 +108,44 @@ select * from t1; drop table t1,t2; 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; + diff --git a/mysql-test/suite/vcol/r/vcol_trigger_sp_innodb.result b/mysql-test/suite/vcol/r/vcol_trigger_sp_innodb.result index e903bc4eafd..1d78bbf50e4 100644 --- a/mysql-test/suite/vcol/r/vcol_trigger_sp_innodb.result +++ b/mysql-test/suite/vcol/r/vcol_trigger_sp_innodb.result @@ -85,3 +85,43 @@ a b c 300 30 30 drop table t1,t2; 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; diff --git a/mysql-test/suite/vcol/r/vcol_trigger_sp_myisam.result b/mysql-test/suite/vcol/r/vcol_trigger_sp_myisam.result index c2a66d656b5..77efa8fe6b9 100644 --- a/mysql-test/suite/vcol/r/vcol_trigger_sp_myisam.result +++ b/mysql-test/suite/vcol/r/vcol_trigger_sp_myisam.result @@ -85,3 +85,43 @@ a b c 300 30 30 drop table t1,t2; 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; diff --git a/mysql-test/t/information_schema.test b/mysql-test/t/information_schema.test index e1962255cf6..616b22245f3 100644 --- a/mysql-test/t/information_schema.test +++ b/mysql-test/t/information_schema.test @@ -1441,6 +1441,17 @@ SELECT length(CAST(b AS CHAR)) FROM 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. diff --git a/mysys/mf_pack.c b/mysys/mf_pack.c index 86fd61537e7..e6b576b6d96 100644 --- a/mysys/mf_pack.c +++ b/mysys/mf_pack.c @@ -35,7 +35,7 @@ void pack_dirname(char * to, const char *from) int cwd_err; size_t d_length,length,UNINIT_VAR(buff_length); char * start; - char buff[FN_REFLEN]; + char buff[FN_REFLEN + 1]; DBUG_ENTER("pack_dirname"); (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; reg4 char * start; char parent[5], /* for "FN_PARENTDIR" */ - buff[FN_REFLEN+1],*end_parentdir; + buff[FN_REFLEN + 1],*end_parentdir; #ifdef BACKSLASH_MBTAIL CHARSET_INFO *fs= fs_character_set(); #endif @@ -245,7 +245,7 @@ my_bool my_use_symdir=0; /* Set this if you want to use symdirs */ #ifdef USE_SYMDIR void symdirget(char *dir) { - char buff[FN_REFLEN+1]; + char buff[FN_REFLEN + 1]; char *pos=strend(dir); 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 length; - char buff[FN_REFLEN]; + char buff[FN_REFLEN + 1]; 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 length, n_length, buff_length; - char buff[FN_REFLEN]; + char buff[FN_REFLEN + 1]; DBUG_ENTER("unpack_filename"); 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; size_t length; char * to_pos,from_pos,pos; - char buff[FN_REFLEN]; + char buff[FN_REFLEN + 1]; DBUG_ENTER("system_filename"); libchar_found=0; @@ -516,7 +516,7 @@ size_t system_filename(char * to, const char *from) char *intern_filename(char *to, const char *from) { size_t length, to_length; - char buff[FN_REFLEN]; + char buff[FN_REFLEN + 1]; if (from == to) { /* Dirname may destroy from */ strmov(buff,from); diff --git a/plugin/feedback/url_http.cc b/plugin/feedback/url_http.cc index 71b67a52807..b0028292707 100644 --- a/plugin/feedback/url_http.cc +++ b/plugin/feedback/url_http.cc @@ -258,18 +258,21 @@ int Url_http::send(const char* data, size_t data_length) Extract the first string between <h1>...</h1> tags and put it as a server reply into the error log. */ + len= 0; 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) break; len+= i; } - if (len && len < sizeof(buf)) + if (len) { char *from; - buf[len+1]= 0; // safety + buf[len]= 0; // safety if ((from= strstr(buf, "<h1>"))) { diff --git a/sql/log.cc b/sql/log.cc index 05e8a66ed04..1aea7a33e0d 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -6322,8 +6322,9 @@ int TC_LOG_MMAP::open(const char *opt_name) syncing= 0; active=pages; + DBUG_ASSERT(npages >= 2); pool=pages+1; - pool_last=pages+npages-1; + pool_last_ptr= &((pages+npages-1)->next); commit_ordered_queue= NULL; commit_ordered_queue_busy= false; @@ -6356,8 +6357,8 @@ void TC_LOG_MMAP::get_active_from_pool() do { best_p= p= &pool; - if ((*p)->waiters == 0) // can the first page be used ? - break; // yes - take it. + if ((*p)->waiters == 0 && (*p)->free > 0) // can the first page be used ? + break; // yes - take it. best_free=0; // no - trying second strategy 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); active=*best_p; - if ((*best_p)->next) // unlink the page from the pool - *best_p=(*best_p)->next; - else - pool_last=*best_p; + /* Unlink the page from the pool. */ + if (!(*best_p)->next) + pool_last_ptr= best_p; + *best_p=(*best_p)->next; pthread_mutex_unlock(&LOCK_pool); 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_lock(&p->lock); p->waiters++; - for (;;) + while (p->state == DIRTY && syncing) { - int not_dirty = p->state != DIRTY; pthread_mutex_unlock(&p->lock); - if (not_dirty || !syncing) - break; pthread_cond_wait(&p->cond, &LOCK_sync); pthread_mutex_lock(&p->lock); } @@ -6541,8 +6539,8 @@ int TC_LOG_MMAP::sync() /* page is synced. let's move it to the pool */ pthread_mutex_lock(&LOCK_pool); - pool_last->next=syncing; - pool_last=syncing; + (*pool_last_ptr)=syncing; + pool_last_ptr=&(syncing->next); syncing->next=0; syncing->state= err ? ERROR : POOL; pthread_cond_signal(&COND_pool); // in case somebody's waiting diff --git a/sql/log.h b/sql/log.h index bfa63b79ffe..156a8e6f1b6 100644 --- a/sql/log.h +++ b/sql/log.h @@ -129,7 +129,7 @@ class TC_LOG_MMAP: public TC_LOG my_off_t file_length; uint npages, inited; 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 'active' pointer, to protect the content of the active page diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 5f20e9f0591..78f77db597b 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -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); Field * 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); #endif /* MYSQL_SERVER */ diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 81e9bc8c46f..0e6ad5dfbf1 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -1352,14 +1352,20 @@ ulong acl_get(const char *host, const char *ip, acl_entry *entry; DBUG_ENTER("acl_get"); - VOID(pthread_mutex_lock(&acl_cache->lock)); - end=strmov((tmp_db=strmov(strmov(key, ip ? ip : "")+1,user)+1),db); + tmp_db= strmov(strmov(key, ip ? ip : "") + 1, user) + 1; + 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) { my_casedn_str(files_charset_info, tmp_db); db=tmp_db; } 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, 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) { 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; 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); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index e93e4fb3b67..0fd92189937 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -8707,7 +8707,9 @@ fill_record(THD * thd, List<Item> &fields, List<Item> &values, /* Update virtual fields*/ thd->abort_on_warning= FALSE; 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; thd->abort_on_warning= save_abort_on_warning; 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 && (table= item_field->field->table) && 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; @@ -8856,7 +8860,10 @@ fill_record(THD *thd, Field **ptr, List<Item> &values, bool ignore_errors, } /* Update virtual fields*/ 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; thd->abort_on_warning= abort_on_warning_saved; DBUG_RETURN(thd->is_error()); @@ -8909,7 +8916,9 @@ fill_record_n_invoke_before_triggers(THD *thd, Field **ptr, { TABLE *table= (*ptr)->table; 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; diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 24b1828b177..480868241f7 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -333,7 +333,9 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ! thd->is_error()) { 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->is_error() is tested to disallow delete row on error if (!select || select->skip_record(thd) > 0) diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 7f5df6a0958..7c125e18cde 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -8109,7 +8109,7 @@ copy_data_between_tables(THD *thd, TABLE *from,TABLE *to, } prev_insert_id= to->file->next_insert_id; if (to->vfield) - update_virtual_fields(thd, to, TRUE); + update_virtual_fields(thd, to, VCOL_UPDATE_FOR_WRITE); if (thd->is_error()) { error= 1; diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 7d6eb62f57d..9d00118f450 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -507,7 +507,9 @@ int mysql_update(THD *thd, while (!(error=info.read_record(&info)) && !thd->killed) { 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++; 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) { 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++; if (!select || select->skip_record(thd) > 0) { diff --git a/sql/table.cc b/sql/table.cc index faa248f43f6..d42fd14120c 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -5801,22 +5801,25 @@ size_t max_row_length(TABLE *table, const uchar *data) @param thd Thread handle @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 The function computes the values of the virtual columns of the table and stores them in the table record buffer. - Only fields from vcol_set are computed, and, when the flag for_write is not - set to TRUE, a virtual field is computed only if it's not stored. - The flag for_write is set to TRUE for row insert/update operations. - + If vcol_update_mode is set to VCOL_UPDATE_ALL then all virtual column are + computed. Otherwise, only fields from vcol_set are computed: all of them, + 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 0 Success @retval >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"); Field **vfield_ptr, *vfield; @@ -5829,9 +5832,9 @@ int update_virtual_fields(THD *thd, TABLE *table, bool for_write) { vfield= (*vfield_ptr); 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) && - (for_write || !vfield->stored_in_db)) + if ((bitmap_is_set(table->vcol_set, vfield->field_index) && + (vcol_update_mode == VCOL_UPDATE_FOR_WRITE || !vfield->stored_in_db)) || + vcol_update_mode == VCOL_UPDATE_ALL) { /* Compute the actual value of the virtual fields */ error= vfield->vcol_info->expr_item->save_in_field(vfield, 0); diff --git a/sql/table.h b/sql/table.h index a2d3aa73f7e..d66a6a44753 100644 --- a/sql/table.h +++ b/sql/table.h @@ -157,6 +157,13 @@ enum frm_type_enum 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 { IO_CACHE *io_cache; /* If sorted through filesort */ |