summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <bell@sanja.is.com.ua>2004-10-27 21:17:31 +0300
committerunknown <bell@sanja.is.com.ua>2004-10-27 21:17:31 +0300
commita94c7639da634502edaae1d28c09dea924159032 (patch)
tree8613fb623c030f24afa43b30b38a0839da9a2f38
parent55833fb49bf8570ee11d4b85b143a9a3975733fa (diff)
parent464da8f13a69d7ce51e1c130475e1a8c4cab59a5 (diff)
downloadmariadb-git-a94c7639da634502edaae1d28c09dea924159032.tar.gz
Merge sanja.is.com.ua:/home/bell/mysql/bk/mysql-4.1
into sanja.is.com.ua:/home/bell/mysql/bk/work-ps-4.1
-rw-r--r--mysql-test/r/subselect.result15
-rw-r--r--mysql-test/t/subselect.test5
-rw-r--r--sql/item_subselect.cc91
-rw-r--r--sql/item_subselect.h4
4 files changed, 91 insertions, 24 deletions
diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result
index 04c5f685f58..32d482f5a32 100644
--- a/mysql-test/r/subselect.result
+++ b/mysql-test/r/subselect.result
@@ -55,7 +55,7 @@ SELECT 1 FROM (SELECT 1 as a) as b HAVING (SELECT a)=1;
1
1
SELECT (SELECT 1), a;
-ERROR 42S22: Unknown column 'a' in 'checking transformed subquery'
+ERROR 42S22: Unknown column 'a' in 'field list'
SELECT 1 as a FROM (SELECT 1) as b HAVING (SELECT a)=1;
a
1
@@ -999,7 +999,9 @@ drop table t1, t2;
CREATE TABLE `t1` (`i` int(11) NOT NULL default '0',PRIMARY KEY (`i`)) ENGINE=MyISAM CHARSET=latin1;
INSERT INTO t1 VALUES (1);
UPDATE t1 SET i=i+1 WHERE i=(SELECT MAX(i));
-ERROR HY000: Invalid use of group function
+select * from t1;
+i
+1
drop table t1;
CREATE TABLE t1 (a int(1));
EXPLAIN EXTENDED SELECT (SELECT RAND() FROM t1) FROM t1;
@@ -1084,7 +1086,7 @@ SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` bigint(20) NOT NULL default '0',
- `(SELECT a)` bigint(20) default NULL
+ `(SELECT a)` bigint(20) NOT NULL default '0'
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
CREATE TABLE t1 SELECT * FROM (SELECT 1 as a,(SELECT a+0)) a;
@@ -1102,7 +1104,7 @@ a
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `a` bigint(20) default NULL
+ `a` bigint(20) NOT NULL default '0'
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 (a int);
@@ -1186,11 +1188,12 @@ PRIMARY KEY (`i`)
) ENGINE=MyISAM CHARSET=latin1;
INSERT INTO t1 VALUES (1);
UPDATE t1 SET i=i+(SELECT MAX(i) FROM (SELECT 1) t) WHERE i=(SELECT MAX(i));
-ERROR HY000: Invalid use of group function
UPDATE t1 SET i=i+1 WHERE i=(SELECT MAX(i));
-ERROR HY000: Invalid use of group function
UPDATE t1 SET t.i=i+(SELECT MAX(i) FROM (SELECT 1) t);
ERROR 42S02: Unknown table 't' in field list
+select * from t1;
+i
+1
drop table t1;
CREATE TABLE t1 (
id int(11) default NULL
diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test
index 5e3aa4064e4..e0f6fcbf515 100644
--- a/mysql-test/t/subselect.test
+++ b/mysql-test/t/subselect.test
@@ -543,8 +543,8 @@ drop table t1, t2;
CREATE TABLE `t1` (`i` int(11) NOT NULL default '0',PRIMARY KEY (`i`)) ENGINE=MyISAM CHARSET=latin1;
INSERT INTO t1 VALUES (1);
--- error 1111
UPDATE t1 SET i=i+1 WHERE i=(SELECT MAX(i));
+select * from t1;
drop table t1;
#test of uncacheable subqueries
@@ -689,12 +689,11 @@ CREATE TABLE `t1` (
) ENGINE=MyISAM CHARSET=latin1;
INSERT INTO t1 VALUES (1);
--- error 1111
UPDATE t1 SET i=i+(SELECT MAX(i) FROM (SELECT 1) t) WHERE i=(SELECT MAX(i));
--- error 1111
UPDATE t1 SET i=i+1 WHERE i=(SELECT MAX(i));
-- error 1109
UPDATE t1 SET t.i=i+(SELECT MAX(i) FROM (SELECT 1) t);
+select * from t1;
drop table t1;
#
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index a869e2d24fb..401d4dee20f 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -164,12 +164,7 @@ bool Item_subselect::fix_fields(THD *thd_param, TABLE_LIST *tables, Item **ref)
thd->where= "checking transformed subquery";
if (!(*ref)->fixed)
ret= (*ref)->fix_fields(thd, tables, ref);
- // We can't substitute aggregate functions like "SELECT (max(i))"
- if (substype() == SINGLEROW_SUBS && (*ref)->with_sum_func)
- {
- my_error(ER_INVALID_GROUP_FUNC_USE, MYF(0));
- return 1;
- }
+ thd->where= save_where;
return ret;
}
// Is it one field subselect?
@@ -322,6 +317,7 @@ Item_singlerow_subselect::select_transformer(JOIN *join)
if (!select_lex->master_unit()->first_select()->next_select() &&
!select_lex->table_list.elements &&
select_lex->item_list.elements == 1 &&
+ !select_lex->item_list.head()->with_sum_func &&
/*
We cant change name of Item_field or Item_ref, because it will
prevent it's correct resolving, but we should save name of
@@ -330,7 +326,13 @@ Item_singlerow_subselect::select_transformer(JOIN *join)
TODO: solve above problem
*/
!(select_lex->item_list.head()->type() == FIELD_ITEM ||
- select_lex->item_list.head()->type() == REF_ITEM)
+ select_lex->item_list.head()->type() == REF_ITEM) &&
+ /*
+ switch off this optimisation for prepare statement,
+ because we do not rollback this changes
+ TODO: make rollback for it, or special name resolving mode in 5.0.
+ */
+ !arena->is_stmt_prepare()
)
{
@@ -352,9 +354,6 @@ Item_singlerow_subselect::select_transformer(JOIN *join)
if (join->conds || join->having)
{
Item *cond;
- if (arena->is_stmt_prepare())
- thd->set_n_backup_item_arena(arena, &backup);
-
if (!join->having)
cond= join->conds;
else if (!join->conds)
@@ -365,16 +364,12 @@ Item_singlerow_subselect::select_transformer(JOIN *join)
if (!(substitution= new Item_func_if(cond, substitution,
new Item_null())))
goto err;
- if (arena->is_stmt_prepare())
- thd->restore_backup_item_arena(arena, &backup);
- }
+ }
return RES_REDUCE;
}
return RES_OK;
err:
- if (arena->is_stmt_prepare())
- thd->restore_backup_item_arena(arena, &backup);
return RES_ERROR;
}
@@ -401,6 +396,13 @@ void Item_singlerow_subselect::fix_length_and_dec()
engine->fix_length_and_dec(row);
value= *row;
}
+ /*
+ If there are not tables in subquery then ability to have NULL value
+ depends on SELECT list (if single row subquery have tables then it
+ always can be NULL if there are not records fetched).
+ */
+ if (engine->no_tables())
+ maybe_null= engine->may_be_null();
}
uint Item_singlerow_subselect::cols()
@@ -644,6 +646,7 @@ Item_subselect::trans_res
Item_in_subselect::single_value_transformer(JOIN *join,
Comp_creator *func)
{
+ const char *save_where= thd->where;
DBUG_ENTER("Item_in_subselect::single_value_transformer");
if (changed)
@@ -899,6 +902,7 @@ Item_in_subselect::single_value_transformer(JOIN *join,
ok:
if (arena->is_stmt_prepare())
thd->restore_backup_item_arena(arena, &backup);
+ thd->where= save_where;
DBUG_RETURN(RES_OK);
err:
@@ -911,6 +915,7 @@ err:
Item_subselect::trans_res
Item_in_subselect::row_value_transformer(JOIN *join)
{
+ const char *save_where= thd->where;
DBUG_ENTER("Item_in_subselect::row_value_transformer");
if (changed)
@@ -1003,6 +1008,7 @@ Item_in_subselect::row_value_transformer(JOIN *join)
}
if (arena->is_stmt_prepare())
thd->restore_backup_item_arena(arena, &backup);
+ thd->where= save_where;
DBUG_RETURN(RES_OK);
err:
@@ -1562,3 +1568,58 @@ int subselect_uniquesubquery_engine::change_item(Item_subselect *si,
DBUG_ASSERT(0);
return -1;
}
+
+
+/*
+ Report about presence of tables in subquery
+
+ SINOPSYS
+ subselect_single_select_engine::no_tables()
+
+ RETURN
+ TRUE there are not tables used in subquery
+ FALSE there are some tables in subquery
+*/
+bool subselect_single_select_engine::no_tables()
+{
+ return(select_lex->table_list.elements == 0);
+}
+
+
+/*
+ Report about presence of tables in subquery
+
+ SINOPSYS
+ subselect_union_engine::no_tables()
+
+ RETURN
+ TRUE there are not tables used in subquery
+ FALSE there are some tables in subquery
+*/
+bool subselect_union_engine::no_tables()
+{
+ for (SELECT_LEX *sl= unit->first_select(); sl; sl= sl->next_select())
+ {
+ if (sl->table_list.elements)
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
+/*
+ Report about presence of tables in subquery
+
+ SINOPSYS
+ subselect_uniquesubquery_engine::no_tables()
+
+ RETURN
+ TRUE there are not tables used in subquery
+ FALSE there are some tables in subquery
+*/
+
+bool subselect_uniquesubquery_engine::no_tables()
+{
+ /* returning value is correct, but this method should never be called */
+ return 0;
+}
diff --git a/sql/item_subselect.h b/sql/item_subselect.h
index f570d89f28f..764c41f33b4 100644
--- a/sql/item_subselect.h
+++ b/sql/item_subselect.h
@@ -291,6 +291,7 @@ public:
static table_map calc_const_tables(TABLE_LIST *);
virtual void print(String *str)= 0;
virtual int change_item(Item_subselect *si, select_subselect *result)= 0;
+ virtual bool no_tables()= 0;
};
@@ -315,6 +316,7 @@ public:
table_map upper_select_const_tables();
void print (String *str);
int change_item(Item_subselect *si, select_subselect *result);
+ bool no_tables();
};
@@ -335,6 +337,7 @@ public:
table_map upper_select_const_tables();
void print (String *str);
int change_item(Item_subselect *si, select_subselect *result);
+ bool no_tables();
};
@@ -364,6 +367,7 @@ public:
table_map upper_select_const_tables() { return 0; }
void print (String *str);
int change_item(Item_subselect *si, select_subselect *result);
+ bool no_tables();
};