Below is the list of changes that have just been committed into a local
5.1 repository of hf. When hf does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet@stripped, 2006-11-17 18:27:28+04:00, holyfoot@deer.(none) +22 -0
Merge mysql.com:/home/hf/work/mysql-5.0-mrg
into mysql.com:/home/hf/work/mysql-5.1-mrg
MERGE: 1.1810.1698.187
BitKeeper/deleted/.del-bdb-deadlock.test@stripped, 2006-11-17 17:59:25+04:00,
holyfoot@deer.(none) +0 -0
Auto merged
MERGE: 1.9.1.2
BitKeeper/deleted/.del-bdb-deadlock.test@stripped, 2006-11-17 17:59:25+04:00,
holyfoot@deer.(none) +0 -0
Merge rename: mysql-test/t/bdb-deadlock.test ->
BitKeeper/deleted/.del-bdb-deadlock.test
Makefile.am@stripped, 2006-11-17 17:59:25+04:00, holyfoot@deer.(none) +0 -0
Auto merged
MERGE: 1.68.1.19
client/mysqltest.c@stripped, 2006-11-17 17:59:25+04:00, holyfoot@deer.(none) +0 -0
Auto merged
MERGE: 1.155.9.67
include/mysql.h@stripped, 2006-11-17 17:59:25+04:00, holyfoot@deer.(none) +0 -0
Auto merged
MERGE: 1.154.1.11
libmysql/libmysql.c@stripped, 2006-11-17 17:59:26+04:00, holyfoot@deer.(none) +0 -0
Auto merged
MERGE: 1.233.1.15
libmysqld/lib_sql.cc@stripped, 2006-11-17 17:59:26+04:00, holyfoot@deer.(none) +0 -0
Auto merged
MERGE: 1.107.1.9
mysql-test/include/deadlock.inc@stripped, 2006-11-17 18:20:24+04:00, holyfoot@deer.(none) +0
-0
SCCS merged
MERGE: 1.11.1.2
mysql-test/include/deadlock.inc@stripped, 2006-11-17 17:59:25+04:00,
holyfoot@deer.(none) +0 -0
Merge rename: mysql-test/t/innodb-deadlock.test -> mysql-test/include/deadlock.inc
mysql-test/r/order_by.result@stripped, 2006-11-17 17:59:26+04:00, holyfoot@deer.(none) +0 -0
Auto merged
MERGE: 1.55.1.1
mysql-test/r/subselect.result@stripped, 2006-11-17 17:59:26+04:00, holyfoot@deer.(none) +0
-0
Auto merged
MERGE: 1.134.1.31
mysql-test/t/disabled.def@stripped, 2006-11-17 18:24:49+04:00, holyfoot@deer.(none) +1 -0
merging
MERGE: 1.2.4.15
mysql-test/t/lock_multi.test@stripped, 2006-11-17 17:59:26+04:00, holyfoot@deer.(none) +0 -0
Auto merged
MERGE: 1.13.1.6
mysql-test/t/rename.test@stripped, 2006-11-17 17:59:26+04:00, holyfoot@deer.(none) +0 -0
Auto merged
MERGE: 1.15.1.3
mysql-test/t/show_check.test@stripped, 2006-11-17 17:59:26+04:00, holyfoot@deer.(none) +0 -0
Auto merged
MERGE: 1.54.1.8
mysql-test/t/status.test@stripped, 2006-11-17 17:59:26+04:00, holyfoot@deer.(none) +0 -0
Auto merged
MERGE: 1.15.1.1
mysql-test/t/subselect.test@stripped, 2006-11-17 17:59:26+04:00, holyfoot@deer.(none) +0 -0
Auto merged
MERGE: 1.129.1.4
sql-common/client.c@stripped, 2006-11-17 17:59:27+04:00, holyfoot@deer.(none) +0 -0
Auto merged
MERGE: 1.83.1.20
sql/item.cc@stripped, 2006-11-17 18:27:19+04:00, holyfoot@deer.(none) +0 -2
merging
MERGE: 1.113.1.125
sql/item_subselect.cc@stripped, 2006-11-17 17:59:26+04:00, holyfoot@deer.(none) +0 -0
Auto merged
MERGE: 1.113.1.22
sql/item_subselect.h@stripped, 2006-11-17 17:59:26+04:00, holyfoot@deer.(none) +0 -0
Auto merged
MERGE: 1.77.1.2
sql/protocol.cc@stripped, 2006-11-17 17:59:26+04:00, holyfoot@deer.(none) +0 -0
Auto merged
MERGE: 1.111.1.6
sql/protocol.h@stripped, 2006-11-17 17:59:27+04:00, holyfoot@deer.(none) +0 -0
Auto merged
MERGE: 1.31.1.2
sql/sql_class.h@stripped, 2006-11-17 17:59:27+04:00, holyfoot@deer.(none) +0 -0
Auto merged
MERGE: 1.230.1.79
# This is a BitKeeper patch. What follows are the unified diffs for the
# set of deltas contained in the patch. The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User: holyfoot
# Host: deer.(none)
# Root: /home/hf/work/mysql-5.1-mrg/RESYNC
--- 1.217/sql/item.cc 2006-11-17 18:27:38 +04:00
+++ 1.218/sql/item.cc 2006-11-17 18:27:38 +04:00
@@ -3672,11 +3672,37 @@ bool Item_field::fix_fields(THD *thd, It
Item** res= find_item_in_list(this, thd->lex->current_select->item_list,
&counter, REPORT_EXCEPT_NOT_FOUND,
¬_used);
- if (res != (Item **)not_found_item &&
- (*res)->type() == Item::FIELD_ITEM)
+ if (res != (Item **)not_found_item)
{
- set_field((*((Item_field**)res))->field);
- return 0;
+ if ((*res)->type() == Item::FIELD_ITEM)
+ {
+ /*
+ It's an Item_field referencing another Item_field in the select
+ list.
+ use the field from the Item_field in the select list and leave
+ the Item_field instance in place.
+ */
+ set_field((*((Item_field**)res))->field);
+ return 0;
+ }
+ else
+ {
+ /*
+ It's not an Item_field in the select list so we must make a new
+ Item_ref to point to the Item in the select list and replace the
+ Item_field created by the parser with the new Item_ref.
+ */
+ Item_ref *rf= new Item_ref(db_name,table_name,field_name);
+ if (!rf)
+ return 1;
+ thd->change_item_tree(ref, rf);
+ /*
+ Because Item_ref never substitutes itself with other items
+ in Item_ref::fix_fields(), we can safely use the original
+ pointer to it even after fix_fields()
+ */
+ return rf->fix_fields(thd, tables, ref) || rf->check_cols(1);
+ }
}
}
if ((ret= fix_outer_field(thd, &from_field, reference)) < 0)
--- 1.119/sql/protocol.cc 2006-11-17 18:27:38 +04:00
+++ 1.120/sql/protocol.cc 2006-11-17 18:27:38 +04:00
@@ -46,7 +46,7 @@ bool Protocol_prep::net_store_data(const
packet->realloc(packet_length+9+length))
return 1;
char *to=(char*) net_store_length((char*) packet->ptr()+packet_length,
- (ulonglong) length);
+ length);
memcpy(to,from,length);
packet->length((uint) (to+length-packet->ptr()));
return 0;
@@ -282,8 +282,8 @@ send_ok(THD *thd, ha_rows affected_rows,
}
buff[0]=0; // No fields
- pos=net_store_length(buff+1,(ulonglong) affected_rows);
- pos=net_store_length(pos, (ulonglong) id);
+ pos=net_store_length(buff+1,affected_rows);
+ pos=net_store_length(pos, id);
if (thd->client_capabilities & CLIENT_PROTOCOL_41)
{
DBUG_PRINT("info",
@@ -458,7 +458,7 @@ void net_send_error_packet(THD *thd, uin
ulonglong for bigger numbers.
*/
-char *net_store_length(char *pkg, uint length)
+static char *net_store_length_fast(char *pkg, uint length)
{
uchar *packet=(uchar*) pkg;
if (length < 251)
@@ -481,7 +481,7 @@ char *net_store_length(char *pkg, uint l
char *net_store_data(char *to,const char *from, uint length)
{
- to=net_store_length(to,length);
+ to=net_store_length_fast(to,length);
memcpy(to,from,length);
return to+length;
}
@@ -490,7 +490,7 @@ char *net_store_data(char *to,int32 from
{
char buff[20];
uint length=(uint) (int10_to_str(from,buff,10)-buff);
- to=net_store_length(to,length);
+ to=net_store_length_fast(to,length);
memcpy(to,buff,length);
return to+length;
}
@@ -499,7 +499,7 @@ char *net_store_data(char *to,longlong f
{
char buff[22];
uint length=(uint) (longlong10_to_str(from,buff,10)-buff);
- to=net_store_length(to,length);
+ to=net_store_length_fast(to,length);
memcpy(to,buff,length);
return to+length;
}
@@ -563,7 +563,7 @@ bool Protocol::send_fields(List<Item> *l
if (flags & SEND_NUM_ROWS)
{ // Packet with number of elements
- char *pos=net_store_length(buff, (uint) list->elements);
+ char *pos=net_store_length(buff, list->elements);
(void) my_net_write(&thd->net, buff,(uint) (pos-buff));
}
--- 1.326/sql/sql_class.h 2006-11-17 18:27:38 +04:00
+++ 1.327/sql/sql_class.h 2006-11-17 18:27:38 +04:00
@@ -838,6 +838,12 @@ public:
struct st_mysql_data **data_tail;
void clear_data_list();
struct st_mysql_data *alloc_new_dataset();
+ /*
+ In embedded server it points to the statement that is processed
+ in the current query. We store some results directly in statement
+ fields then.
+ */
+ struct st_mysql_stmt *current_stmt;
#endif
NET net; // client connection descriptor
MEM_ROOT warn_root; // For warnings and errors
--- 1.155/mysql-test/r/subselect.result 2006-11-17 18:27:38 +04:00
+++ 1.156/mysql-test/r/subselect.result 2006-11-17 18:27:38 +04:00
@@ -3001,6 +3001,38 @@ field1 field2
1 1
1 3
DROP TABLE t1, t2;
+CREATE TABLE t1(a int, INDEX (a));
+INSERT INTO t1 VALUES (1), (3), (5), (7);
+INSERT INTO t1 VALUES (NULL);
+CREATE TABLE t2(a int);
+INSERT INTO t2 VALUES (1),(2),(3);
+EXPLAIN SELECT a, a IN (SELECT a FROM t1) FROM t2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 ALL NULL NULL NULL NULL 3
+2 DEPENDENT SUBQUERY t1 index_subquery a a 5 func 2 Using index
+SELECT a, a IN (SELECT a FROM t1) FROM t2;
+a a IN (SELECT a FROM t1)
+1 1
+2 NULL
+3 1
+DROP TABLE t1,t2;
+CREATE TABLE t1 (a DATETIME);
+INSERT INTO t1 VALUES ('1998-09-23'), ('2003-03-25');
+CREATE TABLE t2 AS SELECT
+(SELECT a FROM t1 WHERE a < '2000-01-01') AS sub_a
+FROM t1 WHERE a > '2000-01-01';
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `sub_a` datetime default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+CREATE TABLE t3 AS (SELECT a FROM t1 WHERE a < '2000-01-01') UNION (SELECT a FROM t1
WHERE a > '2000-01-01');
+SHOW CREATE TABLE t3;
+Table Create Table
+t3 CREATE TABLE `t3` (
+ `a` datetime default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1,t2,t3;
create table t1 (df decimal(5,1));
insert into t1 values(1.1);
insert into t1 values(2.2);
--- 1.133/mysql-test/t/subselect.test 2006-11-17 18:27:38 +04:00
+++ 1.134/mysql-test/t/subselect.test 2006-11-17 18:27:38 +04:00
@@ -1955,6 +1955,39 @@ SELECT field1, field2
DROP TABLE t1, t2;
+#
+# Bug #23478: not top-level IN subquery returning a non-empty result set
+# with possible NULL values by index access from the outer query
+#
+
+CREATE TABLE t1(a int, INDEX (a));
+INSERT INTO t1 VALUES (1), (3), (5), (7);
+INSERT INTO t1 VALUES (NULL);
+
+CREATE TABLE t2(a int);
+INSERT INTO t2 VALUES (1),(2),(3);
+
+EXPLAIN SELECT a, a IN (SELECT a FROM t1) FROM t2;
+SELECT a, a IN (SELECT a FROM t1) FROM t2;
+
+DROP TABLE t1,t2;
+
+#
+# Bug #11302: getObject() returns a String for a sub-query of type datetime
+#
+CREATE TABLE t1 (a DATETIME);
+INSERT INTO t1 VALUES ('1998-09-23'), ('2003-03-25');
+
+CREATE TABLE t2 AS SELECT
+ (SELECT a FROM t1 WHERE a < '2000-01-01') AS sub_a
+ FROM t1 WHERE a > '2000-01-01';
+SHOW CREATE TABLE t2;
+
+CREATE TABLE t3 AS (SELECT a FROM t1 WHERE a < '2000-01-01') UNION (SELECT a FROM t1
WHERE a > '2000-01-01');
+SHOW CREATE TABLE t3;
+
+DROP TABLE t1,t2,t3;
+
# End of 4.1 tests
#
--- 1.131/sql/item_subselect.cc 2006-11-17 18:27:38 +04:00
+++ 1.132/sql/item_subselect.cc 2006-11-17 18:27:38 +04:00
@@ -434,6 +434,15 @@ enum Item_result Item_singlerow_subselec
return engine->type();
}
+/*
+ Don't rely on the result type to calculate field type.
+ Ask the engine instead.
+*/
+enum_field_types Item_singlerow_subselect::field_type() const
+{
+ return engine->field_type();
+}
+
void Item_singlerow_subselect::fix_length_and_dec()
{
if ((max_columns= engine->cols()) == 1)
@@ -710,6 +719,7 @@ double Item_in_subselect::val_real()
*/
DBUG_ASSERT(0);
DBUG_ASSERT(fixed == 1);
+ null_value= 0;
if (exec())
{
reset();
@@ -730,6 +740,7 @@ longlong Item_in_subselect::val_int()
*/
DBUG_ASSERT(0);
DBUG_ASSERT(fixed == 1);
+ null_value= 0;
if (exec())
{
reset();
@@ -750,6 +761,7 @@ String *Item_in_subselect::val_str(Strin
*/
DBUG_ASSERT(0);
DBUG_ASSERT(fixed == 1);
+ null_value= 0;
if (exec())
{
reset();
@@ -1542,32 +1554,36 @@ int subselect_uniquesubquery_engine::pre
return 1;
}
-static Item_result set_row(List<Item> &item_list, Item *item,
- Item_cache **row, bool *maybe_null)
+/*
+ makes storage for the output values for the subquery and calcuates
+ their data and column types and their nullability.
+*/
+void subselect_engine::set_row(List<Item> &item_list, Item_cache **row)
{
- Item_result res_type= STRING_RESULT;
Item *sel_item;
List_iterator_fast<Item> li(item_list);
+ res_type= STRING_RESULT;
+ res_field_type= FIELD_TYPE_VAR_STRING;
for (uint i= 0; (sel_item= li++); i++)
{
item->max_length= sel_item->max_length;
res_type= sel_item->result_type();
+ res_field_type= sel_item->field_type();
item->decimals= sel_item->decimals;
item->unsigned_flag= sel_item->unsigned_flag;
*maybe_null= sel_item->maybe_null;
if (!(row[i]= Item_cache::get_cache(res_type)))
- return STRING_RESULT; // we should return something
+ return;
row[i]->setup(sel_item);
}
if (item_list.elements > 1)
res_type= ROW_RESULT;
- return res_type;
}
void subselect_single_select_engine::fix_length_and_dec(Item_cache **row)
{
DBUG_ASSERT(row || select_lex->item_list.elements==1);
- res_type= set_row(select_lex->item_list, item, row, &maybe_null);
+ set_row(select_lex->item_list, row);
item->collation.set(row[0]->collation);
if (cols() != 1)
maybe_null= 0;
@@ -1579,13 +1595,14 @@ void subselect_union_engine::fix_length_
if (unit->first_select()->item_list.elements == 1)
{
- res_type= set_row(unit->types, item, row, &maybe_null);
+ set_row(unit->types, row);
item->collation.set(row[0]->collation);
}
else
{
- bool fake= 0;
- res_type= set_row(unit->types, item, row, &fake);
+ bool maybe_null_saved= maybe_null;
+ set_row(unit->types, row);
+ maybe_null= maybe_null_saved;
}
}
--- 1.79/sql/item_subselect.h 2006-11-17 18:27:38 +04:00
+++ 1.80/sql/item_subselect.h 2006-11-17 18:27:38 +04:00
@@ -156,6 +156,7 @@ public:
my_decimal *val_decimal(my_decimal *);
bool val_bool();
enum Item_result result_type() const;
+ enum_field_types field_type() const;
void fix_length_and_dec();
uint cols();
@@ -292,6 +293,7 @@ protected:
THD *thd; /* pointer to current THD */
Item_subselect *item; /* item, that use this engine */
enum Item_result res_type; /* type of results */
+ enum_field_types res_field_type; /* column type of the results */
bool maybe_null; /* may be null (first item in select) */
public:
@@ -301,6 +303,7 @@ public:
result= res;
item= si;
res_type= STRING_RESULT;
+ res_field_type= FIELD_TYPE_VAR_STRING;
maybe_null= 0;
}
virtual ~subselect_engine() {}; // to satisfy compiler
@@ -318,6 +321,7 @@ public:
virtual uint cols()= 0; /* return number of columns in select */
virtual uint8 uncacheable()= 0; /* query is uncacheable */
enum Item_result type() { return res_type; }
+ enum_field_types field_type() { return res_field_type; }
virtual void exclude()= 0;
bool may_be_null() { return maybe_null; };
virtual table_map upper_select_const_tables()= 0;
--- 1.113/sql-common/client.c 2006-11-17 18:27:38 +04:00
+++ 1.114/sql-common/client.c 2006-11-17 18:27:38 +04:00
@@ -1186,6 +1186,8 @@ unpack_fields(MYSQL_DATA *data,MEM_ROOT
for (row=data->data; row ; row = row->next,field++)
{
uchar *pos;
+ /* fields count may be wrong */
+ DBUG_ASSERT ((field - result) < fields);
cli_fetch_lengths(&lengths[0], row->data, default_value ? 8 : 7);
field->catalog = strdup_root(alloc,(char*) row->data[0]);
field->db = strdup_root(alloc,(char*) row->data[1]);
--- 1.56/mysql-test/r/order_by.result 2006-11-17 18:27:38 +04:00
+++ 1.57/mysql-test/r/order_by.result 2006-11-17 18:27:38 +04:00
@@ -854,6 +854,33 @@ b a
20 1
10 2
DROP TABLE t1;
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1),(2);
+SELECT a + 1 AS num FROM t1 ORDER BY 30 - num;
+num
+3
+2
+SELECT CONCAT('test', a) AS str FROM t1 ORDER BY UPPER(str);
+str
+test1
+test2
+SELECT a + 1 AS num FROM t1 GROUP BY 30 - num;
+num
+3
+2
+SELECT a + 1 AS num FROM t1 HAVING 30 - num;
+num
+2
+3
+SELECT a + 1 AS num, num + 1 FROM t1;
+ERROR 42S22: Unknown column 'num' in 'field list'
+SELECT a + 1 AS num, (select num + 2 FROM t1 LIMIT 1) FROM t1;
+num (select num + 2 FROM t1 LIMIT 1)
+2 4
+3 5
+SELECT a.a + 1 AS num FROM t1 a JOIN t1 b ON num = b.a;
+ERROR 42S22: Unknown column 'num' in 'on clause'
+DROP TABLE t1;
CREATE TABLE t1 (a int, b int, PRIMARY KEY (a));
INSERT INTO t1 VALUES (1,1), (2,2), (3,3);
explain SELECT t1.b as a, t2.b as c FROM
--- 1.18/mysql-test/t/rename.test 2006-11-17 18:27:38 +04:00
+++ 1.19/mysql-test/t/rename.test 2006-11-17 18:27:38 +04:00
@@ -2,10 +2,6 @@
# Test of rename table
#
-# Test requires concurrent connections, which can't be tested on embedded
-# server
--- source include/not_embedded.inc
-
--disable_warnings
drop table if exists t0,t1,t2,t3,t4;
# Clear up from other tests (to ensure that SHOW TABLES below is right)
--- 1.69/mysql-test/t/show_check.test 2006-11-17 18:27:38 +04:00
+++ 1.70/mysql-test/t/show_check.test 2006-11-17 18:27:38 +04:00
@@ -1,5 +1,4 @@
-# Requires use of multiple simultaneous connections, not supported with
-# embedded server testing
+# Uses GRANT commands that usually disabled in embedded server
-- source include/not_embedded.inc
# check that CSV engine was compiled in, as the result of the test
--- 1.23/mysql-test/t/lock_multi.test 2006-11-17 18:27:38 +04:00
+++ 1.24/mysql-test/t/lock_multi.test 2006-11-17 18:27:38 +04:00
@@ -1,11 +1,3 @@
-# This test doesn't work with the embedded version as this code
-# assumes that one query is running while we are doing queries on
-# a second connection.
-# This would work if mysqltest run would be threaded and handle each
-# connection in a separate thread.
-#
--- source include/not_embedded.inc
-
--disable_warnings
drop table if exists t1,t2;
--enable_warnings
--- 1.11.1.1/mysql-test/t/innodb-deadlock.test 2006-11-17 18:27:38 +04:00
+++ 1.14/mysql-test/include/deadlock.inc 2006-11-17 18:27:38 +04:00
@@ -1,6 +1,18 @@
--- source include/have_innodb.inc
+# include/deadlock.inc
+#
+# The variable
+# $engine_type -- storage engine to be tested
+# has to be set before sourcing this script.
+#
+# Last update:
+# 2006-07-26 ML refactoring + print when connection is switched
+# old name was t/innodb-deadlock.test
+# main code went into include/deadlock.inc
+#
+--echo # Establish connection con1 (user=root)
connect (con1,localhost,root,,);
+--echo # Establish connection con2 (user=root)
connect (con2,localhost,root,,);
--disable_warnings
@@ -11,29 +23,34 @@ drop table if exists t1,t2;
# Testing of FOR UPDATE
#
+--echo # Switch to connection con1
connection con1;
-create table t1 (id integer, x integer) engine=INNODB;
+eval create table t1 (id integer, x integer) engine = $engine_type;
insert into t1 values(0, 0);
set autocommit=0;
SELECT * from t1 where id = 0 FOR UPDATE;
+--echo # Switch to connection con2
connection con2;
set autocommit=0;
-# The following query should hang because con1 is locking the page
+# The following query should hang because con1 is locking the record
--send
update t1 set x=2 where id = 0;
--sleep 2
+--echo # Switch to connection con1
connection con1;
update t1 set x=1 where id = 0;
select * from t1;
commit;
+--echo # Switch to connection con2
connection con2;
reap;
commit;
+--echo # Switch to connection con1
connection con1;
select * from t1;
commit;
@@ -43,9 +60,10 @@ drop table t1;
# Testing of FOR UPDATE
#
+--echo # Switch to connection con1
connection con1;
-create table t1 (id integer, x integer) engine=INNODB;
-create table t2 (b integer, a integer) engine=INNODB;
+eval create table t1 (id integer, x integer) engine = $engine_type;
+eval create table t2 (b integer, a integer) engine = $engine_type;
insert into t1 values(0, 0), (300, 300);
insert into t2 values(0, 10), (1, 20), (2, 30);
commit;
@@ -55,61 +73,75 @@ update t2 set a=100 where b=(SELECT x fr
select * from t2;
select * from t1;
+--echo # Switch to connection con2
connection con2;
set autocommit=0;
-# The following query should hang because con1 is locking the page
+# The following query should hang because con1 is locking the record
--send
update t1 set x=2 where id = 0;
--sleep 2
+--echo # Switch to connection con1
connection con1;
update t1 set x=1 where id = 0;
select * from t1;
commit;
+--echo # Switch to connection con2
connection con2;
reap;
commit;
+--echo # Switch to connection con1
connection con1;
select * from t1;
commit;
drop table t1, t2;
-create table t1 (id integer, x integer) engine=INNODB;
-create table t2 (b integer, a integer) engine=INNODB;
+eval create table t1 (id integer, x integer) engine = $engine_type;
+eval create table t2 (b integer, a integer) engine = $engine_type;
insert into t1 values(0, 0), (300, 300);
insert into t2 values(0, 0), (1, 20), (2, 30);
commit;
+--echo # Switch to connection con1
connection con1;
select a,b from t2 UNION SELECT id, x from t1 FOR UPDATE;
select * from t2;
select * from t1;
+--echo # Switch to connection con2
connection con2;
-# The following query should hang because con1 is locking the page
+# The following query should hang because con1 is locking the record
update t2 set a=2 where b = 0;
select * from t2;
--send
update t1 set x=2 where id = 0;
--sleep 2
+--echo # Switch to connection con1
connection con1;
update t1 set x=1 where id = 0;
select * from t1;
commit;
+--echo # Switch to connection con2
connection con2;
reap;
commit;
+--echo # Switch to connection con1
connection con1;
select * from t1;
commit;
+# Cleanup
+--echo # Switch to connection default + disconnect con1 and con2
+connection default;
+disconnect con1;
+disconnect con2;
drop table t1, t2;
# End of 4.1 tests
--- 1.33/sql/protocol.h 2006-11-17 18:27:38 +04:00
+++ 1.34/sql/protocol.h 2006-11-17 18:27:38 +04:00
@@ -166,7 +166,6 @@ void send_ok(THD *thd, ha_rows affected_
const char *info=0);
void send_eof(THD *thd);
bool send_old_password_request(THD *thd);
-char *net_store_length(char *packet,uint length);
char *net_store_data(char *to,const char *from, uint length);
char *net_store_data(char *to,int32 from);
char *net_store_data(char *to,longlong from);
--- 1.122/libmysqld/lib_sql.cc 2006-11-17 18:27:38 +04:00
+++ 1.123/libmysqld/lib_sql.cc 2006-11-17 18:27:38 +04:00
@@ -100,6 +100,7 @@ emb_advanced_command(MYSQL *mysql, enum
mysql->affected_rows= ~(my_ulonglong) 0;
mysql->field_count= 0;
net->last_errno= 0;
+ thd->current_stmt= stmt;
thd->store_globals(); // Fix if more than one connect
/*
--- 1.246/client/mysqltest.c 2006-11-17 18:27:38 +04:00
+++ 1.247/client/mysqltest.c 2006-11-17 18:27:38 +04:00
@@ -29,6 +29,7 @@
Matt Wagner <matt@stripped>
Monty
Jani
+ Holyfoot
*/
#define MTEST_VERSION "3.0"
@@ -220,6 +221,12 @@ struct st_connection
MYSQL* util_mysql;
char *name;
MYSQL_STMT* stmt;
+
+ const char *cur_query;
+ int cur_query_len;
+ pthread_mutex_t mutex;
+ pthread_cond_t cond;
+ int query_done;
};
struct st_connection connections[128];
struct st_connection* cur_con, *next_con, *connections_end;
@@ -458,7 +465,6 @@ void mysql_disable_rpl_parse(MYSQL* mysq
int mysql_rpl_parse_enabled(MYSQL* mysql __attribute__((unused))) { return 1; }
my_bool mysql_rpl_probe(MYSQL *mysql __attribute__((unused))) { return 1; }
#endif
-
void replace_dynstr_append_mem(DYNAMIC_STRING *ds, const char *val,
int len);
void replace_dynstr_append(DYNAMIC_STRING *ds, const char *val);
@@ -470,6 +476,56 @@ void handle_error(struct st_command*,
void handle_no_error(struct st_command*);
+#ifdef EMBEDDED_LIBRARY
+/*
+ send_one_query executes query in separate thread what is
+ necessary in embedded library to run 'send' in proper way.
+ This implementation doesn't handle errors returned
+ by mysql_send_query. It's technically possible, though
+ i don't see where it is needed.
+*/
+pthread_handler_decl(send_one_query, arg)
+{
+ struct st_connection *cn= (struct st_connection*)arg;
+
+ mysql_thread_init();
+ VOID(mysql_send_query(&cn->mysql, cn->cur_query, cn->cur_query_len));
+
+ mysql_thread_end();
+ pthread_mutex_lock(&cn->mutex);
+ cn->query_done= 1;
+ VOID(pthread_cond_signal(&cn->cond));
+ pthread_mutex_unlock(&cn->mutex);
+ pthread_exit(0);
+ return 0;
+}
+
+static int do_send_query(struct st_connection *cn, const char *q, int q_len,
+ int flags)
+{
+ pthread_t tid;
+
+ if (flags & QUERY_REAP_FLAG)
+ return mysql_send_query(&cn->mysql, q, q_len);
+
+ if (pthread_mutex_init(&cn->mutex, NULL) ||
+ pthread_cond_init(&cn->cond, NULL))
+ die("Error in the thread library");
+
+ cn->cur_query= q;
+ cn->cur_query_len= q_len;
+ cn->query_done= 0;
+ if (pthread_create(&tid, NULL, send_one_query, (void*)cn))
+ die("Cannot start new thread for query");
+
+ return 0;
+}
+
+#else /*EMBEDDED_LIBRARY*/
+
+#define do_send_query(cn,q,q_len,flags) mysql_send_query(&cn->mysql, q, q_len)
+
+#endif /*EMBEDDED_LIBRARY*/
void do_eval(DYNAMIC_STRING *query_eval, const char *query,
const char *query_end, my_bool pass_through_escape_chars)
@@ -4498,7 +4554,6 @@ int append_warnings(DYNAMIC_STRING *ds,
}
-
/*
Run query using MySQL C API
@@ -4515,10 +4570,11 @@ int append_warnings(DYNAMIC_STRING *ds,
error - function will not return
*/
-void run_query_normal(MYSQL *mysql, struct st_command *command,
+void run_query_normal(struct st_connection *cn, struct st_command *command,
int flags, char *query, int query_len,
DYNAMIC_STRING *ds, DYNAMIC_STRING *ds_warnings)
{
+ MYSQL *mysql= &cn->mysql;
MYSQL_RES *res= 0;
int err= 0, counter= 0;
DBUG_ENTER("run_query_normal");
@@ -4530,14 +4586,26 @@ void run_query_normal(MYSQL *mysql, stru
/*
Send the query
*/
- if (mysql_send_query(mysql, query, query_len))
+ if (do_send_query(cn, query, query_len, flags))
{
handle_error(command, mysql_errno(mysql), mysql_error(mysql),
mysql_sqlstate(mysql), ds);
goto end;
}
}
-
+#ifdef EMBEDDED_LIBRARY
+ /*
+ Here we handle 'reap' command, so we need to check if the
+ query's thread was finished and probably wait
+ */
+ else if (flags & QUERY_REAP_FLAG)
+ {
+ pthread_mutex_lock(&cn->mutex);
+ while (!cn->query_done)
+ pthread_cond_wait(&cn->cond, &cn->mutex);
+ pthread_mutex_unlock(&cn->mutex);
+ }
+#endif /*EMBEDDED_LIBRARY*/
if (!(flags & QUERY_REAP_FLAG))
DBUG_VOID_RETURN;
@@ -5028,8 +5096,9 @@ int util_query(MYSQL* org_mysql, const c
*/
-void run_query(MYSQL *mysql, struct st_command *command, int flags)
+void run_query(struct st_connection *cn, struct st_command *command, int flags)
{
+ MYSQL *mysql= &cn->mysql;
DYNAMIC_STRING *ds;
DYNAMIC_STRING ds_result;
DYNAMIC_STRING ds_warnings;
@@ -5186,7 +5255,7 @@ void run_query(MYSQL *mysql, struct st_c
match_re(&ps_re, query))
run_query_stmt(mysql, command, query, query_len, ds, &ds_warnings);
else
- run_query_normal(mysql, command, flags, query, query_len,
+ run_query_normal(cn, command, flags, query, query_len,
ds, &ds_warnings);
if (sp_created)
@@ -5651,7 +5720,7 @@ int main(int argc, char **argv)
strmake(command->require_file, save_file, sizeof(save_file));
save_file[0]= 0;
}
- run_query(&cur_con->mysql, command, QUERY_REAP_FLAG|QUERY_SEND_FLAG);
+ run_query(cur_con, command, QUERY_REAP_FLAG|QUERY_SEND_FLAG);
display_result_vertically= old_display_result_vertically;
command->last_argument= command->end;
command_executed++;
@@ -5682,7 +5751,7 @@ int main(int argc, char **argv)
strmake(command->require_file, save_file, sizeof(save_file));
save_file[0]= 0;
}
- run_query(&cur_con->mysql, command, flags);
+ run_query(cur_con, command, flags);
command_executed++;
command->last_argument= command->end;
break;
@@ -5708,7 +5777,7 @@ int main(int argc, char **argv)
the query and read the result some time later when reap instruction
is given on this connection.
*/
- run_query(&cur_con->mysql, command, QUERY_SEND_FLAG);
+ run_query(cur_con, command, QUERY_SEND_FLAG);
command_executed++;
command->last_argument= command->end;
break;
--- 1.17/mysql-test/t/status.test 2006-11-17 18:27:38 +04:00
+++ 1.18/mysql-test/t/status.test 2006-11-17 18:27:38 +04:00
@@ -1,10 +1,3 @@
-# This test doesn't work with the embedded version as this code
-# assumes that one query is running while we are doing queries on
-# a second connection.
-# This would work if mysqltest run would be threaded and handle each
-# connection in a separate thread.
-#
---source include/not_embedded.inc
# PS causes different statistics
--disable_ps_protocol
| Thread |
|---|
| • bk commit into 5.1 tree (holyfoot:1.2367) | holyfoot | 17 Nov |