Merge chilla.local:/home/mydev/mysql-5.1-ateam
into chilla.local:/home/mydev/mysql-5.1-bug28810
This commit is contained in:
commit
653c2937bc
@ -1,4 +1,6 @@
|
|||||||
DROP TABLE IF EXISTS t1;
|
DROP TABLE IF EXISTS t1;
|
||||||
|
DROP TABLE IF EXISTS t2;
|
||||||
|
DROP TABLE IF EXISTS t3;
|
||||||
CREATE TABLE t1 (
|
CREATE TABLE t1 (
|
||||||
pk1 INT NOT NULL PRIMARY KEY,
|
pk1 INT NOT NULL PRIMARY KEY,
|
||||||
b INT NOT NULL,
|
b INT NOT NULL,
|
||||||
@ -40,3 +42,47 @@ pk1 b c
|
|||||||
12 2 2
|
12 2 2
|
||||||
14 1 1
|
14 1 1
|
||||||
DROP TABLE IF EXISTS t1;
|
DROP TABLE IF EXISTS t1;
|
||||||
|
CREATE TABLE t1 (a int, b int, KEY (a, b)) ENGINE=ndbcluster;
|
||||||
|
CREATE TABLE t2 (a int, b int, UNIQUE KEY (a, b)) ENGINE=ndbcluster;
|
||||||
|
CREATE TABLE t3 (a int, b int, PRIMARY KEY (a, b)) ENGINE=ndbcluster;
|
||||||
|
INSERT INTO t1 VALUES (1, 2);
|
||||||
|
INSERT INTO t1 VALUES (2, 2);
|
||||||
|
INSERT INTO t2 VALUES (1, 2);
|
||||||
|
INSERT INTO t2 VALUES (2, 2);
|
||||||
|
INSERT INTO t3 VALUES (1, 2);
|
||||||
|
INSERT INTO t3 VALUES (2, 2);
|
||||||
|
UPDATE t1 SET a = 1;
|
||||||
|
UPDATE t1 SET a = 1 ORDER BY a;
|
||||||
|
UPDATE t2 SET a = 1;
|
||||||
|
ERROR 23000: Duplicate entry '' for key '*UNKNOWN*'
|
||||||
|
UPDATE t2 SET a = 1 ORDER BY a;
|
||||||
|
ERROR 23000: Duplicate entry '' for key '*UNKNOWN*'
|
||||||
|
UPDATE t3 SET a = 1;
|
||||||
|
ERROR 23000: Duplicate entry '1-2' for key 'PRIMARY'
|
||||||
|
UPDATE t3 SET a = 1 ORDER BY a;
|
||||||
|
ERROR 23000: Duplicate entry '1-2' for key 'PRIMARY'
|
||||||
|
SELECT count(*) FROM t1;
|
||||||
|
count(*)
|
||||||
|
2
|
||||||
|
SELECT count(*) FROM t2;
|
||||||
|
count(*)
|
||||||
|
2
|
||||||
|
SELECT count(*) FROM t3;
|
||||||
|
count(*)
|
||||||
|
2
|
||||||
|
SELECT * FROM t1 ORDER by a;
|
||||||
|
a b
|
||||||
|
1 2
|
||||||
|
1 2
|
||||||
|
SELECT * FROM t2 ORDER by a;
|
||||||
|
a b
|
||||||
|
1 2
|
||||||
|
2 2
|
||||||
|
SELECT * FROM t3 ORDER by a;
|
||||||
|
a b
|
||||||
|
1 2
|
||||||
|
2 2
|
||||||
|
DROP TABLE IF EXISTS t1;
|
||||||
|
DROP TABLE IF EXISTS t2;
|
||||||
|
DROP TABLE IF EXISTS t3;
|
||||||
|
End of 5.1 tests
|
||||||
|
@ -3,10 +3,12 @@
|
|||||||
|
|
||||||
--disable_warnings
|
--disable_warnings
|
||||||
DROP TABLE IF EXISTS t1;
|
DROP TABLE IF EXISTS t1;
|
||||||
|
DROP TABLE IF EXISTS t2;
|
||||||
|
DROP TABLE IF EXISTS t3;
|
||||||
--enable_warnings
|
--enable_warnings
|
||||||
|
|
||||||
#
|
#
|
||||||
# Basic test of INSERT in NDB
|
# Basic test of UPDATE in NDB
|
||||||
#
|
#
|
||||||
|
|
||||||
#
|
#
|
||||||
@ -39,3 +41,49 @@ DROP TABLE IF EXISTS t1;
|
|||||||
--enable_warnings
|
--enable_warnings
|
||||||
|
|
||||||
# End of 4.1 tests
|
# End of 4.1 tests
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug#28158: table->read_set is set incorrectly,
|
||||||
|
# causing wrong error message in Falcon
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 (a int, b int, KEY (a, b)) ENGINE=ndbcluster;
|
||||||
|
CREATE TABLE t2 (a int, b int, UNIQUE KEY (a, b)) ENGINE=ndbcluster;
|
||||||
|
CREATE TABLE t3 (a int, b int, PRIMARY KEY (a, b)) ENGINE=ndbcluster;
|
||||||
|
#
|
||||||
|
INSERT INTO t1 VALUES (1, 2);
|
||||||
|
INSERT INTO t1 VALUES (2, 2);
|
||||||
|
#
|
||||||
|
INSERT INTO t2 VALUES (1, 2);
|
||||||
|
INSERT INTO t2 VALUES (2, 2);
|
||||||
|
#
|
||||||
|
INSERT INTO t3 VALUES (1, 2);
|
||||||
|
INSERT INTO t3 VALUES (2, 2);
|
||||||
|
#
|
||||||
|
UPDATE t1 SET a = 1;
|
||||||
|
UPDATE t1 SET a = 1 ORDER BY a;
|
||||||
|
#
|
||||||
|
--error ER_DUP_ENTRY
|
||||||
|
UPDATE t2 SET a = 1;
|
||||||
|
--error ER_DUP_ENTRY
|
||||||
|
UPDATE t2 SET a = 1 ORDER BY a;
|
||||||
|
#
|
||||||
|
--error ER_DUP_ENTRY
|
||||||
|
UPDATE t3 SET a = 1;
|
||||||
|
--error ER_DUP_ENTRY
|
||||||
|
UPDATE t3 SET a = 1 ORDER BY a;
|
||||||
|
#
|
||||||
|
SELECT count(*) FROM t1;
|
||||||
|
SELECT count(*) FROM t2;
|
||||||
|
SELECT count(*) FROM t3;
|
||||||
|
SELECT * FROM t1 ORDER by a;
|
||||||
|
SELECT * FROM t2 ORDER by a;
|
||||||
|
SELECT * FROM t3 ORDER by a;
|
||||||
|
#
|
||||||
|
--disable_warnings
|
||||||
|
DROP TABLE IF EXISTS t1;
|
||||||
|
DROP TABLE IF EXISTS t2;
|
||||||
|
DROP TABLE IF EXISTS t3;
|
||||||
|
--enable_warnings
|
||||||
|
|
||||||
|
--echo End of 5.1 tests
|
||||||
|
|
||||||
|
@ -83,6 +83,75 @@ static bool check_fields(THD *thd, List<Item> &items)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Re-read record if more columns are needed for error message.
|
||||||
|
|
||||||
|
@detail If we got a duplicate key error, we want to write an error
|
||||||
|
message containing the value of the duplicate key. If we do not have
|
||||||
|
all fields of the key value in record[0], we need to re-read the
|
||||||
|
record with a proper read_set.
|
||||||
|
|
||||||
|
@param[in] error error number
|
||||||
|
@param[in] table table
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void prepare_record_for_error_message(int error, TABLE *table)
|
||||||
|
{
|
||||||
|
Field **field_p;
|
||||||
|
Field *field;
|
||||||
|
uint keynr;
|
||||||
|
MY_BITMAP unique_map; /* Fields in offended unique. */
|
||||||
|
my_bitmap_map unique_map_buf[bitmap_buffer_size(MAX_FIELDS)];
|
||||||
|
DBUG_ENTER("prepare_record_for_error_message");
|
||||||
|
|
||||||
|
/*
|
||||||
|
Only duplicate key errors print the key value.
|
||||||
|
If storage engine does always read all columns, we have the value alraedy.
|
||||||
|
*/
|
||||||
|
if ((error != HA_ERR_FOUND_DUPP_KEY) ||
|
||||||
|
!(table->file->ha_table_flags() & HA_PARTIAL_COLUMN_READ))
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Get the number of the offended index.
|
||||||
|
We will see MAX_KEY if the engine cannot determine the affected index.
|
||||||
|
*/
|
||||||
|
if ((keynr= table->file->get_dup_key(error)) >= MAX_KEY)
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
|
|
||||||
|
/* Create unique_map with all fields used by that index. */
|
||||||
|
bitmap_init(&unique_map, unique_map_buf, table->s->fields, FALSE);
|
||||||
|
table->mark_columns_used_by_index_no_reset(keynr, &unique_map);
|
||||||
|
|
||||||
|
/* Subtract read_set and write_set. */
|
||||||
|
bitmap_subtract(&unique_map, table->read_set);
|
||||||
|
bitmap_subtract(&unique_map, table->write_set);
|
||||||
|
|
||||||
|
/*
|
||||||
|
If the unique index uses columns that are neither in read_set
|
||||||
|
nor in write_set, we must re-read the record.
|
||||||
|
Otherwise no need to do anything.
|
||||||
|
*/
|
||||||
|
if (bitmap_is_clear_all(&unique_map))
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
|
|
||||||
|
/* Get identifier of last read record into table->file->ref. */
|
||||||
|
table->file->position(table->record[0]);
|
||||||
|
/* Add all fields used by unique index to read_set. */
|
||||||
|
bitmap_union(table->read_set, &unique_map);
|
||||||
|
/* Tell the engine about the new set. */
|
||||||
|
table->file->column_bitmaps_signal();
|
||||||
|
/* Read record that is identified by table->file->ref. */
|
||||||
|
(void) table->file->rnd_pos(table->record[1], table->file->ref);
|
||||||
|
/* Copy the newly read columns into the new record. */
|
||||||
|
for (field_p= table->field; (field= *field_p); field_p++)
|
||||||
|
if (bitmap_is_set(&unique_map, field->field_index))
|
||||||
|
field->copy_from_tmp(table->s->rec_buff_length);
|
||||||
|
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Process usual UPDATE
|
Process usual UPDATE
|
||||||
|
|
||||||
@ -470,6 +539,13 @@ int mysql_update(THD *thd,
|
|||||||
else
|
else
|
||||||
will_batch= !table->file->start_bulk_update();
|
will_batch= !table->file->start_bulk_update();
|
||||||
|
|
||||||
|
/*
|
||||||
|
Assure that we can use position()
|
||||||
|
if we need to create an error message.
|
||||||
|
*/
|
||||||
|
if (table->file->ha_table_flags() & HA_PARTIAL_COLUMN_READ)
|
||||||
|
table->prepare_for_position();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
We can use compare_record() to optimize away updates if
|
We can use compare_record() to optimize away updates if
|
||||||
the table handler is returning all columns OR if
|
the table handler is returning all columns OR if
|
||||||
@ -573,6 +649,8 @@ int mysql_update(THD *thd,
|
|||||||
*/
|
*/
|
||||||
if (table->file->is_fatal_error(error, HA_CHECK_DUP_KEY))
|
if (table->file->is_fatal_error(error, HA_CHECK_DUP_KEY))
|
||||||
thd->fatal_error(); /* Other handler errors are fatal */
|
thd->fatal_error(); /* Other handler errors are fatal */
|
||||||
|
|
||||||
|
prepare_record_for_error_message(error, table);
|
||||||
table->file->print_error(error,MYF(0));
|
table->file->print_error(error,MYF(0));
|
||||||
error= 1;
|
error= 1;
|
||||||
break;
|
break;
|
||||||
@ -596,13 +674,16 @@ int mysql_update(THD *thd,
|
|||||||
{
|
{
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
|
/* purecov: begin inspected */
|
||||||
/*
|
/*
|
||||||
The handler should not report error of duplicate keys if they
|
The handler should not report error of duplicate keys if they
|
||||||
are ignored. This is a requirement on batching handlers.
|
are ignored. This is a requirement on batching handlers.
|
||||||
*/
|
*/
|
||||||
|
prepare_record_for_error_message(error, table);
|
||||||
table->file->print_error(error,MYF(0));
|
table->file->print_error(error,MYF(0));
|
||||||
error= 1;
|
error= 1;
|
||||||
break;
|
break;
|
||||||
|
/* purecov: end */
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
Either an error was found and we are ignoring errors or there
|
Either an error was found and we are ignoring errors or there
|
||||||
@ -668,9 +749,12 @@ int mysql_update(THD *thd,
|
|||||||
in the batched update.
|
in the batched update.
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
|
/* purecov: begin inspected */
|
||||||
thd->fatal_error();
|
thd->fatal_error();
|
||||||
|
prepare_record_for_error_message(loc_error, table);
|
||||||
table->file->print_error(loc_error,MYF(0));
|
table->file->print_error(loc_error,MYF(0));
|
||||||
error= 1;
|
error= 1;
|
||||||
|
/* purecov: end */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
updated-= dup_key_found;
|
updated-= dup_key_found;
|
||||||
@ -1540,6 +1624,8 @@ bool multi_update::send_data(List<Item> ¬_used_values)
|
|||||||
*/
|
*/
|
||||||
if (table->file->is_fatal_error(error, HA_CHECK_DUP_KEY))
|
if (table->file->is_fatal_error(error, HA_CHECK_DUP_KEY))
|
||||||
thd->fatal_error(); /* Other handler errors are fatal */
|
thd->fatal_error(); /* Other handler errors are fatal */
|
||||||
|
|
||||||
|
prepare_record_for_error_message(error, table);
|
||||||
table->file->print_error(error,MYF(0));
|
table->file->print_error(error,MYF(0));
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
@ -1676,7 +1762,7 @@ int multi_update::do_updates(bool from_send_error)
|
|||||||
ha_rows org_updated;
|
ha_rows org_updated;
|
||||||
TABLE *table, *tmp_table;
|
TABLE *table, *tmp_table;
|
||||||
List_iterator_fast<TABLE> check_opt_it(unupdated_check_opt_tables);
|
List_iterator_fast<TABLE> check_opt_it(unupdated_check_opt_tables);
|
||||||
DBUG_ENTER("do_updates");
|
DBUG_ENTER("multi_update::do_updates");
|
||||||
|
|
||||||
do_update= 0; // Don't retry this function
|
do_update= 0; // Don't retry this function
|
||||||
if (!found)
|
if (!found)
|
||||||
@ -1819,6 +1905,7 @@ err:
|
|||||||
if (!from_send_error)
|
if (!from_send_error)
|
||||||
{
|
{
|
||||||
thd->fatal_error();
|
thd->fatal_error();
|
||||||
|
prepare_record_for_error_message(local_error, table);
|
||||||
table->file->print_error(local_error,MYF(0));
|
table->file->print_error(local_error,MYF(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1849,6 +1936,7 @@ bool multi_update::send_eof()
|
|||||||
{
|
{
|
||||||
char buff[STRING_BUFFER_USUAL_SIZE];
|
char buff[STRING_BUFFER_USUAL_SIZE];
|
||||||
ulonglong id;
|
ulonglong id;
|
||||||
|
DBUG_ENTER("multi_update::send_eof");
|
||||||
thd->proc_info="updating reference tables";
|
thd->proc_info="updating reference tables";
|
||||||
|
|
||||||
/* Does updates for the last n - 1 tables, returns 0 if ok */
|
/* Does updates for the last n - 1 tables, returns 0 if ok */
|
||||||
@ -1904,7 +1992,7 @@ bool multi_update::send_eof()
|
|||||||
/* Safety: If we haven't got an error before (can happen in do_updates) */
|
/* Safety: If we haven't got an error before (can happen in do_updates) */
|
||||||
my_message(ER_UNKNOWN_ERROR, "An error occured in multi-table update",
|
my_message(ER_UNKNOWN_ERROR, "An error occured in multi-table update",
|
||||||
MYF(0));
|
MYF(0));
|
||||||
return TRUE;
|
DBUG_RETURN(TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
id= thd->arg_of_last_insert_id_function ?
|
id= thd->arg_of_last_insert_id_function ?
|
||||||
@ -1914,5 +2002,5 @@ bool multi_update::send_eof()
|
|||||||
thd->row_count_func=
|
thd->row_count_func=
|
||||||
(thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated;
|
(thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated;
|
||||||
::send_ok(thd, (ulong) thd->row_count_func, id, buff);
|
::send_ok(thd, (ulong) thd->row_count_func, id, buff);
|
||||||
return FALSE;
|
DBUG_RETURN(FALSE);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user