Commit c6a2ae17 authored by unknown's avatar unknown

EXISTS type of subselect

more correct parameters in result creation script


mysql-test/create-test-result:
  more correct parameters in result creation script
mysql-test/r/subselect.result:
  test of EXISTS
mysql-test/t/subselect.test:
  test of EXISTS
sql/item_subselect.cc:
  EXISTS type of subselect
sql/item_subselect.h:
  EXISTS type of subselect
sql/sql_class.cc:
  EXISTS type of subselect
sql/sql_class.h:
  EXISTS type of subselect
sql/sql_yacc.yy:
  EXISTS type of subselect
parent 454712d2
......@@ -32,7 +32,7 @@ result_file=$RESULT_DIR/$test_name.result
touch $result_file
echo "Running the test case against empty file, will fail, but don't worry"
./mysql-test-run --do-test=$test_name
./mysql-test-run --local $test_name
reject_file=$result_file.reject
......
......@@ -67,4 +67,11 @@ b (select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2)
8 7.5000
8 6.0000
9 5.5000
select * from t3 where exists (select * from t2 where t2.b=t3.a);
a
7
select * from t3 where not exists (select * from t2 where t2.b=t3.a);
a
6
3
drop table t1,t2,t3,t4;
......@@ -26,4 +26,6 @@ select * from t1 where t1.a=(select t2.a from t2 where t2.b=(select max(a) from
select * from t1 where t1.a=(select t2.a from t2 where t2.b=(select max(a) from t3 where t3.a > t1.a) order by 1 desc limit 1);
select * from t1 where t1.a=(select t2.a from t2 where t2.b=(select max(a) from t3 where t3.a < t1.a) order by 1 desc limit 1);
select b,(select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2) from t4;
select * from t3 where exists (select * from t2 where t2.b=t3.a);
select * from t3 where not exists (select * from t2 where t2.b=t3.a);
drop table t1,t2,t3,t4;
......@@ -35,12 +35,13 @@ SUBSELECT TODO:
#include "mysql_priv.h"
#include "sql_select.h"
Item_subselect::Item_subselect(THD *thd, st_select_lex *select_lex):
Item_subselect::Item_subselect(THD *thd, st_select_lex *select_lex,
select_subselect *result):
assigned(0), executed(0), optimized(0), error(0)
{
DBUG_ENTER("Item_subselect::Item_subselect");
DBUG_PRINT("subs", ("select_lex 0x%xl", (long) select_lex));
result= new select_subselect(this);
this->result= result;
SELECT_LEX_UNIT *unit= select_lex->master_unit();
unit->offset_limit_cnt= unit->global_parameters->offset_limit;
unit->select_limit_cnt= unit->global_parameters->select_limit+
......@@ -51,41 +52,15 @@ Item_subselect::Item_subselect(THD *thd, st_select_lex *select_lex):
select_lex->options&= ~OPTION_FOUND_ROWS;
join= new JOIN(thd, select_lex->item_list, select_lex->options, result);
this->select_lex= select_lex;
maybe_null= 1;
assign_null();
/*
item value is NULL if select_subselect not changed this value
(i.e. some rows will be found returned)
*/
assign_null();
null_value= 1;
DBUG_VOID_RETURN;
}
Item::Type Item_subselect::type() const
{
return SUBSELECT_ITEM;
}
double Item_subselect::val ()
{
if (exec())
return 0;
return real_value;
}
longlong Item_subselect::val_int ()
{
if (exec())
return 0;
return int_value;
}
String *Item_subselect::val_str (String *str)
{
if (exec() || null_value)
return 0;
return &str_value;
}
void Item_subselect::make_field (Send_field *tmp_field)
{
if (null_value)
......@@ -110,7 +85,7 @@ bool Item_subselect::fix_fields(THD *thd,TABLE_LIST *tables)
return 1;
}
// Is it one field subselect?
if (select_lex->item_list.elements != 1)
if (select_lex->item_list.elements > max_columns)
{
my_printf_error(ER_SUBSELECT_NO_1_COL, ER(ER_SUBSELECT_NO_1_COL), MYF(0));
return 1;
......@@ -131,13 +106,14 @@ bool Item_subselect::fix_fields(THD *thd,TABLE_LIST *tables)
int Item_subselect::exec()
{
DBUG_ENTER("Item_subselect::exec");
if (!optimized)
{
optimized=1;
if (join->optimize())
{
executed= 1;
return (join->error?join->error:1);
DBUG_RETURN(join->error?join->error:1);
}
}
if (join->select_lex->depended && executed)
......@@ -145,7 +121,7 @@ int Item_subselect::exec()
if (join->reinit())
{
error= 1;
return 1;
DBUG_RETURN(1);
}
assign_null();
executed= assigned= 0;
......@@ -157,7 +133,80 @@ int Item_subselect::exec()
join->exec();
join->thd->lex.select= save_select;
executed= 1;
return join->error;
DBUG_RETURN(join->error);
}
DBUG_RETURN(0);
}
inline table_map Item_subselect::used_tables() const
{
return (table_map) select_lex->depended ? 1L : 0L;
}
Item_singleval_subselect::Item_singleval_subselect(THD *thd,
st_select_lex *select_lex):
Item_subselect(thd, select_lex, new select_singleval_subselect(this))
{
max_columns= 1;
maybe_null= 1;
}
Item::Type Item_subselect::type() const
{
return SUBSELECT_ITEM;
}
double Item_singleval_subselect::val ()
{
if (exec())
return 0;
return real_value;
}
longlong Item_singleval_subselect::val_int ()
{
if (exec())
return 0;
return int_value;
}
String *Item_singleval_subselect::val_str (String *str)
{
if (exec() || null_value)
return 0;
return &str_value;
}
Item_exists_subselect::Item_exists_subselect(THD *thd,
st_select_lex *select_lex):
Item_subselect(thd, select_lex, new select_singleval_subselect(this))
{
max_columns= UINT_MAX;
null_value= 0; //can't be NULL
maybe_null= 0; //can't be NULL
value= 0;
select_lex->select_limit= 1; // we need only 1 row to determinate existence
}
double Item_exists_subselect::val ()
{
if (exec())
return 0;
return (double) value;
}
longlong Item_exists_subselect::val_int ()
{
if (exec())
return 0;
return value;
}
String *Item_exists_subselect::val_str(String *str)
{
if (exec())
return 0;
str->set(value);
return str;
}
......@@ -24,42 +24,34 @@ struct st_select_lex;
class JOIN;
class select_subselect;
/* simple (not depended of covered select ) subselect */
/* base class for subselects */
class Item_subselect :public Item
{
protected:
longlong int_value;
double real_value;
uint max_columns;
my_bool assigned; /* value already assigned to subselect */
my_bool executed; /* simple subselect is executed */
my_bool optimized; /* simple subselect is optimized */
my_bool error; /* error in query */
enum Item_result res_type;
int exec();
void assign_null()
virtual void assign_null()
{
null_value= 1;
int_value= 0;
real_value= 0;
max_length= 4;
res_type= STRING_RESULT;
}
public:
st_select_lex *select_lex;
JOIN *join;
select_subselect *result;
Item_subselect(THD *thd, st_select_lex *select_lex);
Item_subselect(THD *thd, st_select_lex *select_lex,
select_subselect* result);
Item_subselect(Item_subselect *item)
{
null_value= item->null_value;
int_value= item->int_value;
real_value= item->real_value;
max_length= item->max_length;
decimals= item->decimals;
res_type= item->res_type;
max_columns= item->max_columns;
assigned= item->assigned;
executed= item->executed;
select_lex= item->select_lex;
......@@ -69,16 +61,75 @@ class Item_subselect :public Item
error= item->error;
}
enum Type type() const;
double val ();
longlong val_int ();
String *val_str (String *);
bool is_null() { return null_value; }
void make_field (Send_field *);
bool fix_fields(THD *thd, TABLE_LIST *tables);
Item *new_item() { return new Item_subselect(this); }
enum Item_result result_type() const { return res_type; }
table_map used_tables() const;
friend class select_subselect;
};
/* single value subselect */
class Item_singleval_subselect :public Item_subselect
{
protected:
longlong int_value;
double real_value;
enum Item_result res_type;
virtual void assign_null()
{
null_value= 1;
int_value= 0;
real_value= 0;
max_length= 4;
res_type= STRING_RESULT;
}
public:
Item_singleval_subselect(THD *thd, st_select_lex *select_lex);
Item_singleval_subselect(Item_singleval_subselect *item):
Item_subselect(item)
{
int_value= item->int_value;
real_value= item->real_value;
max_length= item->max_length;
decimals= item->decimals;
res_type= item->res_type;
}
double val ();
longlong val_int ();
String *val_str (String *);
Item *new_item() { return new Item_singleval_subselect(this); }
enum Item_result result_type() const { return res_type; }
friend class select_singleval_subselect;
};
/* exists subselect */
class Item_exists_subselect :public Item_subselect
{
protected:
longlong value;
virtual void assign_null()
{
value= 0;
}
public:
Item_exists_subselect(THD *thd, st_select_lex *select_lex);
Item_exists_subselect(Item_exists_subselect *item):
Item_subselect(item)
{
value= item->value;
}
Item *new_item() { return new Item_exists_subselect(this); }
enum Item_result result_type() const { return INT_RESULT;}
longlong val_int();
double val();
String *val_str(String*);
friend class select_exists_subselect;
};
......@@ -763,7 +763,6 @@ void select_dump::send_error(uint errcode,const char *err)
file= -1;
}
bool select_dump::send_eof()
{
int error=test(end_io_cache(&cache));
......@@ -782,10 +781,11 @@ select_subselect::select_subselect(Item_subselect *item)
this->item=item;
}
bool select_subselect::send_data(List<Item> &items)
bool select_singleval_subselect::send_data(List<Item> &items)
{
DBUG_ENTER("select_subselect::send_data");
if (item->assigned){
DBUG_ENTER("select_singleval_subselect::send_data");
Item_singleval_subselect *it= (Item_singleval_subselect *)item;
if (it->assigned){
my_printf_error(ER_SUBSELECT_NO_1_ROW, ER(ER_SUBSELECT_NO_1_ROW), MYF(0));
DBUG_RETURN(1);
}
......@@ -800,18 +800,33 @@ bool select_subselect::send_data(List<Item> &items)
Following val() call have to be first, because function AVG() & STD()
calculate value on it & determinate "is it NULL?".
*/
item->real_value= val_item->val();
if ((item->null_value= val_item->is_null()))
it->real_value= val_item->val();
if ((it->null_value= val_item->is_null()))
{
item->assign_null();
it->assign_null();
} else {
item->max_length= val_item->max_length;
item->decimals= val_item->decimals;
item->binary= val_item->binary;
val_item->val_str(&item->str_value);
item->int_value= val_item->val_int();
item->res_type= val_item->result_type();
}
item->assigned= 1;
it->max_length= val_item->max_length;
it->decimals= val_item->decimals;
it->binary= val_item->binary;
val_item->val_str(&it->str_value);
it->int_value= val_item->val_int();
it->res_type= val_item->result_type();
}
it->assigned= 1;
DBUG_RETURN(0);
}
bool select_exists_subselect::send_data(List<Item> &items)
{
DBUG_ENTER("select_exists_subselect::send_data");
Item_exists_subselect *it= (Item_exists_subselect *)item;
if (unit->offset_limit_cnt)
{ // Using limit offset,count
unit->offset_limit_cnt--;
DBUG_RETURN(0);
}
it->value= 1;
it->assigned= 1;
DBUG_RETURN(0);
}
......@@ -712,19 +712,36 @@ class select_union :public select_result {
bool flush();
};
/* Single value subselect interface class */
/* Base subselect interface class */
class select_subselect :public select_result
{
protected:
Item_subselect *item;
public:
select_subselect(Item_subselect *item);
bool send_fields(List<Item> &list, uint flag) { return 0; };
bool send_data(List<Item> &items);
bool send_data(List<Item> &items)=0;
bool send_eof() { return 0; };
friend class Ttem_subselect;
};
/* Single value subselect interface class */
class select_singleval_subselect :public select_subselect
{
public:
select_singleval_subselect(Item_subselect *item):select_subselect(item){}
bool send_data(List<Item> &items);
};
/* EXISTS subselect interface class */
class select_exists_subselect :public select_subselect
{
public:
select_exists_subselect(Item_subselect *item):select_subselect(item){}
bool send_data(List<Item> &items);
};
/* Structs used when sorting */
typedef struct st_sort_field {
......
......@@ -548,7 +548,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
literal text_literal insert_ident order_ident
simple_ident select_item2 expr opt_expr opt_else sum_expr in_sum_expr
table_wild opt_pad no_in_expr expr_expr simple_expr no_and_expr
using_list subselect subselect_init
using_list singleval_subselect singleval_subselect_init
exists_subselect exists_subselect_init
%type <item_list>
expr_list udf_expr_list when_list ident_list ident_list_arg
......@@ -1738,7 +1739,8 @@ simple_expr:
| NOT expr %prec NEG { $$= new Item_func_not($2); }
| '!' expr %prec NEG { $$= new Item_func_not($2); }
| '(' expr ')' { $$= $2; }
| subselect { $$= $1; }
| EXISTS exists_subselect { $$= $2; }
| singleval_subselect { $$= $1; }
| '{' ident expr '}' { $$= $3; }
| MATCH ident_list_arg AGAINST '(' expr ')'
{ Select->ftfunc_list.push_back((Item_func_match *)
......@@ -3918,17 +3920,30 @@ union_option:
/* empty */ {}
| ALL {Lex->union_option=1;};
subselect:
subselect_start subselect_init
singleval_subselect:
subselect_start singleval_subselect_init
subselect_end
{
$$= $2;
};
subselect_init:
singleval_subselect_init:
select_init
{
$$= new Item_subselect(current_thd, Lex->select);
$$= new Item_singleval_subselect(current_thd, Lex->select);
};
exists_subselect:
subselect_start exists_subselect_init
subselect_end
{
$$= $2;
};
exists_subselect_init:
select_init
{
$$= new Item_exists_subselect(current_thd, Lex->select);
};
subselect_start:
......
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