mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
Fixed bugs found by pushbuild
Added code to detect and give error when doing an insert into a view where we accessed fields in a not yet read table Disabled test in subselect.test as the CHECK_OPTION for views doesn't work for insert. This needs to be fixed properly later. The problem with views are described in Bug #41760 Inserting into multiple-table views is not working mysql-test/r/insert.result: Fixed wrong usage of insert into view. mysql-test/r/subselect.result: Disabled wrong test (temporary) mysql-test/suite/maria/r/maria.result: Added test of size of table mysql-test/suite/maria/t/maria.test: Added test of size of table mysql-test/t/insert.test: Fixed wrong usage of insert into view The bug is that during insert/update we currently don't read any of the referenced tables of the view. This means that we can't get a value from another table to use as part of the update. mysql-test/t/subselect.test: Disabled not working test until someone has time to fix insert into view properly Here we where refering to last used value in t2, which is wrong. sql/sql_insert.cc: Detect if we are trying to update one table in a view based on value in another, not yet read, table. This fixes the problem discovered in insert.test storage/maria/ma_blockrec.c: Don't ignore not critical changes to the last page in the table. We need to write the last page as otherwise we can during aborting of a row with a duplicate key get state.data_file_length and the real length of file out of sync storage/maria/ma_check.c: Flush the page cache even if we got an error during zerofill. (This fixes a call to assert() in case of a too short data file) storage/maria/ma_pagecache.c: Mark page as read when we do a write of a full page. This fixes a bug when we got an error during read and then used direct write to page to update it storage/maria/ma_state.c: Restore info->lock.type after call to maria_versioning. Fixed crash in maria_recover.test storage/maria/maria_read_log.c: Don't write thread id in debug log. (Not needed as maria_read_log is a single treaded program)
This commit is contained in:
@ -355,17 +355,17 @@ insert into t2 values (1,12), (2,24);
|
||||
insert into v1 (f1) values (3) on duplicate key update f3= f3 + 10;
|
||||
ERROR HY000: Can not modify more than one base table through a join view 'test.v1'
|
||||
insert into v1 (f1) values (3) on duplicate key update f1= f3 + 10;
|
||||
ERROR HY000: Can not modify more than one base table through a join view 'test.v1'
|
||||
select * from t1;
|
||||
f1 f2
|
||||
1 11
|
||||
2 22
|
||||
3 NULL
|
||||
insert into v1 (f1) values (3) on duplicate key update f1= f3 + 10;
|
||||
ERROR HY000: Can not modify more than one base table through a join view 'test.v1'
|
||||
select * from t1;
|
||||
f1 f2
|
||||
1 11
|
||||
2 22
|
||||
12 NULL
|
||||
drop view v1;
|
||||
drop table t1,t2;
|
||||
create table t1 (id int primary key auto_increment, data int, unique(data));
|
||||
|
@ -4463,15 +4463,12 @@ SELECT t2.id, t2.c AS c FROM t1, t2
|
||||
WHERE t1.id=t2.id AND 1 IN (SELECT id FROM t1) WITH CHECK OPTION;
|
||||
INSERT INTO v2(a,b) VALUES (2,2);
|
||||
ERROR HY000: CHECK OPTION failed 'test.v2'
|
||||
INSERT INTO v2(a,b) VALUES (1,2);
|
||||
SELECT * FROM v1;
|
||||
c
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
2
|
||||
2
|
||||
CREATE VIEW v3 AS
|
||||
SELECT t2.c AS c FROM t2
|
||||
WHERE 1 IN (SELECT id FROM t1) WITH CHECK OPTION;
|
||||
|
@ -2589,4 +2589,7 @@ Warnings:
|
||||
Warning 1265 Data truncated for column 'c' at row 1
|
||||
insert into t1 values(1,repeat('a',100), repeat('b',657860));
|
||||
ERROR 23000: Duplicate entry '1' for key 'PRIMARY'
|
||||
check table t1;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 check status OK
|
||||
drop table t1;
|
||||
|
@ -1855,6 +1855,7 @@ create table t1(a int primary key, b blob, c blob) engine=maria;
|
||||
insert into t1 values(1,repeat('a',100), repeat('b',657860));
|
||||
--error ER_DUP_ENTRY
|
||||
insert into t1 values(1,repeat('a',100), repeat('b',657860));
|
||||
check table t1;
|
||||
drop table t1;
|
||||
|
||||
# Set defaults back
|
||||
|
@ -235,8 +235,10 @@ insert into t1 values (1,11), (2,22);
|
||||
insert into t2 values (1,12), (2,24);
|
||||
--error 1393
|
||||
insert into v1 (f1) values (3) on duplicate key update f3= f3 + 10;
|
||||
--error 1393
|
||||
insert into v1 (f1) values (3) on duplicate key update f1= f3 + 10;
|
||||
select * from t1;
|
||||
--error 1393
|
||||
insert into v1 (f1) values (3) on duplicate key update f1= f3 + 10;
|
||||
select * from t1;
|
||||
drop view v1;
|
||||
|
@ -3379,7 +3379,11 @@ CREATE VIEW v2 (a,b) AS
|
||||
|
||||
--error 1369
|
||||
INSERT INTO v2(a,b) VALUES (2,2);
|
||||
|
||||
# disabled for now as this refers to old content of t2
|
||||
--disable_parsing
|
||||
INSERT INTO v2(a,b) VALUES (1,2);
|
||||
--enable_parsing
|
||||
SELECT * FROM v1;
|
||||
|
||||
CREATE VIEW v3 AS
|
||||
|
@ -107,8 +107,8 @@ static bool check_view_insertability(THD *thd, TABLE_LIST *view);
|
||||
1 Error
|
||||
*/
|
||||
|
||||
bool check_view_single_update(List<Item> &fields, TABLE_LIST *view,
|
||||
table_map *map)
|
||||
bool check_view_single_update(List<Item> &fields, List<Item> &values,
|
||||
TABLE_LIST *view, table_map *map)
|
||||
{
|
||||
/* it is join view => we need to find the table for update */
|
||||
List_iterator_fast<Item> it(fields);
|
||||
@ -116,6 +116,10 @@ bool check_view_single_update(List<Item> &fields, TABLE_LIST *view,
|
||||
TABLE_LIST *tbl= 0; // reset for call to check_single_table()
|
||||
table_map tables= 0;
|
||||
|
||||
while ((item= it++))
|
||||
tables|= item->used_tables();
|
||||
|
||||
it.init(values);
|
||||
while ((item= it++))
|
||||
tables|= item->used_tables();
|
||||
|
||||
@ -238,7 +242,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list,
|
||||
|
||||
if (table_list->effective_algorithm == VIEW_ALGORITHM_MERGE)
|
||||
{
|
||||
if (check_view_single_update(fields, table_list, map))
|
||||
if (check_view_single_update(fields, values, table_list, map))
|
||||
return -1;
|
||||
table= table_list->table;
|
||||
}
|
||||
@ -298,7 +302,8 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list,
|
||||
*/
|
||||
|
||||
static int check_update_fields(THD *thd, TABLE_LIST *insert_table_list,
|
||||
List<Item> &update_fields, table_map *map)
|
||||
List<Item> &update_fields,
|
||||
List<Item> &update_values, table_map *map)
|
||||
{
|
||||
TABLE *table= insert_table_list->table;
|
||||
my_bool timestamp_mark;
|
||||
@ -320,7 +325,8 @@ static int check_update_fields(THD *thd, TABLE_LIST *insert_table_list,
|
||||
return -1;
|
||||
|
||||
if (insert_table_list->effective_algorithm == VIEW_ALGORITHM_MERGE &&
|
||||
check_view_single_update(update_fields, insert_table_list, map))
|
||||
check_view_single_update(update_fields, update_values, insert_table_list,
|
||||
map))
|
||||
return -1;
|
||||
|
||||
if (table->timestamp_field)
|
||||
@ -1246,7 +1252,8 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list,
|
||||
if (!res && duplic == DUP_UPDATE)
|
||||
{
|
||||
select_lex->no_wrap_view_item= TRUE;
|
||||
res= check_update_fields(thd, context->table_list, update_fields, &map);
|
||||
res= check_update_fields(thd, context->table_list, update_fields,
|
||||
update_values, &map);
|
||||
select_lex->no_wrap_view_item= FALSE;
|
||||
}
|
||||
|
||||
@ -2912,7 +2919,8 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
|
||||
|
||||
lex->select_lex.no_wrap_view_item= TRUE;
|
||||
res= res || check_update_fields(thd, context->table_list,
|
||||
*info.update_fields, &map);
|
||||
*info.update_fields, *info.update_values,
|
||||
&map);
|
||||
lex->select_lex.no_wrap_view_item= FALSE;
|
||||
/*
|
||||
When we are not using GROUP BY and there are no ungrouped aggregate functions
|
||||
@ -3580,7 +3588,7 @@ select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
|
||||
/* First field to copy */
|
||||
/* First field to copy */
|
||||
field= table->field+table->s->fields - values.elements;
|
||||
|
||||
/* Mark all fields that are given values */
|
||||
|
@ -2408,11 +2408,22 @@ static my_bool free_full_page_range(MARIA_HA *info, pgcache_page_no_t page,
|
||||
uint count)
|
||||
{
|
||||
my_bool res= 0;
|
||||
uint delete_count;
|
||||
MARIA_SHARE *share= info->s;
|
||||
DBUG_ENTER("free_full_page_range");
|
||||
|
||||
delete_count= count;
|
||||
if (share->state.state.data_file_length ==
|
||||
(page + count) * share->block_size)
|
||||
{
|
||||
/*
|
||||
Don't delete last page from pagecache as this will make the file
|
||||
shorter than expected if the last operation extended the file
|
||||
*/
|
||||
delete_count--;
|
||||
}
|
||||
if (pagecache_delete_pages(share->pagecache, &info->dfile,
|
||||
page, count, PAGECACHE_LOCK_WRITE, 0))
|
||||
page, delete_count, PAGECACHE_LOCK_WRITE, 0))
|
||||
res= 1;
|
||||
|
||||
if (share->now_transactional)
|
||||
|
@ -3249,7 +3249,7 @@ static my_bool maria_zerofill_data(HA_CHECK *param, MARIA_HA *info,
|
||||
pgcache_page_no_t page;
|
||||
uint block_size= share->block_size;
|
||||
MARIA_FILE_BITMAP *bitmap= &share->bitmap;
|
||||
my_bool zero_lsn= !(param->testflag & T_ZEROFILL_KEEP_LSN);
|
||||
my_bool zero_lsn= !(param->testflag & T_ZEROFILL_KEEP_LSN), error;
|
||||
DBUG_ENTER("maria_zerofill_data");
|
||||
|
||||
/* This works only with BLOCK_RECORD files */
|
||||
@ -3344,15 +3344,22 @@ static my_bool maria_zerofill_data(HA_CHECK *param, MARIA_HA *info,
|
||||
PAGECACHE_UNPIN, LSN_IMPOSSIBLE,
|
||||
LSN_IMPOSSIBLE, 1, FALSE);
|
||||
}
|
||||
DBUG_RETURN(_ma_bitmap_flush(share) ||
|
||||
flush_pagecache_blocks(share->pagecache, &info->dfile,
|
||||
FLUSH_FORCE_WRITE));
|
||||
error= _ma_bitmap_flush(share);
|
||||
if (flush_pagecache_blocks(share->pagecache, &info->dfile,
|
||||
FLUSH_FORCE_WRITE))
|
||||
error= 1;
|
||||
DBUG_RETURN(error);
|
||||
|
||||
err:
|
||||
pagecache_unlock_by_link(share->pagecache, page_link.link,
|
||||
PAGECACHE_LOCK_WRITE_UNLOCK,
|
||||
PAGECACHE_UNPIN, LSN_IMPOSSIBLE,
|
||||
LSN_IMPOSSIBLE, 0, FALSE);
|
||||
/* flush what was changed so far */
|
||||
(void) _ma_bitmap_flush(share);
|
||||
(void) flush_pagecache_blocks(share->pagecache, &info->dfile,
|
||||
FLUSH_FORCE_WRITE);
|
||||
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
|
@ -2974,7 +2974,11 @@ void pagecache_unlock_by_link(PAGECACHE *pagecache,
|
||||
}
|
||||
if (lsn != LSN_IMPOSSIBLE)
|
||||
check_and_set_lsn(pagecache, lsn, block);
|
||||
block->status&= ~PCBLOCK_ERROR;
|
||||
/*
|
||||
Reset error flag. Mark also that page is active; This may not have
|
||||
been the case if there was an error reading the page
|
||||
*/
|
||||
block->status= (block->status & ~PCBLOCK_ERROR) | PCBLOCK_READ;
|
||||
}
|
||||
|
||||
/* if we lock for write we must link the block to changed blocks */
|
||||
|
@ -616,10 +616,14 @@ void maria_versioning(MARIA_HA *info, my_bool versioning)
|
||||
/* For now, this is a hack */
|
||||
if (info->s->have_versioning)
|
||||
{
|
||||
enum thr_lock_type save_lock_type;
|
||||
/* Assume is a non threaded application (for now) */
|
||||
info->s->lock_key_trees= 0;
|
||||
/* Set up info->lock.type temporary for _ma_block_get_status() */
|
||||
save_lock_type= info->lock.type;
|
||||
info->lock.type= versioning ? TL_WRITE_CONCURRENT_INSERT : TL_WRITE;
|
||||
_ma_block_get_status((void*) info, versioning);
|
||||
info->lock.type= save_lock_type;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -23,9 +23,9 @@ static const char *load_default_groups[]= { "maria_read_log",0 };
|
||||
static void get_options(int *argc,char * * *argv);
|
||||
#ifndef DBUG_OFF
|
||||
#if defined(__WIN__)
|
||||
const char *default_dbug_option= "d:t:i:O,\\maria_read_log.trace";
|
||||
const char *default_dbug_option= "d:t:O,\\maria_read_log.trace";
|
||||
#else
|
||||
const char *default_dbug_option= "d:t:i:o,/tmp/maria_read_log.trace";
|
||||
const char *default_dbug_option= "d:t:o,/tmp/maria_read_log.trace";
|
||||
#endif
|
||||
#endif /* DBUG_OFF */
|
||||
static my_bool opt_display_only, opt_apply, opt_apply_undo, opt_silent;
|
||||
|
Reference in New Issue
Block a user