summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <gkodinov/kgeorge@rakia.gmz>2006-10-31 16:15:35 +0200
committerunknown <gkodinov/kgeorge@rakia.gmz>2006-10-31 16:15:35 +0200
commit704d5d6083c4d5f069ceec58e2ce16b3636c512d (patch)
treedc2e97faddf5841099f97fa25f4d91997aa28197 /sql
parent24e4fed73d70fa76f5e8febb4b398d6482a256e2 (diff)
parentbf3ff2eaf422dcdf27113912a768d927e540c62e (diff)
downloadmariadb-git-704d5d6083c4d5f069ceec58e2ce16b3636c512d.tar.gz
Merge gkodinov@bk-internal.mysql.com:/home/bk/mysql-5.0-opt
into rakia.gmz:/home/kgeorge/mysql/autopush/B21809-5.0-opt sql/item.cc: Auto merged sql/item_func.cc: Auto merged sql/item_func.h: Auto merged sql/sql_lex.cc: Auto merged sql/sql_lex.h: Auto merged
Diffstat (limited to 'sql')
-rw-r--r--sql/item.cc26
-rw-r--r--sql/item_func.cc14
-rw-r--r--sql/item_func.h1
-rw-r--r--sql/sql_lex.cc2
-rw-r--r--sql/sql_lex.h2
-rw-r--r--sql/sql_yacc.yy41
6 files changed, 73 insertions, 13 deletions
diff --git a/sql/item.cc b/sql/item.cc
index d56ca95093b..d0777f8f2a2 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -1148,6 +1148,28 @@ void Item_name_const::print(String *str)
/*
+ need a special class to adjust printing : references to aggregate functions
+ must not be printed as refs because the aggregate functions that are added to
+ the front of select list are not printed as well.
+*/
+class Item_aggregate_ref : public Item_ref
+{
+public:
+ Item_aggregate_ref(Name_resolution_context *context_arg, Item **item,
+ const char *table_name_arg, const char *field_name_arg)
+ :Item_ref(context_arg, item, table_name_arg, field_name_arg) {}
+
+ void print (String *str)
+ {
+ if (ref)
+ (*ref)->print(str);
+ else
+ Item_ident::print(str);
+ }
+};
+
+
+/*
Move SUM items out from item tree and replace with reference
SYNOPSIS
@@ -1200,8 +1222,8 @@ void Item::split_sum_func2(THD *thd, Item **ref_pointer_array,
Item *new_item, *real_itm= real_item();
ref_pointer_array[el]= real_itm;
- if (!(new_item= new Item_ref(&thd->lex->current_select->context,
- ref_pointer_array + el, 0, name)))
+ if (!(new_item= new Item_aggregate_ref(&thd->lex->current_select->context,
+ ref_pointer_array + el, 0, name)))
return; // fatal_error is set
fields.push_front(real_itm);
thd->change_item_tree(ref, new_item);
diff --git a/sql/item_func.cc b/sql/item_func.cc
index a294bbd7a71..e9f75a507a4 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -2869,6 +2869,20 @@ void Item_udf_func::cleanup()
}
+void Item_udf_func::print(String *str)
+{
+ str->append(func_name());
+ str->append('(');
+ for (uint i=0 ; i < arg_count ; i++)
+ {
+ if (i != 0)
+ str->append(',');
+ args[i]->print_item_w_name(str);
+ }
+ str->append(')');
+}
+
+
double Item_func_udf_float::val_real()
{
DBUG_ASSERT(fixed == 1);
diff --git a/sql/item_func.h b/sql/item_func.h
index 31adc033034..99f7d16855e 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -952,6 +952,7 @@ public:
Item_result result_type () const { return udf.result_type(); }
table_map not_null_tables() const { return 0; }
bool is_expensive() { return 1; }
+ void print(String *str);
};
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index af81960f9ef..f9ff4bca06b 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -163,6 +163,7 @@ void lex_start(THD *thd, uchar *buf,uint length)
lex->select_lex.ftfunc_list= &lex->select_lex.ftfunc_list_alloc;
lex->select_lex.group_list.empty();
lex->select_lex.order_list.empty();
+ lex->select_lex.udf_list.empty();
lex->current_select= &lex->select_lex;
lex->yacc_yyss=lex->yacc_yyvs=0;
lex->ignore_space=test(thd->variables.sql_mode & MODE_IGNORE_SPACE);
@@ -1166,6 +1167,7 @@ void st_select_lex::init_select()
braces= 0;
when_list.empty();
expr_list.empty();
+ udf_list.empty();
interval_list.empty();
use_index.empty();
ftfunc_list_alloc.empty();
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index a3173b73d6d..b23ccb4f3fc 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -581,6 +581,8 @@ public:
/* exclude this select from check of unique_table() */
bool exclude_from_table_unique_test;
+ List<udf_func> udf_list; /* udf function calls stack */
+
void init_query();
void init_select();
st_select_lex_unit* master_unit();
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index cb105d05332..e5c11f6d437 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -650,11 +650,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token UNIX_TIMESTAMP
%token UNKNOWN_SYM
%token UNLOCK_SYM
-%token UNLOCK_SYM
%token UNSIGNED
%token UNTIL_SYM
-%token UNTIL_SYM
-%token UPDATE_SYM
%token UPDATE_SYM
%token UPGRADE_SYM
%token USAGE
@@ -764,7 +761,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%type <item_list>
expr_list udf_expr_list udf_expr_list2 when_list
- ident_list ident_list_arg
+ ident_list ident_list_arg opt_expr_list
%type <var_type>
option_type opt_var_type opt_var_ident_type
@@ -4724,7 +4721,7 @@ simple_expr:
{ $$= new Item_func_trim($5,$3); }
| TRUNCATE_SYM '(' expr ',' expr ')'
{ $$= new Item_func_round($3,$5,1); }
- | ident '.' ident '(' udf_expr_list ')'
+ | ident '.' ident '(' opt_expr_list ')'
{
LEX *lex= Lex;
sp_name *name= new sp_name($1, $3);
@@ -4741,27 +4738,27 @@ simple_expr:
{
#ifdef HAVE_DLOPEN
udf_func *udf= 0;
+ LEX *lex= Lex;
if (using_udf_functions &&
(udf= find_udf($1.str, $1.length)) &&
udf->type == UDFTYPE_AGGREGATE)
{
- LEX *lex= Lex;
if (lex->current_select->inc_in_sum_expr())
{
yyerror(ER(ER_SYNTAX_ERROR));
YYABORT;
}
}
- $<udf>$= udf;
+ lex->current_select->udf_list.push_front(udf);
#endif
}
udf_expr_list ')'
{
#ifdef HAVE_DLOPEN
- udf_func *udf= $<udf>3;
- SELECT_LEX *sel= Select;
+ udf_func *udf;
+ LEX *lex= Lex;
- if (udf)
+ if (NULL != (udf= lex->current_select->udf_list.pop()))
{
if (udf->type == UDFTYPE_AGGREGATE)
Select->in_sum_expr--;
@@ -4988,12 +4985,29 @@ udf_expr_list3:
udf_expr:
remember_name expr remember_end select_alias
{
+ udf_func *udf= Select->udf_list.head();
+ /*
+ Use Item::name as a storage for the attribute value of user
+ defined function argument. It is safe to use Item::name
+ because the syntax will not allow having an explicit name here.
+ See WL#1017 re. udf attributes.
+ */
if ($4.str)
{
+ if (!udf)
+ {
+ /*
+ Disallow using AS to specify explicit names for the arguments
+ of stored routine calls
+ */
+ yyerror(ER(ER_SYNTAX_ERROR));
+ YYABORT;
+ }
+
$2->is_autogenerated_name= FALSE;
$2->set_name($4.str, $4.length, system_charset_info);
}
- else
+ else if (udf)
$2->set_name($1, (uint) ($3 - $1), YYTHD->charset());
$$= $2;
}
@@ -5114,6 +5128,11 @@ cast_type:
| DECIMAL_SYM float_options { $$=ITEM_CAST_DECIMAL; Lex->charset= NULL; }
;
+opt_expr_list:
+ /* empty */ { $$= NULL; }
+ | expr_list { $$= $1;}
+ ;
+
expr_list:
{ Select->expr_list.push_front(new List<Item>); }
expr_list2