Commit 437813fb authored by rburnett@bk-internal.mysql.com's avatar rburnett@bk-internal.mysql.com

Merge bk-internal.mysql.com:/data0/bk/mysql-5.1

into  bk-internal.mysql.com:/data0/bk/mysql-5.1-kt
parents 7e07425b 21f7f347
Branches unavailable
Tags unavailable
......@@ -370,8 +370,9 @@ enum ha_base_keytype {
would lead to a duplicate key
error in some other table. */
#define HA_ERR_TABLE_NEEDS_UPGRADE 164 /* The table changed in storage engine */
#define HA_ERR_TABLE_READONLY 165 /* The table is not writable */
#define HA_ERR_LAST 164 /*Copy last error nr.*/
#define HA_ERR_LAST 165 /*Copy last error nr.*/
/* Add error numbers before HA_ERR_LAST and change it accordingly. */
#define HA_ERR_ERRORS (HA_ERR_LAST - HA_ERR_FIRST + 1)
......
......@@ -894,10 +894,14 @@ bool Protocol::send_fields(List<Item> *list, uint flags)
}
else
{
uint max_char_len;
/* With conversion */
client_field->charsetnr= thd_cs->number;
uint char_len= server_field.length / item->collation.collation->mbmaxlen;
client_field->length= char_len * thd_cs->mbmaxlen;
max_char_len= (server_field.type >= (int) MYSQL_TYPE_TINY_BLOB &&
server_field.type <= (int) MYSQL_TYPE_BLOB) ?
server_field.length / item->collation.collation->mbminlen :
server_field.length / item->collation.collation->mbmaxlen;
client_field->length= max_char_len * thd_cs->mbmaxlen;
}
client_field->type= server_field.type;
client_field->flags= server_field.flags;
......
......@@ -1603,6 +1603,44 @@ fld_cid fld_name fld_parentid fld_delt
5 Torkel 0 0
DROP TABLE federated.t1;
DROP TABLE federated.bug_17377_table;
DROP TABLE IF EXISTS federated.test;
CREATE TABLE federated.test (
`id` int(11) NOT NULL,
`val1` varchar(255) NOT NULL,
`val2` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
DROP TABLE IF EXISTS federated.test_local;
DROP TABLE IF EXISTS federated.test_remote;
CREATE TABLE federated.test_local (
`id` int(11) NOT NULL,
`val1` varchar(255) NOT NULL,
`val2` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
INSERT INTO federated.test_local VALUES (1, 'foo', 'bar'),
(2, 'bar', 'foo');
CREATE TABLE federated.test_remote (
`id` int(11) NOT NULL,
`val1` varchar(255) NOT NULL,
`val2` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=FEDERATED DEFAULT CHARSET=latin1
CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/test';
insert into federated.test_remote select * from federated.test_local;
select * from federated.test_remote;
id val1 val2
1 foo bar
2 bar foo
delete from federated.test_remote where id in (1,2);
insert into federated.test_remote select * from federated.test_local;
select * from federated.test_remote;
id val1 val2
2 bar foo
1 foo bar
DROP TABLE federated.test_local;
DROP TABLE federated.test_remote;
DROP TABLE federated.test;
drop table if exists federated.t1;
create table federated.t1 (a int, b int, c int);
drop table if exists federated.t1;
......@@ -1733,6 +1771,19 @@ id val
2 0
drop table t1;
drop table t1;
create table t1 (a longblob not null);
create table t1
(a longblob not null) engine=federated
connection='mysql://root@127.0.0.1:SLAVE_PORT/test/t1';
insert into t1 values (repeat('a',5000));
select length(a) from t1;
length(a)
5000
select length(a) from t1;
length(a)
5000
drop table t1;
drop table t1;
End of 5.0 tests
DROP TABLE IF EXISTS federated.t1;
DROP DATABASE IF EXISTS federated;
......
......@@ -777,3 +777,15 @@ create table tm (b bit(1)) engine = merge union = (t1,t2);
select * from tm;
b
drop table tm, t1, t2;
create table t1 (a int) insert_method = last engine = merge;
insert into t1 values (1);
ERROR HY000: Table 't1' is read only
create table t2 (a int) engine = myisam;
alter table t1 union (t2);
insert into t1 values (1);
alter table t1 insert_method = no;
insert into t1 values (1);
ERROR HY000: Table 't1' is read only
drop table t2;
drop table t1;
End of 5.0 tests
......@@ -22,6 +22,7 @@ ndb_binlog_ignore_db : BUG#21279 2006-07-25 ingo Randomly throws a warnin
ndb_load : BUG#17233 2006-05-04 tomas failed load data from infile causes mysqld dbug_assert, binlog not flushed
ndb_restore_compat : BUG#21283 2006-07-26 ingo Test fails randomly
partition_03ndb : BUG#16385 2006-03-24 mikael Partitions: crash when updating a range partitioned NDB table
ps : BUG#21524 2006-08-08 pgalbraith 'ps' test fails in --ps-protocol test AMD64 bit
ps_7ndb : BUG#18950 2006-02-16 jmiller create table like does not obtain LOCK_open
rpl_ndb_2innodb : BUG#19227 2006-04-20 pekka pk delete apparently not replicated
rpl_ndb_2myisam : BUG#19227 Seems to pass currently
......
......@@ -1366,6 +1366,62 @@ drop table federated.t1, federated.t2;
connection master;
--enable_parsing
#
# BUG #18764: Delete conditions causing inconsistencies in Federated tables
#
connection slave;
--disable_warnings
DROP TABLE IF EXISTS federated.test;
--enable_warnings
CREATE TABLE federated.test (
`id` int(11) NOT NULL,
`val1` varchar(255) NOT NULL,
`val2` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
connection master;
--disable_warnings
DROP TABLE IF EXISTS federated.test_local;
DROP TABLE IF EXISTS federated.test_remote;
--enable_warnings
CREATE TABLE federated.test_local (
`id` int(11) NOT NULL,
`val1` varchar(255) NOT NULL,
`val2` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
INSERT INTO federated.test_local VALUES (1, 'foo', 'bar'),
(2, 'bar', 'foo');
--replace_result $SLAVE_MYPORT SLAVE_PORT
eval CREATE TABLE federated.test_remote (
`id` int(11) NOT NULL,
`val1` varchar(255) NOT NULL,
`val2` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=FEDERATED DEFAULT CHARSET=latin1
CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/test';
insert into federated.test_remote select * from federated.test_local;
select * from federated.test_remote;
delete from federated.test_remote where id in (1,2);
insert into federated.test_remote select * from federated.test_local;
select * from federated.test_remote;
--disable_warnings
DROP TABLE federated.test_local;
DROP TABLE federated.test_remote;
--enable_warnings
connection slave;
--disable_warnings
DROP TABLE federated.test;
--enable_warnings
#
# Additional test for bug#18437 "Wrong values inserted with a before
# update trigger on NDB table". SQL-layer didn't properly inform
......@@ -1479,7 +1535,23 @@ drop table t1;
connection master;
drop table t1;
--echo End of 5.0 tests
#
# Bug #17608: String literals lost during INSERT query on FEDERATED table
#
connection slave;
create table t1 (a longblob not null);
connection master;
--replace_result $SLAVE_MYPORT SLAVE_PORT
eval create table t1
(a longblob not null) engine=federated
connection='mysql://root@127.0.0.1:$SLAVE_MYPORT/test/t1';
insert into t1 values (repeat('a',5000));
select length(a) from t1;
connection slave;
select length(a) from t1;
drop table t1;
connection master;
drop table t1;
--echo End of 5.0 tests
source include/federated_cleanup.inc;
......@@ -392,4 +392,19 @@ create table tm (b bit(1)) engine = merge union = (t1,t2);
select * from tm;
drop table tm, t1, t2;
# End of 5.0 tests
#
# Bug #17766: The server accepts to create MERGE tables which cannot work
#
create table t1 (a int) insert_method = last engine = merge;
--error ER_OPEN_AS_READONLY
insert into t1 values (1);
create table t2 (a int) engine = myisam;
alter table t1 union (t2);
insert into t1 values (1);
alter table t1 insert_method = no;
--error ER_OPEN_AS_READONLY
insert into t1 values (1);
drop table t2;
drop table t1;
--echo End of 5.0 tests
......@@ -1572,104 +1572,6 @@ Field *Field::new_key_field(MEM_ROOT *root, struct st_table *new_table,
}
/*
SYNOPSIS
Field::quote_data()
unquoted_string Pointer pointing to the value of a field
DESCRIPTION
Simple method that passes the field type to the method "type_quote"
To get a true/false value as to whether the value in string1 needs
to be enclosed with quotes. This ensures that values in the final
sql statement to be passed to the remote server will be quoted properly
RETURN_VALUE
void Immediately - if string doesn't need quote
void Upon prepending/appending quotes on each side of variable
*/
bool Field::quote_data(String *unquoted_string)
{
char escaped_string[IO_SIZE];
DBUG_ENTER("Field::quote_data");
if (!needs_quotes())
DBUG_RETURN(0);
// this is the same call that mysql_real_escape_string() calls
if (escape_string_for_mysql(&my_charset_bin, (char *)escaped_string,
sizeof(escaped_string), unquoted_string->ptr(),
unquoted_string->length()) == (ulong)~0)
DBUG_RETURN(1);
// reset string, then re-append with quotes and escaped values
unquoted_string->length(0);
if (unquoted_string->append('\'') ||
unquoted_string->append((char *)escaped_string) ||
unquoted_string->append('\''))
DBUG_RETURN(1);
DBUG_RETURN(0);
}
/*
Quote a field type if needed
SYNOPSIS
Field::type_quote
DESCRIPTION
Simple method to give true/false whether a field should be quoted.
Used when constructing INSERT and UPDATE queries to the remote server
see write_row and update_row
RETURN VALUE
0 if value is of type NOT needing quotes
1 if value is of type needing quotes
*/
bool Field::needs_quotes(void)
{
DBUG_ENTER("Field::type_quote");
switch (type()) {
//FIX this when kernel is fixed
case MYSQL_TYPE_VARCHAR :
case FIELD_TYPE_STRING :
case FIELD_TYPE_VAR_STRING :
case FIELD_TYPE_YEAR :
case FIELD_TYPE_NEWDATE :
case FIELD_TYPE_TIME :
case FIELD_TYPE_TIMESTAMP :
case FIELD_TYPE_DATE :
case FIELD_TYPE_DATETIME :
case FIELD_TYPE_TINY_BLOB :
case FIELD_TYPE_BLOB :
case FIELD_TYPE_MEDIUM_BLOB :
case FIELD_TYPE_LONG_BLOB :
case FIELD_TYPE_GEOMETRY :
case FIELD_TYPE_BIT:
DBUG_RETURN(1);
case FIELD_TYPE_DECIMAL :
case FIELD_TYPE_TINY :
case FIELD_TYPE_SHORT :
case FIELD_TYPE_INT24 :
case FIELD_TYPE_LONG :
case FIELD_TYPE_FLOAT :
case FIELD_TYPE_DOUBLE :
case FIELD_TYPE_LONGLONG :
case FIELD_TYPE_NULL :
case FIELD_TYPE_SET :
case FIELD_TYPE_ENUM :
DBUG_RETURN(0);
default:
DBUG_RETURN(0);
}
}
/* This is used to generate a field in TABLE from TABLE_SHARE */
Field *Field::clone(MEM_ROOT *root, struct st_table *new_table)
......
......@@ -268,8 +268,6 @@ class Field
ptr= old_ptr;
return str;
}
bool quote_data(String *unquoted_string);
bool needs_quotes(void);
virtual bool send_binary(Protocol *protocol);
virtual char *pack(char* to, const char *from, uint max_length=~(uint) 0)
{
......
......@@ -124,11 +124,6 @@
ha_federated::write_row
<for every field/column>
Field::quote_data
Field::quote_data
</for every field/column>
ha_federated::reset
(UPDATE)
......@@ -138,20 +133,10 @@
ha_federated::index_init
ha_federated::index_read
ha_federated::index_read_idx
Field::quote_data
ha_federated::rnd_next
ha_federated::convert_row_to_internal_format
ha_federated::update_row
<quote 3 cols, new and old data>
Field::quote_data
Field::quote_data
Field::quote_data
Field::quote_data
Field::quote_data
Field::quote_data
</quote 3 cols, new and old data>
ha_federated::extra
ha_federated::extra
ha_federated::extra
......@@ -1157,7 +1142,7 @@ bool ha_federated::create_where_from_key(String *to,
Field *field= key_part->field;
uint store_length= key_part->store_length;
uint part_length= min(store_length, length);
needs_quotes= field->needs_quotes();
needs_quotes= 1;
DBUG_DUMP("key, start of loop", (char *) ptr, length);
if (key_part->null_bit)
......@@ -1578,7 +1563,62 @@ inline uint field_in_record_is_null(TABLE *table,
int ha_federated::write_row(byte *buf)
{
bool has_fields= FALSE;
/*
I need a bool again, in 5.0, I used table->s->fields to accomplish this.
This worked as a flag that says there are fields with values or not.
In 5.1, this value doesn't work the same, and I end up with the code
truncating open parenthesis:
the statement "INSERT INTO t1 VALUES ()" ends up being first built
in two strings
"INSERT INTO t1 ("
and
" VALUES ("
If there are fields with values, they get appended, with commas, and
the last loop, a trailing comma is there
"INSERT INTO t1 ( col1, col2, colN, "
" VALUES ( 'val1', 'val2', 'valN', "
Then, if there are fields, it should decrement the string by ", " length.
"INSERT INTO t1 ( col1, col2, colN"
" VALUES ( 'val1', 'val2', 'valN'"
Then it adds a close paren to both - if there are fields
"INSERT INTO t1 ( col1, col2, colN)"
" VALUES ( 'val1', 'val2', 'valN')"
Then appends both together
"INSERT INTO t1 ( col1, col2, colN) VALUES ( 'val1', 'val2', 'valN')"
So... the problem, is if you have the original statement:
"INSERT INTO t1 VALUES ()"
Which is legitimate, but if the code thinks there are fields
"INSERT INTO t1 ("
" VALUES ( "
If the field flag is set, but there are no commas, reduces the
string by strlen(", ")
"INSERT INTO t1 "
" VALUES "
Then adds the close parenthesis
"INSERT INTO t1 )"
" VALUES )"
So, I have to use a bool as before, set in the loop where fields and commas
are appended to the string
*/
my_bool commas_added= FALSE;
char insert_buffer[FEDERATED_QUERY_BUFFER_SIZE];
char values_buffer[FEDERATED_QUERY_BUFFER_SIZE];
char insert_field_value_buffer[STRING_BUFFER_USUAL_SIZE];
......@@ -1594,10 +1634,6 @@ int ha_federated::write_row(byte *buf)
&my_charset_bin);
my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->read_set);
DBUG_ENTER("ha_federated::write_row");
DBUG_PRINT("info",
("table charset name %s csname %s",
table->s->table_charset->name,
table->s->table_charset->csname));
values_string.length(0);
insert_string.length(0);
......@@ -1609,37 +1645,33 @@ int ha_federated::write_row(byte *buf)
/*
start both our field and field values strings
*/
insert_string.append(STRING_WITH_LEN("INSERT `"));
insert_string.append(STRING_WITH_LEN("INSERT INTO `"));
insert_string.append(share->table_name, share->table_name_length);
insert_string.append(STRING_WITH_LEN("` ("));
insert_string.append('`');
insert_string.append(STRING_WITH_LEN(" ("));
values_string.append(STRING_WITH_LEN(" VALUES ("));
values_string.append(STRING_WITH_LEN(" VALUES "));
values_string.append(STRING_WITH_LEN(" ("));
/*
loop through the field pointer array, add any fields to both the values
list and the fields list that is part of the write set
You might ask "Why an index variable (has_fields) ?" My answer is that
we need to count how many fields we actually need
*/
for (field= table->field; *field; field++)
{
/* if there is a query id and if it's equal to the current query id */
if (bitmap_is_set(table->write_set, (*field)->field_index))
{
/*
There are some fields. This will be used later to determine
whether to chop off commas and parens.
*/
has_fields= TRUE;
commas_added= TRUE;
if ((*field)->is_null())
insert_field_value_string.append(STRING_WITH_LEN(" NULL "));
else
{
(*field)->val_str(&insert_field_value_string);
/* quote these fields if they require it */
(*field)->quote_data(&insert_field_value_string);
values_string.append('\'');
insert_field_value_string.print(&values_string);
values_string.append('\'');
insert_field_value_string.length(0);
}
/* append the field name */
insert_string.append((*field)->field_name);
......@@ -1665,10 +1697,10 @@ int ha_federated::write_row(byte *buf)
AND, we don't want to chop off the last char '('
insert will be "INSERT INTO t1 VALUES ();"
*/
if (has_fields)
if (commas_added)
{
/* chops off trailing commas */
insert_string.length(insert_string.length() - sizeof_trailing_comma);
/* chops off leading commas */
values_string.length(values_string.length() - sizeof_trailing_comma);
insert_string.append(STRING_WITH_LEN(") "));
}
......@@ -1678,6 +1710,7 @@ int ha_federated::write_row(byte *buf)
insert_string.length(insert_string.length() - sizeof_trailing_closeparen);
}
/* we always want to append this, even if there aren't any fields */
values_string.append(STRING_WITH_LEN(") "));
/* add the values */
......@@ -1799,6 +1832,7 @@ int ha_federated::update_row(const byte *old_data, byte *new_data)
this.
*/
bool has_a_primary_key= test(table->s->primary_key != MAX_KEY);
/*
buffers for following strings
*/
......@@ -1844,7 +1878,7 @@ int ha_federated::update_row(const byte *old_data, byte *new_data)
if (bitmap_is_set(table->write_set, (*field)->field_index))
{
update_string.append((*field)->field_name);
update_string.append(STRING_WITH_LEN("="));
update_string.append(STRING_WITH_LEN(" = "));
if ((*field)->is_null())
update_string.append(STRING_WITH_LEN(" NULL "));
......@@ -1852,9 +1886,10 @@ int ha_federated::update_row(const byte *old_data, byte *new_data)
{
my_bitmap_map *old_map= tmp_use_all_columns(table, table->read_set);
/* otherwise = */
(*field)->val_str(&field_value);
(*field)->quote_data(&field_value);
update_string.append(field_value);
(*field)->val_str(&field_value);
update_string.append('\'');
field_value.print(&update_string);
update_string.append('\'');
field_value.length(0);
tmp_restore_column_map(table->read_set, old_map);
}
......@@ -1871,8 +1906,9 @@ int ha_federated::update_row(const byte *old_data, byte *new_data)
where_string.append(STRING_WITH_LEN(" = "));
(*field)->val_str(&field_value,
(char*) (old_data + (*field)->offset()));
(*field)->quote_data(&field_value);
where_string.append(field_value);
where_string.append('\'');
field_value.print(&where_string);
where_string.append('\'');
field_value.length(0);
}
where_string.append(STRING_WITH_LEN(" AND "));
......@@ -1881,6 +1917,7 @@ int ha_federated::update_row(const byte *old_data, byte *new_data)
/* Remove last ', '. This works as there must be at least on updated field */
update_string.length(update_string.length() - sizeof_trailing_comma);
if (where_string.length())
{
/* chop off trailing AND */
......@@ -1946,10 +1983,11 @@ int ha_federated::delete_row(const byte *buf)
}
else
{
delete_string.append(STRING_WITH_LEN(" = "));
cur_field->val_str(&data_string);
cur_field->quote_data(&data_string);
delete_string.append(data_string);
delete_string.append(STRING_WITH_LEN(" = "));
cur_field->val_str(&data_string);
delete_string.append('\'');
data_string.print(&delete_string);
delete_string.append('\'');
}
delete_string.append(STRING_WITH_LEN(" AND "));
}
......
......@@ -122,6 +122,10 @@ int ha_myisammrg::close(void)
int ha_myisammrg::write_row(byte * buf)
{
statistic_increment(table->in_use->status_var.ha_write_count,&LOCK_status);
if (file->merge_insert_method == MERGE_INSERT_DISABLED || !file->tables)
return (HA_ERR_TABLE_READONLY);
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
table->timestamp_field->set_time();
if (table->next_number_field && buf == table->record[0])
......
......@@ -344,6 +344,7 @@ static int ha_init_errors(void)
SETMSG(HA_ERR_TABLE_DEF_CHANGED, ER(ER_TABLE_DEF_CHANGED));
SETMSG(HA_ERR_FOREIGN_DUPLICATE_KEY, "FK constraint would lead to duplicate key");
SETMSG(HA_ERR_TABLE_NEEDS_UPGRADE, ER(ER_TABLE_NEEDS_UPGRADE));
SETMSG(HA_ERR_TABLE_READONLY, ER(ER_OPEN_AS_READONLY));
/* Register the error messages for use with my_error(). */
return my_error_register(errmsgs, HA_ERR_FIRST, HA_ERR_LAST);
......@@ -2115,6 +2116,9 @@ void handler::print_error(int error, myf errflag)
case HA_ERR_TABLE_NEEDS_UPGRADE:
textno=ER_TABLE_NEEDS_UPGRADE;
break;
case HA_ERR_TABLE_READONLY:
textno= ER_OPEN_AS_READONLY;
break;
default:
{
/* The error was "unknown" to this function.
......
......@@ -26,8 +26,7 @@
*/
#include "my_base.h" /* Defines EOVERFLOW on Windows */
#include "my_global.h" /* Includes errno.h */
#include "my_base.h" /* Includes errno.h + EOVERFLOW */
#include "m_ctype.h"
#define MAX_DBL_EXP 308
......
......@@ -552,15 +552,18 @@ fi
%doc %attr(644, root, root) %{_infodir}/mysql.info*
%doc %attr(644, root, man) %{_mandir}/man1/myisam_ftdump.1*
%doc %attr(644, root, man) %{_mandir}/man1/myisamchk.1*
%doc %attr(644, root, man) %{_mandir}/man1/myisamlog.1*
%doc %attr(644, root, man) %{_mandir}/man1/myisampack.1*
%doc %attr(644, root, man) %{_mandir}/man1/mysql_explain_log.1*
%doc %attr(644, root, man) %{_mandir}/man1/mysqld.1*
%doc %attr(644, root, man) %{_mandir}/man1/mysqld_multi.1*
%doc %attr(644, root, man) %{_mandir}/man1/mysqld_safe.1*
%doc %attr(644, root, man) %{_mandir}/man1/mysql_fix_privilege_tables.1*
%doc %attr(644, root, man) %{_mandir}/man1/mysql_upgrade.1*
%doc %attr(644, root, man) %{_mandir}/man1/mysqlhotcopy.1*
%doc %attr(644, root, man) %{_mandir}/man1/mysqlman.1*
%doc %attr(644, root, man) %{_mandir}/man1/mysqlmanager.1*
%doc %attr(644, root, man) %{_mandir}/man1/mysql.server.1*
%doc %attr(644, root, man) %{_mandir}/man1/mysql_zap.1*
......@@ -646,7 +649,6 @@ fi
%files ndb-management
%defattr(-,root,root,0755)
%attr(755, root, root) %{_sbindir}/ndb_mgmd
%attr(755, root, root) %{_bindir}/ndb_mgm
%files ndb-tools
%defattr(-,root,root,0755)
......
......@@ -15490,7 +15490,9 @@ static struct my_tests_st my_tests[]= {
{ "test_bug14845", test_bug14845 },
{ "test_opt_reconnect", test_opt_reconnect },
{ "test_bug15510", test_bug15510},
#ifndef EMBEDDED_LIBRARY
{ "test_bug12744", test_bug12744 },
#endif
{ "test_bug16143", test_bug16143 },
{ "test_bug16144", test_bug16144 },
{ "test_bug15613", test_bug15613 },
......
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