A fix and a test case for Bug#13488 "Left outer join query incorrectly
gives MYSQL_DATA_TRUNCATED" sql/sql_cursor.cc: A partial fix for Bug#13488 "Left outer join query incorrectly gives MYSQL_DATA_TRUNCATED": send the correct metadata of the cursor result set at execute. The full fix would be to make sure that the metadata doesn't change between prepare and execute. tests/mysql_client_test.c: A test case for Bug#13488 "Left outer join query incorrectly gives MYSQL_DATA_TRUNCATED"
This commit is contained in:
parent
db46acd0bc
commit
75fab5146f
@ -558,6 +558,24 @@ int Materialized_cursor::open(JOIN *join __attribute__((unused)))
|
|||||||
result->prepare(item_list, &fake_unit) ||
|
result->prepare(item_list, &fake_unit) ||
|
||||||
table->file->ha_rnd_init(TRUE));
|
table->file->ha_rnd_init(TRUE));
|
||||||
thd->restore_active_arena(this, &backup_arena);
|
thd->restore_active_arena(this, &backup_arena);
|
||||||
|
if (rc == 0)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Now send the result set metadata to the client. We need to do it
|
||||||
|
here, as in Select_materialize::send_fields the exact column types
|
||||||
|
are not yet known. The new types may differ from the original ones
|
||||||
|
sent at prepare if some of them were altered by MySQL HEAP tables
|
||||||
|
mechanism -- used when create_tmp_field_from_item may alter the
|
||||||
|
original column type.
|
||||||
|
|
||||||
|
We can't simply supply SEND_EOF flag to send_fields, because
|
||||||
|
send_fields doesn't flush the network buffer.
|
||||||
|
*/
|
||||||
|
rc= result->send_fields(item_list, Protocol::SEND_NUM_ROWS);
|
||||||
|
thd->server_status|= SERVER_STATUS_CURSOR_EXISTS;
|
||||||
|
result->send_eof();
|
||||||
|
thd->server_status&= ~SERVER_STATUS_CURSOR_EXISTS;
|
||||||
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -647,14 +665,6 @@ bool Select_materialize::send_fields(List<Item> &list, uint flags)
|
|||||||
if (create_result_table(unit->thd, unit->get_unit_column_types(),
|
if (create_result_table(unit->thd, unit->get_unit_column_types(),
|
||||||
FALSE, thd->options | TMP_TABLE_ALL_COLUMNS, ""))
|
FALSE, thd->options | TMP_TABLE_ALL_COLUMNS, ""))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
/*
|
|
||||||
We can't simply supply SEND_EOF flag to send_fields, because send_fields
|
|
||||||
doesn't flush the network buffer.
|
|
||||||
*/
|
|
||||||
rc= result->send_fields(list, Protocol::SEND_NUM_ROWS);
|
|
||||||
thd->server_status|= SERVER_STATUS_CURSOR_EXISTS;
|
|
||||||
result->send_eof();
|
|
||||||
thd->server_status&= ~SERVER_STATUS_CURSOR_EXISTS;
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14419,6 +14419,74 @@ static void test_bug14210()
|
|||||||
myquery(rc);
|
myquery(rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Bug#13488 */
|
||||||
|
|
||||||
|
static void test_bug13488()
|
||||||
|
{
|
||||||
|
MYSQL_BIND bind[3];
|
||||||
|
MYSQL_STMT *stmt1;
|
||||||
|
int rc, f1, f2, f3, i;
|
||||||
|
const ulong type= CURSOR_TYPE_READ_ONLY;
|
||||||
|
const char *query= "select * from t1 left join t2 on f1=f2 where f1=1";
|
||||||
|
|
||||||
|
myheader("test_bug13488");
|
||||||
|
|
||||||
|
rc= mysql_query(mysql, "drop table if exists t1, t2");
|
||||||
|
myquery(rc);
|
||||||
|
rc= mysql_query(mysql, "create table t1 (f1 int not null primary key)");
|
||||||
|
myquery(rc);
|
||||||
|
rc= mysql_query(mysql, "create table t2 (f2 int not null primary key, "
|
||||||
|
"f3 int not null)");
|
||||||
|
myquery(rc);
|
||||||
|
rc= mysql_query(mysql, "insert into t1 values (1), (2)");
|
||||||
|
myquery(rc);
|
||||||
|
rc= mysql_query(mysql, "insert into t2 values (1,2), (2,4)");
|
||||||
|
myquery(rc);
|
||||||
|
|
||||||
|
memset(bind, 0, sizeof(bind));
|
||||||
|
for (i= 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
bind[i].buffer_type= MYSQL_TYPE_LONG;
|
||||||
|
bind[i].buffer_length= 4;
|
||||||
|
bind[i].length= 0;
|
||||||
|
}
|
||||||
|
bind[0].buffer=&f1;
|
||||||
|
bind[1].buffer=&f2;
|
||||||
|
bind[2].buffer=&f3;
|
||||||
|
|
||||||
|
stmt1= mysql_stmt_init(mysql);
|
||||||
|
rc= mysql_stmt_attr_set(stmt1,STMT_ATTR_CURSOR_TYPE, (const void *)&type);
|
||||||
|
check_execute(stmt1, rc);
|
||||||
|
|
||||||
|
rc= mysql_stmt_prepare(stmt1, query, strlen(query));
|
||||||
|
check_execute(stmt1, rc);
|
||||||
|
|
||||||
|
rc= mysql_stmt_execute(stmt1);
|
||||||
|
check_execute(stmt1, rc);
|
||||||
|
|
||||||
|
rc= mysql_stmt_bind_result(stmt1, bind);
|
||||||
|
check_execute(stmt1, rc);
|
||||||
|
|
||||||
|
rc= mysql_stmt_fetch(stmt1);
|
||||||
|
check_execute(stmt1, rc);
|
||||||
|
|
||||||
|
rc= mysql_stmt_free_result(stmt1);
|
||||||
|
check_execute(stmt1, rc);
|
||||||
|
|
||||||
|
rc= mysql_stmt_reset(stmt1);
|
||||||
|
check_execute(stmt1, rc);
|
||||||
|
|
||||||
|
rc= mysql_stmt_close(stmt1);
|
||||||
|
check_execute(stmt1, rc);
|
||||||
|
|
||||||
|
if (!opt_silent)
|
||||||
|
printf("data is: %s", (f1 == 1 && f2 == 1 && f3 == 2)?"OK":
|
||||||
|
"wrong");
|
||||||
|
DIE_UNLESS(f1 == 1 && f2 == 1 && f3 == 2);
|
||||||
|
rc= mysql_query(mysql, "drop table t1, t2");
|
||||||
|
myquery(rc);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Read and parse arguments and MySQL options from my.cnf
|
Read and parse arguments and MySQL options from my.cnf
|
||||||
*/
|
*/
|
||||||
@ -14675,6 +14743,7 @@ static struct my_tests_st my_tests[]= {
|
|||||||
{ "test_bug11904", test_bug11904 },
|
{ "test_bug11904", test_bug11904 },
|
||||||
{ "test_bug12243", test_bug12243 },
|
{ "test_bug12243", test_bug12243 },
|
||||||
{ "test_bug14210", test_bug14210 },
|
{ "test_bug14210", test_bug14210 },
|
||||||
|
{ "test_bug13488", test_bug13488 },
|
||||||
{ 0, 0 }
|
{ 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user