Commit 749a4e91 authored by unknown's avatar unknown

Merge mskold@bk-internal.mysql.com:/home/bk/mysql-5.0

into mysql.com:/usr/local/home/marty/MySQL/mysql-5.0

parents 110eb52d b0502fc2
......@@ -16,3 +16,8 @@ explain select * from t1 where str <> default(str);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 system NULL NULL NULL NULL 1
drop table t1;
CREATE TABLE t1 (id int(11), s varchar(20));
INSERT INTO t1 VALUES (1, 'one'), (2, 'two'), (3, 'three');
SELECT s, 32 AS mi FROM t1 GROUP BY s HAVING DEFAULT(mi) IS NULL;
ERROR HY000: Field 'mi' doesn't have a default value
DROP TABLE t1;
This diff is collapsed.
......@@ -16,4 +16,14 @@ explain select * from t1 where str <> default(str);
#show create table from t1;
#insert into t2 select select default(str), default(strnull), default(intg), default(rel) from t1;
drop table t1;
\ No newline at end of file
drop table t1;
#
# Bug #11314 (HAVING DEFAULT() hangs)
#
CREATE TABLE t1 (id int(11), s varchar(20));
INSERT INTO t1 VALUES (1, 'one'), (2, 'two'), (3, 'three');
--error 1364
SELECT s, 32 AS mi FROM t1 GROUP BY s HAVING DEFAULT(mi) IS NULL;
DROP TABLE t1;
......@@ -756,4 +756,36 @@ flush query cache;
drop table t1, t2;
#
# SP cursors and selects with query cache (BUG#9715)
#
create table t1 (a int);
insert into t1 values (1),(2);
delimiter //;
CREATE PROCEDURE `p1`()
begin
Declare c1 cursor for select a from t1;
open c1;
select * from t1;
end//
call p1()//
drop procedure p1;
create function f1() returns int
begin
Declare var1 int;
select max(a) from t1 into var1;
return var1;
end//
create procedure `p1`()
begin
select a, f1() from t1;
end//
call p1()//
drop procedure p1//
drop table t1//
delimiter ;//
set GLOBAL query_cache_size=0;
......@@ -343,6 +343,7 @@ void start_master()
add_arg(&al, "--character-sets-dir=%s", char_dir);
add_arg(&al, "--tmpdir=%s", mysql_tmp_dir);
add_arg(&al, "--language=%s", lang_dir);
add_arg(&al, "--log-bin-trust-routine-creators");
#ifdef DEBUG //only for debug builds
add_arg(&al, "--debug");
#endif
......@@ -516,6 +517,7 @@ void start_slave()
add_arg(&al, "--master-retry-count=10");
add_arg(&al, "-O");
add_arg(&al, "slave_net_timeout=10");
add_arg(&al, "--log-bin-trust-routine-creators");
#ifdef DEBUG //only for debug builds
add_arg(&al, "--debug");
#endif
......@@ -1164,6 +1166,8 @@ void setup(char *file)
setenv("MYSQL_CLIENT_TEST",file_path,1);
snprintf(file_path, PATH_MAX*2, "%s/mysql --no-defaults --user=root --port=%u ", bin_dir, master_port);
setenv("MYSQL",file_path,1);
snprintf(file_path, PATH_MAX*2, "%s/mysqlshow --no-defaults --user=root --port=%u", bin_dir, master_port);
setenv("MYSQL_SHOW",file_path,1);
}
/******************************************************************************
......
......@@ -40,7 +40,7 @@
DESCRIPTION
Function to add a string to the buffer. It is different from
store_to_string, which is used in the protocol.cc. The last
store_to_protocol_packet, which is used in the protocol.cc. The last
one also stores the length of the string in a special way.
This is required for MySQL client/server protocol support only.
......@@ -104,11 +104,12 @@ int Show_instances::execute(struct st_net *net, ulong connection_id)
while ((instance= iterator.next()))
{
position= 0;
store_to_string(&send_buff, instance->options.instance_name, &position);
store_to_protocol_packet(&send_buff, instance->options.instance_name,
&position);
if (instance->is_running())
store_to_string(&send_buff, (char*) "online", &position);
store_to_protocol_packet(&send_buff, (char*) "online", &position);
else
store_to_string(&send_buff, (char*) "offline", &position);
store_to_protocol_packet(&send_buff, (char*) "offline", &position);
if (my_net_write(net, send_buff.buffer, (uint) position))
goto err;
}
......@@ -199,18 +200,19 @@ int Show_instance_status::execute(struct st_net *net,
{
Instance *instance;
store_to_string(&send_buff, (char*) instance_name, &position);
store_to_protocol_packet(&send_buff, (char*) instance_name, &position);
if (!(instance= instance_map->find(instance_name, strlen(instance_name))))
goto err;
if (instance->is_running())
store_to_string(&send_buff, (char*) "online", &position);
store_to_protocol_packet(&send_buff, (char*) "online", &position);
else
store_to_string(&send_buff, (char*) "offline", &position);
store_to_protocol_packet(&send_buff, (char*) "offline", &position);
if (instance->options.mysqld_version)
store_to_string(&send_buff, instance->options.mysqld_version, &position);
store_to_protocol_packet(&send_buff, instance->options.mysqld_version,
&position);
else
store_to_string(&send_buff, (char*) "unknown", &position);
store_to_protocol_packet(&send_buff, (char*) "unknown", &position);
if (send_buff.is_error() ||
......@@ -272,17 +274,17 @@ int Show_instance_options::execute(struct st_net *net, ulong connection_id)
if (!(instance= instance_map->find(instance_name, strlen(instance_name))))
goto err;
store_to_string(&send_buff, (char*) "instance_name", &position);
store_to_string(&send_buff, (char*) instance_name, &position);
store_to_protocol_packet(&send_buff, (char*) "instance_name", &position);
store_to_protocol_packet(&send_buff, (char*) instance_name, &position);
if (my_net_write(net, send_buff.buffer, (uint) position))
goto err;
if ((instance->options.mysqld_path))
{
position= 0;
store_to_string(&send_buff, (char*) "mysqld-path", &position);
store_to_string(&send_buff,
(char*) instance->options.mysqld_path,
&position);
store_to_protocol_packet(&send_buff, (char*) "mysqld-path", &position);
store_to_protocol_packet(&send_buff,
(char*) instance->options.mysqld_path,
&position);
if (send_buff.is_error() ||
my_net_write(net, send_buff.buffer, (uint) position))
goto err;
......@@ -291,8 +293,8 @@ int Show_instance_options::execute(struct st_net *net, ulong connection_id)
if ((instance->options.nonguarded))
{
position= 0;
store_to_string(&send_buff, (char*) "nonguarded", &position);
store_to_string(&send_buff, "", &position);
store_to_protocol_packet(&send_buff, (char*) "nonguarded", &position);
store_to_protocol_packet(&send_buff, "", &position);
if (send_buff.is_error() ||
my_net_write(net, send_buff.buffer, (uint) position))
goto err;
......@@ -310,13 +312,16 @@ int Show_instance_options::execute(struct st_net *net, ulong connection_id)
if (option_value != NULL)
{
*option_value= 0;
store_to_string(&send_buff, tmp_option + 2, &position);
store_to_string(&send_buff, option_value + 1, &position);
store_to_protocol_packet(&send_buff, tmp_option + 2, &position);
store_to_protocol_packet(&send_buff, option_value + 1, &position);
/* join name and the value into the same option again */
*option_value= '=';
}
else
store_to_string(&send_buff, tmp_option + 2, &position);
{
store_to_protocol_packet(&send_buff, tmp_option + 2, &position);
store_to_protocol_packet(&send_buff, "", &position);
}
if (send_buff.is_error() ||
my_net_write(net, send_buff.buffer, (uint) position))
......@@ -478,7 +483,7 @@ int Show_instance_log::execute(struct st_net *net, ulong connection_id)
char *bf= (char*) malloc(sizeof(char)*buff_size);
if ((read_len= my_read(fd, bf, buff_size, MYF(0))) < 0)
return ER_READ_FILE;
store_to_string(&send_buff, (char*) bf, &position, read_len);
store_to_protocol_packet(&send_buff, (char*) bf, &position, read_len);
close(fd);
}
else
......@@ -593,19 +598,19 @@ int Show_instance_log_files::execute(struct st_net *net, ulong connection_id)
position= 0;
/* store the type of the log in the send buffer */
store_to_string(&send_buff, log_files->name, &position);
store_to_protocol_packet(&send_buff, log_files->name, &position);
if (stat(log_files->value, &file_stat))
{
store_to_string(&send_buff, "", &position);
store_to_string(&send_buff, (char*) "0", &position);
store_to_protocol_packet(&send_buff, "", &position);
store_to_protocol_packet(&send_buff, (char*) "0", &position);
}
else if (S_ISREG(file_stat.st_mode))
{
store_to_string(&send_buff,
(char*) log_files->value,
&position);
store_to_protocol_packet(&send_buff,
(char*) log_files->value,
&position);
int10_to_str(file_stat.st_size, buff, 10);
store_to_string(&send_buff, (char*) buff, &position);
store_to_protocol_packet(&send_buff, (char*) buff, &position);
}
if (my_net_write(net, send_buff.buffer, (uint) position))
......
......@@ -58,7 +58,7 @@ int net_send_ok(struct st_net *net, unsigned long connection_id,
if (message != NULL)
{
buff.reserve(position, 9 + strlen(message));
store_to_string(&buff, message, &position);
store_to_protocol_packet(&buff, message, &position);
}
return my_net_write(net, buff.buffer, position) || net_flush(net);
......@@ -117,8 +117,8 @@ char *net_store_length(char *pkg, uint length)
}
int store_to_string(Buffer *buf, const char *string, uint *position,
uint string_len)
int store_to_protocol_packet(Buffer *buf, const char *string, uint *position,
uint string_len)
{
uint currpos;
......@@ -137,12 +137,12 @@ err:
}
int store_to_string(Buffer *buf, const char *string, uint *position)
int store_to_protocol_packet(Buffer *buf, const char *string, uint *position)
{
uint string_len;
string_len= strlen(string);
return store_to_string(buf, string, position, string_len);
return store_to_protocol_packet(buf, string, position, string_len);
}
......@@ -176,21 +176,28 @@ int send_fields(struct st_net *net, LIST *fields)
position= 0;
field= (NAME_WITH_LENGTH *) tmp->data;
store_to_string(&send_buff, (char*) "", &position); /* catalog name */
store_to_string(&send_buff, (char*) "", &position); /* db name */
store_to_string(&send_buff, (char*) "", &position); /* table name */
store_to_string(&send_buff, (char*) "", &position); /* table name alias */
store_to_string(&send_buff, field->name, &position); /* column name */
store_to_string(&send_buff, field->name, &position); /* column name alias */
store_to_protocol_packet(&send_buff,
(char*) "", &position); /* catalog name */
store_to_protocol_packet(&send_buff,
(char*) "", &position); /* db name */
store_to_protocol_packet(&send_buff,
(char*) "", &position); /* table name */
store_to_protocol_packet(&send_buff,
(char*) "", &position); /* table name alias */
store_to_protocol_packet(&send_buff,
field->name, &position); /* column name */
store_to_protocol_packet(&send_buff,
field->name, &position); /* column name alias */
send_buff.reserve(position, 12);
if (send_buff.is_error())
goto err;
send_buff.buffer[position++]= 12;
int2store(send_buff.buffer + position, 1); /* charsetnr */
int4store(send_buff.buffer + position + 2, field->length); /* field length */
send_buff.buffer[position+6]= FIELD_TYPE_STRING; /* type */
int2store(send_buff.buffer + position + 7, 0); /* flags */
send_buff.buffer[position + 9]= (char) 0; /* decimals */
int2store(send_buff.buffer + position, 1); /* charsetnr */
int4store(send_buff.buffer + position + 2,
field->length); /* field length */
send_buff.buffer[position+6]= FIELD_TYPE_STRING; /* type */
int2store(send_buff.buffer + position + 7, 0); /* flags */
send_buff.buffer[position + 9]= (char) 0; /* decimals */
send_buff.buffer[position + 10]= 0;
send_buff.buffer[position + 11]= 0;
position+= 12;
......
......@@ -41,10 +41,10 @@ int send_fields(struct st_net *net, LIST *fields);
char *net_store_length(char *pkg, uint length);
int store_to_string(Buffer *buf, const char *string, uint *position);
int store_to_protocol_packet(Buffer *buf, const char *string, uint *position);
int store_to_string(Buffer *buf, const char *string, uint *position,
uint string_len);
int store_to_protocol_packet(Buffer *buf, const char *string, uint *position,
uint string_len);
int send_eof(struct st_net *net);
......
......@@ -4443,6 +4443,7 @@ bool Item_default_value::fix_fields(THD *thd,
struct st_table_list *table_list,
Item **items)
{
Item *real_arg;
Item_field *field_arg;
Field *def_field;
DBUG_ASSERT(fixed == 0);
......@@ -4454,17 +4455,15 @@ bool Item_default_value::fix_fields(THD *thd,
}
if (!arg->fixed && arg->fix_fields(thd, table_list, &arg))
return TRUE;
if (arg->type() == REF_ITEM)
real_arg= arg->real_item();
if (real_arg->type() != FIELD_ITEM)
{
Item_ref *ref= (Item_ref *)arg;
if (ref->ref[0]->type() != FIELD_ITEM)
{
return TRUE;
}
arg= ref->ref[0];
my_error(ER_NO_DEFAULT_FOR_FIELD, MYF(0), arg->name);
return TRUE;
}
field_arg= (Item_field *)arg;
field_arg= (Item_field *)real_arg;
if (field_arg->field->flags & NO_DEFAULT_VALUE_FLAG)
{
my_error(ER_NO_DEFAULT_FOR_FIELD, MYF(0), field_arg->field->field_name);
......
......@@ -1352,7 +1352,10 @@ public:
{
(*ref)->save_in_field(result_field, no_conversions);
}
Item *real_item() { return *ref; }
Item *real_item()
{
return (*ref)->real_item();
}
bool walk(Item_processor processor, byte *arg)
{ return (*ref)->walk(processor, arg); }
void print(String *str);
......
......@@ -377,6 +377,10 @@ public:
return (uint)m_lex->sql_command;
}
void disable_query_cache()
{
m_lex->safe_to_cache_query= 0;
}
private:
LEX *m_lex;
......
......@@ -169,6 +169,17 @@ sp_rcontext::pop_cursors(uint count)
*
*/
sp_cursor::sp_cursor(sp_lex_keeper *lex_keeper)
:m_lex_keeper(lex_keeper), m_prot(NULL), m_isopen(0), m_current_row(NULL)
{
/*
currsor can't be stored in QC, so we should prevent opening QC for
try to write results which are absent.
*/
lex_keeper->disable_query_cache();
}
/*
pre_open cursor
......
......@@ -203,11 +203,7 @@ class sp_cursor : public Sql_alloc
{
public:
sp_cursor(sp_lex_keeper *lex_keeper)
: m_lex_keeper(lex_keeper), m_prot(NULL), m_isopen(0), m_current_row(NULL)
{
/* Empty */
}
sp_cursor(sp_lex_keeper *lex_keeper);
virtual ~sp_cursor()
{
......
......@@ -7957,6 +7957,19 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
modify_item ? (Item_field*) item : NULL,
convert_blob_length);
}
case Item::REF_ITEM:
if ( item->real_item()->type() == Item::FIELD_ITEM)
{
Item_field *field= (Item_field*) *((Item_ref*)item)->ref;
Field *new_field= create_tmp_field_from_field(thd,
(*from_field= field->field),
item->name, table,
NULL,
convert_blob_length);
if (modify_item)
item->set_result_field(new_field);
return new_field;
}
case Item::FUNC_ITEM:
case Item::COND_ITEM:
case Item::FIELD_AVG_ITEM:
......@@ -7968,7 +7981,6 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
case Item::REAL_ITEM:
case Item::DECIMAL_ITEM:
case Item::STRING_ITEM:
case Item::REF_ITEM:
case Item::NULL_ITEM:
case Item::VARBIN_ITEM:
return create_tmp_field_from_item(thd, item, table, copy_func, modify_item,
......
......@@ -13145,6 +13145,62 @@ static void test_bug9643()
myquery(rc);
}
/*
Bug#11111: fetch from view returns wrong data
*/
static void test_bug11111()
{
MYSQL_STMT *stmt;
MYSQL_BIND bind[2];
char buf[2][20];
long len[2];
int i;
int rc;
const char * query = "SELECT DISTINCT f1,ff2 FROM v1";
myheader("test_bug11111");
rc= mysql_query(mysql, "drop table if exists t1, t2, v1");
myquery(rc);
rc= mysql_query(mysql, "drop view if exists t1, t2, v1");
myquery(rc);
rc= mysql_query(mysql, "create table t1 (f1 int, f2 int)");
myquery(rc);
rc= mysql_query(mysql, "create table t2 (ff1 int, ff2 int)");
myquery(rc);
rc= mysql_query(mysql, "create view v1 as select * from t1, t2 where f1=ff1");
myquery(rc);
rc= mysql_query(mysql, "insert into t1 values (1,1), (2,2), (3,3)");
myquery(rc);
rc= mysql_query(mysql, "insert into t2 values (1,1), (2,2), (3,3)");
myquery(rc);
stmt = mysql_stmt_init(mysql);
mysql_stmt_prepare(stmt, query, strlen(query));
mysql_stmt_execute(stmt);
for (i=0; i < 2; i++) {
memset(&bind[i], '\0', sizeof(MYSQL_BIND));
bind[i].buffer_type= MYSQL_TYPE_STRING;
bind[i].buffer= (gptr *)&buf[i];
bind[i].buffer_length= 20;
bind[i].length= &len[i];
}
if (mysql_stmt_bind_result(stmt, bind))
printf("Error: %s\n", mysql_stmt_error(stmt));
mysql_stmt_fetch(stmt);
printf("return: %s", buf[1]);
DIE_UNLESS(!strcmp(buf[1],"1"));
mysql_stmt_close(stmt);
rc= mysql_query(mysql, "drop view v1");
myquery(rc);
rc= mysql_query(mysql, "drop table t1, t2");
myquery(rc);
}
/*
Check that proper cleanups are done for prepared statement when
fetching thorugh a cursor.
......@@ -13439,6 +13495,7 @@ static struct my_tests_st my_tests[]= {
{ "test_bug9478", test_bug9478 },
{ "test_bug9643", test_bug9643 },
{ "test_bug10729", test_bug10729 },
{ "test_bug11111", test_bug11111 },
{ 0, 0 }
};
......
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