Commit 910284e6 authored by Michael Widenius's avatar Michael Widenius

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)
parent ee4ddd8e
......@@ -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;
......
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