summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/row.result19
-rw-r--r--mysql-test/t/row.test17
-rw-r--r--sql/item.h2
-rw-r--r--sql/item_cmpfunc.cc68
-rw-r--r--sql/item_cmpfunc.h19
-rw-r--r--sql/sql_yacc.yy72
6 files changed, 94 insertions, 103 deletions
diff --git a/mysql-test/r/row.result b/mysql-test/r/row.result
index f3522e05380..d86ae6c7961 100644
--- a/mysql-test/r/row.result
+++ b/mysql-test/r/row.result
@@ -1,6 +1,6 @@
drop table if exists t1;
-select row(1,2,3) IN (row(3,2,3), row(1,2,3), row(1,3,3));
-row(1,2,3) IN (row(3,2,3), row(1,2,3), row(1,3,3))
+select (1,2,3) IN ((3,2,3), (1,2,3), (1,3,3));
+(1,2,3) IN ((3,2,3), (1,2,3), (1,3,3))
1
select row(10,2,3) IN (row(3,2,3), row(1,2,3), row(1,3,3));
row(10,2,3) IN (row(3,2,3), row(1,2,3), row(1,3,3))
@@ -32,14 +32,23 @@ NULL
select row('b',1.5,3) IN (row('b',NULL,4), row('a',1.5,3), row(1,3,3));
row('b',1.5,3) IN (row('b',NULL,4), row('a',1.5,3), row(1,3,3))
0
-select row(1,2,row(3,4)) IN (row(3,2,row(3,4)), row(1,2,row(3,4)));
-row(1,2,row(3,4)) IN (row(3,2,row(3,4)), row(1,2,row(3,4)))
+select (1,2,(3,4)) IN ((3,2,(3,4)), (1,2,(3,4)));
+(1,2,(3,4)) IN ((3,2,(3,4)), (1,2,(3,4)))
1
select row(1,2,row(3,4)) IN (row(3,2,row(3,4)), row(1,2,4));
Cardinality error (more/less than 2 columns)
select row(1,2,row(3,4)) IN (row(3,2,row(3,4)), row(1,2,row(3,NULL)));
row(1,2,row(3,4)) IN (row(3,2,row(3,4)), row(1,2,row(3,NULL)))
NULL
+SELECT (1,2,3)=(0,NULL,3);
+(1,2,3)=(0,NULL,3)
+0
+SELECT (1,2,3)=(1,NULL,3);
+(1,2,3)=(1,NULL,3)
+NULL
+SELECT (1,2,3)=(1,NULL,0);
+(1,2,3)=(1,NULL,0)
+NULL
SELECT ROW(1,2,3)=ROW(1,2,3);
ROW(1,2,3)=ROW(1,2,3)
1
@@ -132,4 +141,6 @@ select 1 from t1 where ROW(1,1);
Cardinality error (more/less than 1 columns)
select count(*) from t1 order by ROW(1,1);
Cardinality error (more/less than 1 columns)
+select count(*) from t1 having (1,1) order by i;
+Cardinality error (more/less than 1 columns)
drop table t1;
diff --git a/mysql-test/t/row.test b/mysql-test/t/row.test
index 099eaa95c77..98fd640f12e 100644
--- a/mysql-test/t/row.test
+++ b/mysql-test/t/row.test
@@ -3,7 +3,7 @@
drop table if exists t1;
--enable_warnings
-select row(1,2,3) IN (row(3,2,3), row(1,2,3), row(1,3,3));
+select (1,2,3) IN ((3,2,3), (1,2,3), (1,3,3));
select row(10,2,3) IN (row(3,2,3), row(1,2,3), row(1,3,3));
select row(1,2,3) IN (row(3,NULL,3), row(1,2,3), row(1,3,3));
select row(10,2,3) IN (row(3,NULL,3), row(1,2,3), row(1,3,3));
@@ -14,11 +14,16 @@ select row('a',1.5,3) IN (row(3,NULL,3), row('a',1.5,3), row(1,3,3));
select row('b',1.5,3) IN (row(3,NULL,3), row('a',1.5,3), row(1,3,3));
select row('b',1.5,3) IN (row('b',NULL,3), row('a',1.5,3), row(1,3,3));
select row('b',1.5,3) IN (row('b',NULL,4), row('a',1.5,3), row(1,3,3));
-select row(1,2,row(3,4)) IN (row(3,2,row(3,4)), row(1,2,row(3,4)));
+select (1,2,(3,4)) IN ((3,2,(3,4)), (1,2,(3,4)));
-- error 1239
select row(1,2,row(3,4)) IN (row(3,2,row(3,4)), row(1,2,4));
select row(1,2,row(3,4)) IN (row(3,2,row(3,4)), row(1,2,row(3,NULL)));
+SELECT (1,2,3)=(0,NULL,3);
+SELECT (1,2,3)=(1,NULL,3);
+# here's something for Sanja to fix :)
+SELECT (1,2,3)=(1,NULL,0);
+
SELECT ROW(1,2,3)=ROW(1,2,3);
SELECT ROW(2,2,3)=ROW(1+1,2,3);
SELECT ROW(1,2,3)=ROW(1+1,2,3);
@@ -58,9 +63,7 @@ create table t1 (i int);
select 1 from t1 where ROW(1,1);
-- error 1239
select count(*) from t1 order by ROW(1,1);
-#TODO remove comments after parser fixing
-#-- error 1239
-#select count(*) from t1 order by i having (1,1);
-#-- error 1239
-#select 1 from t1 limit (1,1), (1,1);
+-- error 1239
+select count(*) from t1 having (1,1) order by i;
drop table t1;
+
diff --git a/sql/item.h b/sql/item.h
index 25cc2601281..3852a63e722 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -580,12 +580,12 @@ public:
#include "spatial.h"
#include "item_sum.h"
#include "item_func.h"
+#include "item_row.h"
#include "item_cmpfunc.h"
#include "item_strfunc.h"
#include "item_timefunc.h"
#include "item_uniq.h"
#include "item_subselect.h"
-#include "item_row.h"
class Item_copy_string :public Item
{
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 1c579708503..06b7dc451dc 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -392,51 +392,44 @@ longlong Item_func_strcmp::val_int()
return !value ? 0 : (value < 0 ? (longlong) -1 : (longlong) 1);
}
-
void Item_func_interval::fix_length_and_dec()
{
- bool nums=1;
- uint i;
- for (i=0 ; i < arg_count ; i++)
+ if (row->cols() > 8)
{
- if (!args[i])
- return; // End of memory
- if (args[i]->type() != Item::INT_ITEM &&
- args[i]->type() != Item::REAL_ITEM)
+ bool consts=1;
+
+ for (uint i=1 ; consts && i < row->cols() ; i++)
{
- nums=0;
- break;
+ consts&= row->el(i)->const_item();
}
- }
- if (nums && arg_count >= 8)
- {
- if ((intervals=(double*) sql_alloc(sizeof(double)*arg_count)))
+
+ if (consts &&
+ (intervals=(double*) sql_alloc(sizeof(double)*(row->cols()-1))))
{
- for (i=0 ; i < arg_count ; i++)
- intervals[i]=args[i]->val();
+ for (uint i=1 ; i < row->cols(); i++)
+ intervals[i-1]=row->el(i)->val();
}
}
maybe_null= 0;
max_length= 2;
- used_tables_cache|=item->used_tables();
}
/*
return -1 if null value,
0 if lower than lowest
- 1 - arg_count if between args[n] and args[n+1]
- arg_count+1 if higher than biggest argument
+ 1 - arg_count-1 if between args[n] and args[n+1]
+ arg_count if higher than biggest argument
*/
longlong Item_func_interval::val_int()
{
- double value=item->val();
- if (item->null_value)
- return -1; // -1 if null /* purecov: inspected */
+ double value=row->el(0)->val();
+ if (row->el(0)->null_value)
+ return -1; // -1 if null
if (intervals)
{ // Use binary search to find interval
uint start,end;
- start=0; end=arg_count-1;
+ start=1; end=row->cols()-2;
while (start != end)
{
uint mid=(start+end+1)/2;
@@ -447,31 +440,14 @@ longlong Item_func_interval::val_int()
}
return (value < intervals[start]) ? 0 : start+1;
}
- if (args[0]->val() > value)
- return 0;
- for (uint i=1 ; i < arg_count ; i++)
+
+ uint i;
+ for (i=1 ; i < row->cols() ; i++)
{
- if (args[i]->val() > value)
- return i;
+ if (row->el(i)->val() > value)
+ return i-1;
}
- return (longlong) arg_count;
-}
-
-
-void Item_func_interval::update_used_tables()
-{
- Item_func::update_used_tables();
- item->update_used_tables();
- used_tables_cache|=item->used_tables();
- const_item_cache&=item->const_item();
-}
-
-bool Item_func_interval::check_loop(uint id)
-{
- DBUG_ENTER("Item_func_interval::check_loop");
- if (Item_func::check_loop(id))
- DBUG_RETURN(1);
- DBUG_RETURN(item->check_loop(id));
+ return i-1;
}
void Item_func_between::fix_length_and_dec()
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 8641ab410b3..1bb85a9e233 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -267,27 +267,14 @@ public:
class Item_func_interval :public Item_int_func
{
- Item *item;
+ Item_row *row;
double *intervals;
public:
- Item_func_interval(Item *a,List<Item> &list)
- :Item_int_func(list),item(a),intervals(0) {}
+ Item_func_interval(Item_row *a)
+ :Item_int_func(a),row(a),intervals(0) { allowed_arg_cols= a->cols(); }
longlong val_int();
- bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref)
- {
- return (item->fix_fields(thd, tlist, &item) || item->check_cols(1) ||
- Item_func::fix_fields(thd, tlist, ref));
- }
void fix_length_and_dec();
- ~Item_func_interval() { delete item; }
const char *func_name() const { return "interval"; }
- void update_used_tables();
- bool check_loop(uint id);
- void set_outer_resolving()
- {
- item->set_outer_resolving();
- Item_func::set_outer_resolving();
- }
};
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index d603748c443..78c8889c8ee 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -587,7 +587,7 @@ 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 expr_or_default set_expr_or_default
+ using_list expr_or_default set_expr_or_default interval_expr
param_marker singlerow_subselect singlerow_subselect_init
exists_subselect exists_subselect_init
@@ -1928,10 +1928,10 @@ expr_expr:
| expr '^' expr { $$= new Item_func_bit_xor($1,$3); }
| expr '&' expr { $$= new Item_func_bit_and($1,$3); }
| expr '%' expr { $$= new Item_func_mod($1,$3); }
- | expr '+' INTERVAL_SYM expr interval
- { $$= new Item_date_add_interval($1,$4,$5,0); }
- | expr '-' INTERVAL_SYM expr interval
- { $$= new Item_date_add_interval($1,$4,$5,1); }
+ | expr '+' interval_expr interval
+ { $$= new Item_date_add_interval($1,$3,$4,0); }
+ | expr '-' interval_expr interval
+ { $$= new Item_date_add_interval($1,$3,$4,1); }
| expr COLLATE_SYM collation_name
{ $$= new Item_func_set_collation($1,$3); };
@@ -1975,10 +1975,10 @@ no_in_expr:
| no_in_expr '&' expr { $$= new Item_func_bit_and($1,$3); }
| no_in_expr '%' expr { $$= new Item_func_mod($1,$3); }
| no_in_expr MOD_SYM expr { $$= new Item_func_mod($1,$3); }
- | no_in_expr '+' INTERVAL_SYM expr interval
- { $$= new Item_date_add_interval($1,$4,$5,0); }
- | no_in_expr '-' INTERVAL_SYM expr interval
- { $$= new Item_date_add_interval($1,$4,$5,1); }
+ | no_in_expr '+' interval_expr interval
+ { $$= new Item_date_add_interval($1,$3,$4,0); }
+ | no_in_expr '-' interval_expr interval
+ { $$= new Item_date_add_interval($1,$3,$4,1); }
| simple_expr;
/* expressions that begin with 'expr' that does NOT follow AND */
@@ -2030,12 +2030,16 @@ no_and_expr:
| no_and_expr '&' expr { $$= new Item_func_bit_and($1,$3); }
| no_and_expr '%' expr { $$= new Item_func_mod($1,$3); }
| no_and_expr MOD_SYM expr { $$= new Item_func_mod($1,$3); }
- | no_and_expr '+' INTERVAL_SYM expr interval
- { $$= new Item_date_add_interval($1,$4,$5,0); }
- | no_and_expr '-' INTERVAL_SYM expr interval
- { $$= new Item_date_add_interval($1,$4,$5,1); }
+ | no_and_expr '+' interval_expr interval
+ { $$= new Item_date_add_interval($1,$3,$4,0); }
+ | no_and_expr '-' interval_expr interval
+ { $$= new Item_date_add_interval($1,$3,$4,1); }
| simple_expr;
+interval_expr:
+ INTERVAL_SYM expr { $$=$2 }
+ ;
+
simple_expr:
simple_ident
| literal
@@ -2061,8 +2065,11 @@ simple_expr:
| NOT expr %prec NEG { $$= new Item_func_not($2); }
| '!' expr %prec NEG { $$= new Item_func_not($2); }
| '(' expr ')' { $$= $2; }
- /* Note: In SQL-99 "ROW" is optional, but not having it mandatory
- causes conflicts with the INTERVAL syntax. */
+ | '(' expr ',' expr_list ')'
+ {
+ $4->push_front($2);
+ $$= new Item_row(*$4);
+ }
| ROW_SYM '(' expr ',' expr_list ')'
{
$5->push_front($3);
@@ -2118,10 +2125,10 @@ simple_expr:
$$= new Item_func_curtime($3);
Lex->safe_to_cache_query=0;
}
- | DATE_ADD_INTERVAL '(' expr ',' INTERVAL_SYM expr interval ')'
- { $$= new Item_date_add_interval($3,$6,$7,0); }
- | DATE_SUB_INTERVAL '(' expr ',' INTERVAL_SYM expr interval ')'
- { $$= new Item_date_add_interval($3,$6,$7,1); }
+ | DATE_ADD_INTERVAL '(' expr ',' interval_expr interval ')'
+ { $$= new Item_date_add_interval($3,$5,$6,0); }
+ | DATE_SUB_INTERVAL '(' expr ',' interval_expr interval ')'
+ { $$= new Item_date_add_interval($3,$5,$6,1); }
| DATABASE '(' ')'
{
$$= new Item_func_database();
@@ -2181,14 +2188,21 @@ simple_expr:
{ $$= new Item_func_if($3,$5,$7); }
| INSERT '(' expr ',' expr ',' expr ',' expr ')'
{ $$= new Item_func_insert($3,$5,$7,$9); }
- | INTERVAL_SYM expr interval '+' expr
+ | interval_expr interval '+' expr
/* we cannot put interval before - */
- { $$= new Item_date_add_interval($5,$2,$3,0); }
- | INTERVAL_SYM '(' expr ',' expr_list ')'
- { $$= new Item_func_interval($3,* $5); }
+ { $$= new Item_date_add_interval($4,$1,$2,0); }
+ | interval_expr
+ {
+ if ($1->type() != Item::ROW_ITEM)
+ {
+ send_error(Lex->thd, ER_SYNTAX_ERROR);
+ YYABORT;
+ }
+ $$= new Item_func_interval((Item_row *)$1);
+ }
| LAST_INSERT_ID '(' ')'
{
- $$= get_system_var(OPT_SESSION, "last_insert_id", 14,
+ $$= get_system_var(OPT_SESSION, "last_insert_id", 14,
"last_insert_id()");
}
| LAST_INSERT_ID '(' expr ')'
@@ -2243,10 +2257,10 @@ simple_expr:
| MPOLYFROMTEXT '(' expr ',' expr ')'
{ $$= new Item_func_geometry_from_text($3); }
| MULTIPOINT '(' expr_list ')'
- { $$= new Item_func_spatial_collection(* $3,
+ { $$= new Item_func_spatial_collection(* $3,
Geometry::wkbMultiPoint, Geometry::wkbPoint); }
| MULTIPOLYGON '(' expr_list ')'
- { $$= new Item_func_spatial_collection(* $3,
+ { $$= new Item_func_spatial_collection(* $3,
Geometry::wkbMultiPolygon, Geometry::wkbPolygon ); }
| NOW_SYM optional_braces
{ $$= new Item_func_now(); Lex->safe_to_cache_query=0;}
@@ -2265,7 +2279,7 @@ simple_expr:
| POLYFROMTEXT '(' expr ',' expr ')'
{ $$= new Item_func_geometry_from_text($3); }
| POLYGON '(' expr_list ')'
- { $$= new Item_func_spatial_collection(* $3,
+ { $$= new Item_func_spatial_collection(* $3,
Geometry::wkbPolygon, Geometry::wkbLineString); }
| POSITION_SYM '(' no_in_expr IN_SYM expr ')'
{ $$ = new Item_func_locate($5,$3); }
@@ -2425,7 +2439,7 @@ in_sum_expr:
};
cast_type:
- BINARY { $$=ITEM_CAST_BINARY; }
+ BINARY { $$=ITEM_CAST_BINARY; }
| CHAR_SYM { $$=ITEM_CAST_CHAR; }
| SIGNED_SYM { $$=ITEM_CAST_SIGNED_INT; }
| SIGNED_SYM INT_SYM { $$=ITEM_CAST_SIGNED_INT; }
@@ -4647,7 +4661,7 @@ subselect_start:
'(' SELECT_SYM
{
LEX *lex=Lex;
- if (((int)lex->sql_command >= (int)SQLCOM_HA_OPEN &&
+ if (((int)lex->sql_command >= (int)SQLCOM_HA_OPEN &&
lex->sql_command <= (int)SQLCOM_HA_READ) || lex->sql_command == (int)SQLCOM_KILL) {
send_error(lex->thd, ER_SYNTAX_ERROR);
YYABORT;