summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authormsvensson@neptunus.(none) <>2006-12-04 19:11:55 +0100
committermsvensson@neptunus.(none) <>2006-12-04 19:11:55 +0100
commit971c783f7dd3a136693722f20a815b7171bbbcd8 (patch)
treeac382a3e694ccbe7ed5a481331e35e4f055fdcae /sql
parent6072b7a4c4b786604b4584058c6c62a339b6d3ba (diff)
parentb70d2b9341ae804fbd5147500a4d29bd86e2a5d6 (diff)
downloadmariadb-git-971c783f7dd3a136693722f20a815b7171bbbcd8.tar.gz
Merge neptunus.(none):/home/msvensson/mysql/mysql-5.1
into neptunus.(none):/home/msvensson/mysql/mysql-5.1-maint
Diffstat (limited to 'sql')
-rw-r--r--sql/field_conv.cc24
-rw-r--r--sql/ha_ndbcluster.cc3
-rw-r--r--sql/handler.cc4
-rw-r--r--sql/item.cc1
-rw-r--r--sql/item_create.cc278
-rw-r--r--sql/item_func.cc78
-rw-r--r--sql/item_func.h8
-rw-r--r--sql/item_timefunc.cc18
-rw-r--r--sql/mysql_priv.h1
-rw-r--r--sql/mysqld.cc36
-rw-r--r--sql/share/errmsg.txt2
-rw-r--r--sql/sp.cc9
-rw-r--r--sql/sql_base.cc7
-rw-r--r--sql/sql_handler.cc38
-rw-r--r--sql/sql_lex.cc2
-rw-r--r--sql/sql_lex.h2
-rw-r--r--sql/sql_parse.cc151
-rw-r--r--sql/sql_table.cc122
-rw-r--r--sql/sql_yacc.yy19
-rw-r--r--sql/udf_example.c31
-rw-r--r--sql/udf_example.def2
21 files changed, 581 insertions, 255 deletions
diff --git a/sql/field_conv.cc b/sql/field_conv.cc
index 01b5306f5a4..5fde5ecb2e8 100644
--- a/sql/field_conv.cc
+++ b/sql/field_conv.cc
@@ -308,6 +308,21 @@ static void do_field_string(Copy_field *copy)
}
+static void do_field_varbinary_pre50(Copy_field *copy)
+{
+ char buff[MAX_FIELD_WIDTH];
+ copy->tmp.set_quick(buff,sizeof(buff),copy->tmp.charset());
+ copy->from_field->val_str(&copy->tmp);
+
+ /* Use the same function as in 4.1 to trim trailing spaces */
+ uint length= my_lengthsp_8bit(&my_charset_bin, copy->tmp.c_ptr_quick(),
+ copy->from_field->field_length);
+
+ copy->to_field->store(copy->tmp.c_ptr_quick(), length,
+ copy->tmp.charset());
+}
+
+
static void do_field_int(Copy_field *copy)
{
longlong value= copy->from_field->val_int();
@@ -570,6 +585,15 @@ void (*Copy_field::get_copy_func(Field *to,Field *from))(Copy_field*)
if (from->result_type() == STRING_RESULT)
{
/*
+ Detect copy from pre 5.0 varbinary to varbinary as of 5.0 and
+ use special copy function that removes trailing spaces and thus
+ repairs data.
+ */
+ if (from->type() == MYSQL_TYPE_VAR_STRING && !from->has_charset() &&
+ to->type() == MYSQL_TYPE_VARCHAR && !to->has_charset())
+ return do_field_varbinary_pre50;
+
+ /*
If we are copying date or datetime's we have to check the dates
if we don't allow 'all' dates.
*/
diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc
index fa69c113a69..0362b8bf215 100644
--- a/sql/ha_ndbcluster.cc
+++ b/sql/ha_ndbcluster.cc
@@ -7325,6 +7325,8 @@ static void print_ndbcluster_open_tables()
DBUG_UNLOCK_FILE;
}
+#endif
+
#define dbug_print_open_tables() \
DBUG_EXECUTE("info", \
@@ -7336,7 +7338,6 @@ static void print_ndbcluster_open_tables()
print_share((t), (s));); \
DBUG_UNLOCK_FILE;
-#endif
#ifdef HAVE_NDB_BINLOG
/*
diff --git a/sql/handler.cc b/sql/handler.cc
index b134814db1e..ce9dc342713 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -2304,6 +2304,10 @@ int handler::check_old_types()
{
return HA_ADMIN_NEEDS_ALTER;
}
+ if ((*field)->type() == MYSQL_TYPE_VAR_STRING)
+ {
+ return HA_ADMIN_NEEDS_ALTER;
+ }
}
}
return 0;
diff --git a/sql/item.cc b/sql/item.cc
index b310c81af5c..e2ab28dd452 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -5574,6 +5574,7 @@ int Item_default_value::save_in_field(Field *field_arg, bool no_conversions)
ER(ER_NO_DEFAULT_FOR_FIELD),
field_arg->field_name);
}
+ field_arg->set_default();
return 1;
}
field_arg->set_default();
diff --git a/sql/item_create.cc b/sql/item_create.cc
index da8954910c8..80b5e946ae7 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -28,6 +28,37 @@
*/
/**
+ Adapter for native functions with a variable number of arguments.
+ The main use of this class is to discard the following calls:
+ <code>foo(expr1 AS name1, expr2 AS name2, ...)</code>
+ which are syntactically correct (the syntax can refer to a UDF),
+ but semantically invalid for native functions.
+*/
+
+class Create_native_func : public Create_func
+{
+public:
+ virtual Item* create(THD *thd, LEX_STRING name, List<Item> *item_list);
+
+ /**
+ Builder method, with no arguments.
+ @param thd The current thread
+ @param name The native function name
+ @param item_list The function parameters, none of which are named
+ @return An item representing the function call
+ */
+ virtual Item* create_native(THD *thd, LEX_STRING name,
+ List<Item> *item_list) = 0;
+
+protected:
+ /** Constructor. */
+ Create_native_func() {}
+ /** Destructor. */
+ virtual ~Create_native_func() {}
+};
+
+
+/**
Adapter for functions that takes exactly zero arguments.
*/
@@ -302,10 +333,10 @@ protected:
};
-class Create_func_atan : public Create_func
+class Create_func_atan : public Create_native_func
{
public:
- virtual Item* create(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item* create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
static Create_func_atan s_singleton;
@@ -434,10 +465,10 @@ protected:
};
-class Create_func_concat : public Create_func
+class Create_func_concat : public Create_native_func
{
public:
- virtual Item* create(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item* create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
static Create_func_concat s_singleton;
@@ -447,10 +478,10 @@ protected:
};
-class Create_func_concat_ws : public Create_func
+class Create_func_concat_ws : public Create_native_func
{
public:
- virtual Item* create(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item* create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
static Create_func_concat_ws s_singleton;
@@ -672,10 +703,10 @@ protected:
};
-class Create_func_des_decrypt : public Create_func
+class Create_func_des_decrypt : public Create_native_func
{
public:
- virtual Item* create(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item* create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
static Create_func_des_decrypt s_singleton;
@@ -685,10 +716,10 @@ protected:
};
-class Create_func_des_encrypt : public Create_func
+class Create_func_des_encrypt : public Create_native_func
{
public:
- virtual Item* create(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item* create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
static Create_func_des_encrypt s_singleton;
@@ -728,10 +759,10 @@ protected:
#endif
-class Create_func_elt : public Create_func
+class Create_func_elt : public Create_native_func
{
public:
- virtual Item* create(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item* create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
static Create_func_elt s_singleton;
@@ -754,10 +785,10 @@ protected:
};
-class Create_func_encrypt : public Create_func
+class Create_func_encrypt : public Create_native_func
{
public:
- virtual Item* create(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item* create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
static Create_func_encrypt s_singleton;
@@ -825,10 +856,10 @@ protected:
};
-class Create_func_export_set : public Create_func
+class Create_func_export_set : public Create_native_func
{
public:
- virtual Item* create(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item* create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
static Create_func_export_set s_singleton;
@@ -853,10 +884,10 @@ protected:
#endif
-class Create_func_field : public Create_func
+class Create_func_field : public Create_native_func
{
public:
- virtual Item* create(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item* create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
static Create_func_field s_singleton;
@@ -931,10 +962,10 @@ protected:
};
-class Create_func_from_unixtime : public Create_func
+class Create_func_from_unixtime : public Create_native_func
{
public:
- virtual Item* create(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item* create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
static Create_func_from_unixtime s_singleton;
@@ -945,10 +976,10 @@ protected:
#ifdef HAVE_SPATIAL
-class Create_func_geometry_from_text : public Create_func
+class Create_func_geometry_from_text : public Create_native_func
{
public:
- virtual Item* create(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item* create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
static Create_func_geometry_from_text s_singleton;
@@ -960,10 +991,10 @@ protected:
#ifdef HAVE_SPATIAL
-class Create_func_geometry_from_wkb : public Create_func
+class Create_func_geometry_from_wkb : public Create_native_func
{
public:
- virtual Item* create(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item* create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
static Create_func_geometry_from_wkb s_singleton;
@@ -1032,10 +1063,10 @@ protected:
#endif
-class Create_func_greatest : public Create_func
+class Create_func_greatest : public Create_native_func
{
public:
- virtual Item* create(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item* create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
static Create_func_greatest s_singleton;
@@ -1237,10 +1268,10 @@ protected:
};
-class Create_func_last_insert_id : public Create_func
+class Create_func_last_insert_id : public Create_native_func
{
public:
- virtual Item* create(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item* create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
static Create_func_last_insert_id s_singleton;
@@ -1263,10 +1294,10 @@ protected:
};
-class Create_func_least : public Create_func
+class Create_func_least : public Create_native_func
{
public:
- virtual Item* create(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item* create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
static Create_func_least s_singleton;
@@ -1315,10 +1346,10 @@ protected:
};
-class Create_func_locate : public Create_func
+class Create_func_locate : public Create_native_func
{
public:
- virtual Item* create(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item* create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
static Create_func_locate s_singleton;
@@ -1328,10 +1359,10 @@ protected:
};
-class Create_func_log : public Create_func
+class Create_func_log : public Create_native_func
{
public:
- virtual Item* create(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item* create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
static Create_func_log s_singleton;
@@ -1419,10 +1450,10 @@ protected:
};
-class Create_func_make_set : public Create_func
+class Create_func_make_set : public Create_native_func
{
public:
- virtual Item* create(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item* create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
static Create_func_make_set s_singleton;
@@ -1432,10 +1463,10 @@ protected:
};
-class Create_func_master_pos_wait : public Create_func
+class Create_func_master_pos_wait : public Create_native_func
{
public:
- virtual Item* create(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item* create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
static Create_func_master_pos_wait s_singleton;
@@ -1676,10 +1707,10 @@ protected:
};
-class Create_func_rand : public Create_func
+class Create_func_rand : public Create_native_func
{
public:
- virtual Item* create(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item* create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
static Create_func_rand s_singleton;
@@ -1715,10 +1746,10 @@ protected:
};
-class Create_func_round : public Create_func
+class Create_func_round : public Create_native_func
{
public:
- virtual Item* create(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item* create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
static Create_func_round s_singleton;
@@ -2085,10 +2116,10 @@ protected:
};
-class Create_func_unix_timestamp : public Create_func
+class Create_func_unix_timestamp : public Create_native_func
{
public:
- virtual Item* create(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item* create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
static Create_func_unix_timestamp s_singleton;
@@ -2221,10 +2252,10 @@ protected:
#endif
-class Create_func_year_week : public Create_func
+class Create_func_year_week : public Create_native_func
{
public:
- virtual Item* create(THD *thd, LEX_STRING name, List<Item> *item_list);
+ virtual Item* create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
static Create_func_year_week s_singleton;
@@ -2240,6 +2271,29 @@ protected:
=============================================================================
*/
+/**
+ Checks if there are named parameters in a parameter list.
+ The syntax to name parameters in a function call is as follow:
+ <code>foo(expr AS named, expr named, expr AS "named", expr "named")</code>
+ @param params The parameter list, can be null
+ @return true if one or more parameter is named
+*/
+static bool has_named_parameters(List<Item> *params)
+{
+ if (params)
+ {
+ Item *param;
+ List_iterator<Item> it(*params);
+ while ((param= it++))
+ {
+ if (! param->is_autogenerated_name)
+ return true;
+ }
+ }
+
+ return false;
+}
+
#ifndef HAVE_SPATIAL
Create_func_no_geom Create_func_no_geom::s_singleton;
@@ -2387,11 +2441,27 @@ Create_sp_func::create(THD *thd, LEX_STRING db, LEX_STRING name,
int arg_count= 0;
Item *func= NULL;
LEX *lex= thd->lex;
- sp_name *qname= new (thd->mem_root) sp_name(db, name);
+ sp_name *qname;
+
+ if (has_named_parameters(item_list))
+ {
+ /*
+ The syntax "db.foo(expr AS p1, expr AS p2, ...) is invalid,
+ and has been rejected during syntactic parsing already,
+ because a stored function call may not have named parameters.
+
+ The syntax "foo(expr AS p1, expr AS p2, ...)" is correct,
+ because it can refer to a User Defined Function call.
+ For a Stored Function however, this has no semantic.
+ */
+ my_error(ER_WRONG_PARAMETERS_TO_STORED_FCT, MYF(0), name.str);
+ return NULL;
+ }
if (item_list != NULL)
arg_count= item_list->elements;
+ qname= new (thd->mem_root) sp_name(db, name);
qname->init_qname(thd);
sp_add_used_routine(lex, thd, qname, TYPE_ENUM_FUNCTION);
@@ -2407,6 +2477,19 @@ Create_sp_func::create(THD *thd, LEX_STRING db, LEX_STRING name,
Item*
+Create_native_func::create(THD *thd, LEX_STRING name, List<Item> *item_list)
+{
+ if (has_named_parameters(item_list))
+ {
+ my_error(ER_WRONG_PARAMETERS_TO_NATIVE_FCT, MYF(0), name.str);
+ return NULL;
+ }
+
+ return create_native(thd, name, item_list);
+}
+
+
+Item*
Create_func_arg0::create(THD *thd, LEX_STRING name, List<Item> *item_list)
{
int arg_count= 0;
@@ -2439,6 +2522,13 @@ Create_func_arg1::create(THD *thd, LEX_STRING name, List<Item> *item_list)
}
Item *param_1= item_list->pop();
+
+ if (! param_1->is_autogenerated_name)
+ {
+ my_error(ER_WRONG_PARAMETERS_TO_NATIVE_FCT, MYF(0), name.str);
+ return NULL;
+ }
+
return create(thd, param_1);
}
@@ -2459,6 +2549,14 @@ Create_func_arg2::create(THD *thd, LEX_STRING name, List<Item> *item_list)
Item *param_1= item_list->pop();
Item *param_2= item_list->pop();
+
+ if ( (! param_1->is_autogenerated_name)
+ || (! param_2->is_autogenerated_name))
+ {
+ my_error(ER_WRONG_PARAMETERS_TO_NATIVE_FCT, MYF(0), name.str);
+ return NULL;
+ }
+
return create(thd, param_1, param_2);
}
@@ -2480,6 +2578,15 @@ Create_func_arg3::create(THD *thd, LEX_STRING name, List<Item> *item_list)
Item *param_1= item_list->pop();
Item *param_2= item_list->pop();
Item *param_3= item_list->pop();
+
+ if ( (! param_1->is_autogenerated_name)
+ || (! param_2->is_autogenerated_name)
+ || (! param_3->is_autogenerated_name))
+ {
+ my_error(ER_WRONG_PARAMETERS_TO_NATIVE_FCT, MYF(0), name.str);
+ return NULL;
+ }
+
return create(thd, param_1, param_2, param_3);
}
@@ -2574,7 +2681,8 @@ Create_func_asin::create(THD *thd, Item *arg1)
Create_func_atan Create_func_atan::s_singleton;
Item*
-Create_func_atan::create(THD *thd, LEX_STRING name, List<Item> *item_list)
+Create_func_atan::create_native(THD *thd, LEX_STRING name,
+ List<Item> *item_list)
{
Item* func= NULL;
int arg_count= 0;
@@ -2687,7 +2795,8 @@ Create_func_coercibility::create(THD *thd, Item *arg1)
Create_func_concat Create_func_concat::s_singleton;
Item*
-Create_func_concat::create(THD *thd, LEX_STRING name, List<Item> *item_list)
+Create_func_concat::create_native(THD *thd, LEX_STRING name,
+ List<Item> *item_list)
{
int arg_count= 0;
@@ -2707,7 +2816,8 @@ Create_func_concat::create(THD *thd, LEX_STRING name, List<Item> *item_list)
Create_func_concat_ws Create_func_concat_ws::s_singleton;
Item*
-Create_func_concat_ws::create(THD *thd, LEX_STRING name, List<Item> *item_list)
+Create_func_concat_ws::create_native(THD *thd, LEX_STRING name,
+ List<Item> *item_list)
{
int arg_count= 0;
@@ -2897,8 +3007,8 @@ Create_func_degrees::create(THD *thd, Item *arg1)
Create_func_des_decrypt Create_func_des_decrypt::s_singleton;
Item*
-Create_func_des_decrypt::create(THD *thd, LEX_STRING name,
- List<Item> *item_list)
+Create_func_des_decrypt::create_native(THD *thd, LEX_STRING name,
+ List<Item> *item_list)
{
Item *func= NULL;
int arg_count= 0;
@@ -2934,8 +3044,8 @@ Create_func_des_decrypt::create(THD *thd, LEX_STRING name,
Create_func_des_encrypt Create_func_des_encrypt::s_singleton;
Item*
-Create_func_des_encrypt::create(THD *thd, LEX_STRING name,
- List<Item> *item_list)
+Create_func_des_encrypt::create_native(THD *thd, LEX_STRING name,
+ List<Item> *item_list)
{
Item *func= NULL;
int arg_count= 0;
@@ -2994,7 +3104,8 @@ Create_func_disjoint::create(THD *thd, Item *arg1, Item *arg2)
Create_func_elt Create_func_elt::s_singleton;
Item*
-Create_func_elt::create(THD *thd, LEX_STRING name, List<Item> *item_list)
+Create_func_elt::create_native(THD *thd, LEX_STRING name,
+ List<Item> *item_list)
{
int arg_count= 0;
@@ -3023,7 +3134,8 @@ Create_func_encode::create(THD *thd, Item *arg1, Item *arg2)
Create_func_encrypt Create_func_encrypt::s_singleton;
Item*
-Create_func_encrypt::create(THD *thd, LEX_STRING name, List<Item> *item_list)
+Create_func_encrypt::create_native(THD *thd, LEX_STRING name,
+ List<Item> *item_list)
{
Item *func= NULL;
int arg_count= 0;
@@ -3104,7 +3216,8 @@ Create_func_exp::create(THD *thd, Item *arg1)
Create_func_export_set Create_func_export_set::s_singleton;
Item*
-Create_func_export_set::create(THD *thd, LEX_STRING name, List<Item> *item_list)
+Create_func_export_set::create_native(THD *thd, LEX_STRING name,
+ List<Item> *item_list)
{
Item *func= NULL;
int arg_count= 0;
@@ -3168,7 +3281,8 @@ Create_func_exteriorring::create(THD *thd, Item *arg1)
Create_func_field Create_func_field::s_singleton;
Item*
-Create_func_field::create(THD *thd, LEX_STRING name, List<Item> *item_list)
+Create_func_field::create_native(THD *thd, LEX_STRING name,
+ List<Item> *item_list)
{
int arg_count= 0;
@@ -3234,8 +3348,8 @@ Create_func_from_days::create(THD *thd, Item *arg1)
Create_func_from_unixtime Create_func_from_unixtime::s_singleton;
Item*
-Create_func_from_unixtime::create(THD *thd, LEX_STRING name,
- List<Item> *item_list)
+Create_func_from_unixtime::create_native(THD *thd, LEX_STRING name,
+ List<Item> *item_list)
{
Item *func= NULL;
int arg_count= 0;
@@ -3273,8 +3387,8 @@ Create_func_from_unixtime::create(THD *thd, LEX_STRING name,
Create_func_geometry_from_text Create_func_geometry_from_text::s_singleton;
Item*
-Create_func_geometry_from_text::create(THD *thd, LEX_STRING name,
- List<Item> *item_list)
+Create_func_geometry_from_text::create_native(THD *thd, LEX_STRING name,
+ List<Item> *item_list)
{
Item *func= NULL;
int arg_count= 0;
@@ -3313,8 +3427,8 @@ Create_func_geometry_from_text::create(THD *thd, LEX_STRING name,
Create_func_geometry_from_wkb Create_func_geometry_from_wkb::s_singleton;
Item*
-Create_func_geometry_from_wkb::create(THD *thd, LEX_STRING name,
- List<Item> *item_list)
+Create_func_geometry_from_wkb::create_native(THD *thd, LEX_STRING name,
+ List<Item> *item_list)
{
Item *func= NULL;
int arg_count= 0;
@@ -3396,7 +3510,8 @@ Create_func_glength::create(THD *thd, Item *arg1)
Create_func_greatest Create_func_greatest::s_singleton;
Item*
-Create_func_greatest::create(THD *thd, LEX_STRING name, List<Item> *item_list)
+Create_func_greatest::create_native(THD *thd, LEX_STRING name,
+ List<Item> *item_list)
{
int arg_count= 0;
@@ -3556,8 +3671,8 @@ Create_func_last_day::create(THD *thd, Item *arg1)
Create_func_last_insert_id Create_func_last_insert_id::s_singleton;
Item*
-Create_func_last_insert_id::create(THD *thd, LEX_STRING name,
- List<Item> *item_list)
+Create_func_last_insert_id::create_native(THD *thd, LEX_STRING name,
+ List<Item> *item_list)
{
Item *func= NULL;
int arg_count= 0;
@@ -3602,7 +3717,8 @@ Create_func_lcase::create(THD *thd, Item *arg1)
Create_func_least Create_func_least::s_singleton;
Item*
-Create_func_least::create(THD *thd, LEX_STRING name, List<Item> *item_list)
+Create_func_least::create_native(THD *thd, LEX_STRING name,
+ List<Item> *item_list)
{
int arg_count= 0;
@@ -3650,7 +3766,8 @@ Create_func_load_file::create(THD *thd, Item *arg1)
Create_func_locate Create_func_locate::s_singleton;
Item*
-Create_func_locate::create(THD *thd, LEX_STRING name, List<Item> *item_list)
+Create_func_locate::create_native(THD *thd, LEX_STRING name,
+ List<Item> *item_list)
{
Item *func= NULL;
int arg_count= 0;
@@ -3690,7 +3807,8 @@ Create_func_locate::create(THD *thd, LEX_STRING name, List<Item> *item_list)
Create_func_log Create_func_log::s_singleton;
Item*
-Create_func_log::create(THD *thd, LEX_STRING name, List<Item> *item_list)
+Create_func_log::create_native(THD *thd, LEX_STRING name,
+ List<Item> *item_list)
{
Item *func= NULL;
int arg_count= 0;
@@ -3780,7 +3898,8 @@ Create_func_maketime::create(THD *thd, Item *arg1, Item *arg2, Item *arg3)
Create_func_make_set Create_func_make_set::s_singleton;
Item*
-Create_func_make_set::create(THD *thd, LEX_STRING name, List<Item> *item_list)
+Create_func_make_set::create_native(THD *thd, LEX_STRING name,
+ List<Item> *item_list)
{
int arg_count= 0;
@@ -3801,8 +3920,8 @@ Create_func_make_set::create(THD *thd, LEX_STRING name, List<Item> *item_list)
Create_func_master_pos_wait Create_func_master_pos_wait::s_singleton;
Item*
-Create_func_master_pos_wait::create(THD *thd, LEX_STRING name,
- List<Item> *item_list)
+Create_func_master_pos_wait::create_native(THD *thd, LEX_STRING name,
+ List<Item> *item_list)
{
Item *func= NULL;
int arg_count= 0;
@@ -4010,7 +4129,8 @@ Create_func_radians::create(THD *thd, Item *arg1)
Create_func_rand Create_func_rand::s_singleton;
Item*
-Create_func_rand::create(THD *thd, LEX_STRING name, List<Item> *item_list)
+Create_func_rand::create_native(THD *thd, LEX_STRING name,
+ List<Item> *item_list)
{
Item *func= NULL;
int arg_count= 0;
@@ -4065,7 +4185,8 @@ Create_func_reverse::create(THD *thd, Item *arg1)
Create_func_round Create_func_round::s_singleton;
Item*
-Create_func_round::create(THD *thd, LEX_STRING name, List<Item> *item_list)
+Create_func_round::create_native(THD *thd, LEX_STRING name,
+ List<Item> *item_list)
{
Item *func= NULL;
int arg_count= 0;
@@ -4374,8 +4495,8 @@ Create_func_unhex::create(THD *thd, Item *arg1)
Create_func_unix_timestamp Create_func_unix_timestamp::s_singleton;
Item*
-Create_func_unix_timestamp::create(THD *thd, LEX_STRING name,
- List<Item> *item_list)
+Create_func_unix_timestamp::create_native(THD *thd, LEX_STRING name,
+ List<Item> *item_list)
{
Item *func= NULL;
int arg_count= 0;
@@ -4506,7 +4627,8 @@ Create_func_y::create(THD *thd, Item *arg1)
Create_func_year_week Create_func_year_week::s_singleton;
Item*
-Create_func_year_week::create(THD *thd, LEX_STRING name, List<Item> *item_list)
+Create_func_year_week::create_native(THD *thd, LEX_STRING name,
+ List<Item> *item_list)
{
Item *func= NULL;
int arg_count= 0;
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 08e417d8322..0f5faf93cc3 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -1362,6 +1362,10 @@ longlong Item_func_mod::int_op()
signal_divide_by_null();
return 0;
}
+
+ if (args[0]->unsigned_flag)
+ return ((ulonglong) value) % val2;
+
return value % val2;
}
@@ -2730,39 +2734,47 @@ udf_handler::fix_fields(THD *thd, Item_result_field *func,
char *to=num_buffer;
for (uint i=0; i < arg_count; i++)
{
- f_args.args[i]=0;
+ /*
+ For a constant argument i, args->args[i] points to the argument value.
+ For non-constant, args->args[i] is NULL.
+ */
+ f_args.args[i]= NULL; /* Non-const unless updated below. */
+
f_args.lengths[i]= arguments[i]->max_length;
f_args.maybe_null[i]= (char) arguments[i]->maybe_null;
f_args.attributes[i]= arguments[i]->name;
f_args.attribute_lengths[i]= arguments[i]->name_length;
- switch(arguments[i]->type()) {
- case Item::STRING_ITEM: // Constant string !
+ if (arguments[i]->const_item())
{
- String *res=arguments[i]->val_str(&buffers[i]);
- if (arguments[i]->null_value)
- continue;
- f_args.args[i]= (char*) res->ptr();
- break;
- }
- case Item::INT_ITEM:
- *((longlong*) to) = arguments[i]->val_int();
- if (!arguments[i]->null_value)
- {
- f_args.args[i]=to;
- to+= ALIGN_SIZE(sizeof(longlong));
- }
- break;
- case Item::REAL_ITEM:
- *((double*) to)= arguments[i]->val_real();
- if (!arguments[i]->null_value)
- {
- f_args.args[i]=to;
- to+= ALIGN_SIZE(sizeof(double));
- }
- break;
- default: // Skip these
- break;
+ if (arguments[i]->null_value)
+ continue;
+
+ switch (arguments[i]->result_type())
+ {
+ case STRING_RESULT:
+ case DECIMAL_RESULT:
+ {
+ String *res= arguments[i]->val_str(&buffers[i]);
+ f_args.args[i]= (char*) res->ptr();
+ break;
+ }
+ case INT_RESULT:
+ *((longlong*) to)= arguments[i]->val_int();
+ f_args.args[i]= to;
+ to+= ALIGN_SIZE(sizeof(longlong));
+ break;
+ case REAL_RESULT:
+ *((double*) to)= arguments[i]->val_real();
+ f_args.args[i]= to;
+ to+= ALIGN_SIZE(sizeof(double));
+ break;
+ case ROW_RESULT:
+ default:
+ // This case should never be chosen
+ DBUG_ASSERT(0);
+ break;
+ }
}
}
thd->net.last_error[0]=0;
@@ -5025,6 +5037,18 @@ Item_func_sp::execute_impl(THD *thd, Field *return_value_fld)
goto error;
/*
+ Throw an error if a non-deterministic function is called while
+ statement-based replication (SBR) is active.
+ */
+ if (!m_sp->m_chistics->detistic && !trust_function_creators &&
+ (mysql_bin_log.is_open() &&
+ thd->variables.binlog_format == BINLOG_FORMAT_STMT))
+ {
+ my_error(ER_BINLOG_ROW_RBR_TO_SBR, MYF(0));
+ goto error;
+ }
+
+ /*
Disable the binlogging if this is not a SELECT statement. If this is a
SELECT, leave binlogging on, so execute_function() code writes the
function call into binlog.
diff --git a/sql/item_func.h b/sql/item_func.h
index 9139e30483d..9130ef0a0c4 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -1315,10 +1315,10 @@ public:
class Item_func_inet_aton : public Item_int_func
{
public:
- Item_func_inet_aton(Item *a) :Item_int_func(a) {}
- longlong val_int();
- const char *func_name() const { return "inet_aton"; }
- void fix_length_and_dec() { decimals = 0; max_length = 21; maybe_null=1;}
+ Item_func_inet_aton(Item *a) :Item_int_func(a) {}
+ longlong val_int();
+ const char *func_name() const { return "inet_aton"; }
+ void fix_length_and_dec() { decimals= 0; max_length= 21; maybe_null= 1; unsigned_flag= 1;}
bool check_partition_func_processor(byte *int_arg) {return FALSE;}
};
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index 76ab70cca96..ff688e15307 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -289,15 +289,16 @@ static bool extract_date_time(DATE_TIME_FORMAT *format,
for (; ptr != end && val != val_end; ptr++)
{
+ /* Skip pre-space between each argument */
+ while (val != val_end && my_isspace(cs, *val))
+ val++;
+
if (*ptr == '%' && ptr+1 != end)
{
int val_len;
char *tmp;
error= 0;
- /* Skip pre-space between each argument */
- while (val != val_end && my_isspace(cs, *val))
- val++;
val_len= (uint) (val_end - val);
switch (*++ptr) {
@@ -3193,7 +3194,9 @@ bool Item_func_str_to_date::get_date(TIME *ltime, uint fuzzy_date)
date_time_format.format.str= (char*) format->ptr();
date_time_format.format.length= format->length();
if (extract_date_time(&date_time_format, val->ptr(), val->length(),
- ltime, cached_timestamp_type, 0, "datetime"))
+ ltime, cached_timestamp_type, 0, "datetime") ||
+ ((fuzzy_date & TIME_NO_ZERO_DATE) &&
+ (ltime->year == 0 || ltime->month == 0 || ltime->day == 0)))
goto null_date;
if (cached_timestamp_type == MYSQL_TIMESTAMP_TIME && ltime->day)
{
@@ -3230,8 +3233,13 @@ String *Item_func_str_to_date::val_str(String *str)
bool Item_func_last_day::get_date(TIME *ltime, uint fuzzy_date)
{
- if (get_arg0_date(ltime, fuzzy_date & ~TIME_FUZZY_DATE))
+ if (get_arg0_date(ltime, fuzzy_date & ~TIME_FUZZY_DATE) ||
+ (ltime->month == 0))
+ {
+ null_value= 1;
return 1;
+ }
+ null_value= 0;
uint month_idx= ltime->month-1;
ltime->day= days_in_month[month_idx];
if ( month_idx == 1 && calc_days_in_year(ltime->year) == 366)
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index a75f204ae33..58e38362544 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -1112,6 +1112,7 @@ bool mysql_ha_read(THD *, TABLE_LIST *,enum enum_ha_read_modes,char *,
List<Item> *,enum ha_rkey_function,Item *,ha_rows,ha_rows);
int mysql_ha_flush(THD *thd, TABLE_LIST *tables, uint mode_flags,
bool is_locked);
+void mysql_ha_mark_tables_for_reopen(THD *thd, TABLE *table);
/* mysql_ha_flush mode_flags bits */
#define MYSQL_HA_CLOSE_FINAL 0x00
#define MYSQL_HA_REOPEN_ON_USAGE 0x01
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 6921fe3e6d8..ee64a247e5a 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -346,7 +346,7 @@ bool opt_error_log= IF_WIN(1,0);
bool opt_disable_networking=0, opt_skip_show_db=0;
my_bool opt_character_set_client_handshake= 1;
bool server_id_supplied = 0;
-bool opt_endinfo,using_udf_functions;
+bool opt_endinfo, using_udf_functions;
my_bool locked_in_memory;
bool opt_using_transactions, using_update_log;
bool volatile abort_loop;
@@ -2155,13 +2155,24 @@ later when used with nscd), disable LDAP in your nsswitch.conf, or use a\n\
mysqld that is not statically linked.\n");
#endif
- if (test_flags & TEST_CORE_ON_SIGNAL)
- {
- fprintf(stderr, "Writing a core file\n");
- fflush(stderr);
- write_core(sig);
- }
- exit(1);
+ if (locked_in_memory)
+ {
+ fprintf(stderr, "\n\
+The \"--memlock\" argument, which was enabled, uses system calls that are\n\
+unreliable and unstable on some operating systems and operating-system\n\
+versions (notably, some versions of Linux). This crash could be due to use\n\
+of those buggy OS calls. You should consider whether you really need the\n\
+\"--memlock\" parameter and/or consult the OS distributer about \"mlockall\"\n\
+bugs.\n");
+ }
+
+ if (test_flags & TEST_CORE_ON_SIGNAL)
+ {
+ fprintf(stderr, "Writing a core file\n");
+ fflush(stderr);
+ write_core(sig);
+ }
+ exit(1);
}
#ifndef SA_RESETHAND
@@ -2784,13 +2795,13 @@ static int init_common_variables(const char *conf_file_name, int argc,
!(log_output_options & LOG_NONE))
sql_print_warning("Although a path was specified for the "
"--log option, log tables are used. "
- "To enable logging to file use the --log-output option.");
+ "To enable logging to files use the --log-output option.");
if (opt_slow_log && opt_slow_logname && !(log_output_options & LOG_FILE)
&& !(log_output_options & LOG_NONE))
sql_print_warning("Although a path was specified for the "
"--log-slow-queries option, log tables are used. "
- "To enable logging to file use the --log-output option.");
+ "To enable logging to files use the --log-output option.");
if (!opt_logname)
opt_logname= make_default_log_name(buff, ".log");
@@ -5932,9 +5943,11 @@ The minimum value for this variable is 4096.",
"If there is more than this number of interrupted connections from a host this host will be blocked from further connections.",
(gptr*) &max_connect_errors, (gptr*) &max_connect_errors, 0, GET_ULONG,
REQUIRED_ARG, MAX_CONNECT_ERRORS, 1, ~0L, 0, 1, 0},
+ // Default max_connections of 151 is larger than Apache's default max
+ // children, to avoid "too many connections" error in a common setup
{"max_connections", OPT_MAX_CONNECTIONS,
"The number of simultaneous clients allowed.", (gptr*) &max_connections,
- (gptr*) &max_connections, 0, GET_ULONG, REQUIRED_ARG, 100, 1, 16384, 0, 1,
+ (gptr*) &max_connections, 0, GET_ULONG, REQUIRED_ARG, 151, 1, 16384, 0, 1,
0},
{"max_delayed_threads", OPT_MAX_DELAYED_THREADS,
"Don't start more than this number of threads to handle INSERT DELAYED statements. If set to zero, which means INSERT DELAYED is not used.",
@@ -6624,6 +6637,7 @@ SHOW_VAR status_vars[]= {
{"Com_create_function", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_FUNCTION]), SHOW_LONG_STATUS},
{"Com_create_index", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_INDEX]), SHOW_LONG_STATUS},
{"Com_create_table", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_TABLE]), SHOW_LONG_STATUS},
+ {"Com_create_user", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_USER]), SHOW_LONG_STATUS},
{"Com_dealloc_sql", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DEALLOCATE_PREPARE]), SHOW_LONG_STATUS},
{"Com_delete", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DELETE]), SHOW_LONG_STATUS},
{"Com_delete_multi", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DELETE_MULTI]), SHOW_LONG_STATUS},
diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt
index cfeca697692..c64f4da045e 100644
--- a/sql/share/errmsg.txt
+++ b/sql/share/errmsg.txt
@@ -6010,6 +6010,8 @@ ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT 42000
eng "Incorrect parameter count in the call to native function '%-.64s'"
ER_WRONG_PARAMETERS_TO_NATIVE_FCT 42000
eng "Incorrect parameters in the call to native function '%-.64s'"
+ER_WRONG_PARAMETERS_TO_STORED_FCT 42000
+ eng "Incorrect parameters in the call to stored function '%-.64s'"
ER_NATIVE_FCT_NAME_COLLISION
eng "This function '%-.64s' has the same name as a native function."
ER_BINLOG_PURGE_EMFILE
diff --git a/sql/sp.cc b/sql/sp.cc
index 45a177d3e7a..9e53aff742e 100644
--- a/sql/sp.cc
+++ b/sql/sp.cc
@@ -497,17 +497,10 @@ db_create_routine(THD *thd, int type, sp_head *sp)
char definer[USER_HOST_BUFF_SIZE];
char old_db_buf[NAME_LEN+1];
LEX_STRING old_db= { old_db_buf, sizeof(old_db_buf) };
- bool dbchanged;
DBUG_ENTER("db_create_routine");
DBUG_PRINT("enter", ("type: %d name: %.*s",type,sp->m_name.length,
sp->m_name.str));
- if ((ret= sp_use_new_db(thd, sp->m_db, &old_db, 0, &dbchanged)))
- {
- ret= SP_NO_DB_ERROR;
- goto done;
- }
-
if (!(table= open_proc_table_for_update(thd)))
ret= SP_OPEN_TABLE_FAILED;
else
@@ -631,8 +624,6 @@ db_create_routine(THD *thd, int type, sp_head *sp)
done:
close_thread_tables(thd);
- if (dbchanged)
- (void) mysql_change_db(thd, old_db.str, 1);
DBUG_RETURN(ret);
}
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index db6baac8681..3fd09d909a4 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -1089,6 +1089,13 @@ void close_thread_tables(THD *thd, bool lock_in_use, bool skip_derived)
DBUG_PRINT("info", ("thd->open_tables: 0x%lx", (long) thd->open_tables));
+ /*
+ End open index scans and table scans and remove references to the tables
+ from the handler tables hash. After this preparation it is safe to close
+ the tables.
+ */
+ mysql_ha_mark_tables_for_reopen(thd, thd->open_tables);
+
found_old_table= 0;
while (thd->open_tables)
found_old_table|= close_thread_table(thd, &thd->open_tables);
diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc
index c448be04ac5..5951acdcc40 100644
--- a/sql/sql_handler.cc
+++ b/sql/sql_handler.cc
@@ -757,3 +757,41 @@ static int mysql_ha_flush_table(THD *thd, TABLE **table_ptr, uint mode_flags)
DBUG_RETURN(0);
}
+
+
+/*
+ Mark tables for reopen.
+
+ SYNOPSIS
+ mysql_ha_mark_tables_for_reopen()
+ thd Thread identifier.
+ table Table list to mark for reopen.
+
+ DESCRIPTION
+ For each table found in the handler hash mark it as closed
+ (ready for reopen) and end all index/table scans.
+
+ NOTE
+ The caller must lock LOCK_open.
+*/
+
+void mysql_ha_mark_tables_for_reopen(THD *thd, TABLE *table)
+{
+ DBUG_ENTER("mysql_ha_mark_tables_for_reopen");
+
+ safe_mutex_assert_owner(&LOCK_open);
+ for (; table; table= table->next)
+ {
+ TABLE_LIST *hash_tables;
+ if ((hash_tables= (TABLE_LIST*) hash_search(&thd->handler_tables_hash,
+ (byte*) table->alias,
+ strlen(table->alias) + 1)))
+ {
+ /* Mark table as ready for reopen. */
+ hash_tables->table= NULL;
+ /* End open index/table scans. */
+ table->file->ha_index_or_rnd_end();
+ }
+ }
+ DBUG_VOID_RETURN;
+}
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 47704570720..d156973a790 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -164,7 +164,6 @@ void lex_start(THD *thd, const 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->ignore_space=test(thd->variables.sql_mode & MODE_IGNORE_SPACE);
lex->sql_command= SQLCOM_END;
lex->duplicates= DUP_ERROR;
@@ -1182,7 +1181,6 @@ 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 4af767b25db..7fd60cbfa58 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -609,8 +609,6 @@ 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_parse.cc b/sql/sql_parse.cc
index 401285c2f8b..3f06c0680e2 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -57,10 +57,6 @@
(LP)->sql_command == SQLCOM_DROP_FUNCTION ? \
"FUNCTION" : "PROCEDURE")
-#ifdef SOLARIS
-extern "C" int gethostname(char *name, int namelen);
-#endif
-
static void time_out_user_resource_limits(THD *thd, USER_CONN *uc);
#ifndef NO_EMBEDDED_ACCESS_CHECKS
static int check_for_max_user_connections(THD *thd, USER_CONN *uc);
@@ -2631,10 +2627,11 @@ mysql_execute_command(THD *thd)
if (opt_readonly &&
!(thd->security_ctx->master_access & SUPER_ACL) &&
(sql_command_flags[lex->sql_command] & CF_CHANGES_DATA) &&
- !((lex->sql_command == SQLCOM_CREATE_TABLE) &&
- (lex->create_info.options & HA_LEX_CREATE_TMP_TABLE)) &&
- ((lex->sql_command != SQLCOM_UPDATE_MULTI) &&
- some_non_temp_table_to_be_updated(thd, all_tables)))
+ !((lex->sql_command == SQLCOM_CREATE_TABLE) &&
+ (lex->create_info.options & HA_LEX_CREATE_TMP_TABLE)) &&
+ !((lex->sql_command == SQLCOM_DROP_TABLE) && lex->drop_temporary) &&
+ ((lex->sql_command != SQLCOM_UPDATE_MULTI) &&
+ some_non_temp_table_to_be_updated(thd, all_tables)))
{
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only");
DBUG_RETURN(-1);
@@ -4229,6 +4226,7 @@ end_with_restore_list:
bool write_to_binlog;
if (check_global_access(thd,RELOAD_ACL))
goto error;
+
/*
reload_acl_and_cache() will tell us if we are allowed to write to the
binlog or not.
@@ -4249,7 +4247,8 @@ end_with_restore_list:
}
}
send_ok(thd);
- }
+ }
+
break;
}
case SQLCOM_KILL:
@@ -4434,26 +4433,38 @@ end_with_restore_list:
{
uint namelen;
char *name;
- int result;
+ int result= SP_INTERNAL_ERROR;
DBUG_ASSERT(lex->sphead != 0);
DBUG_ASSERT(lex->sphead->m_db.str); /* Must be initialized in the parser */
-
- if (check_access(thd, CREATE_PROC_ACL, lex->sphead->m_db.str, 0, 0, 0,
- is_schema_db(lex->sphead->m_db.str)))
+ /*
+ Verify that the database name is allowed, optionally
+ lowercase it.
+ */
+ if (check_db_name(&lex->sphead->m_db))
{
- delete lex->sphead;
- lex->sphead= 0;
- goto error;
+ my_error(ER_WRONG_DB_NAME, MYF(0), lex->sphead->m_db.str);
+ goto create_sp_error;
}
- if (end_active_trans(thd))
+ /*
+ Check that a database directory with this name
+ exists. Design note: This won't work on virtual databases
+ like information_schema.
+ */
+ if (check_db_dir_existence(lex->sphead->m_db.str))
{
- delete lex->sphead;
- lex->sphead= 0;
- goto error;
+ my_error(ER_BAD_DB_ERROR, MYF(0), lex->sphead->m_db.str);
+ goto create_sp_error;
}
+ if (check_access(thd, CREATE_PROC_ACL, lex->sphead->m_db.str, 0, 0, 0,
+ is_schema_db(lex->sphead->m_db.str)))
+ goto create_sp_error;
+
+ if (end_active_trans(thd))
+ goto create_sp_error;
+
name= lex->sphead->name(&namelen);
#ifdef HAVE_DLOPEN
if (lex->sphead->m_type == TYPE_ENUM_FUNCTION)
@@ -4462,10 +4473,8 @@ end_with_restore_list:
if (udf)
{
- my_error(ER_UDF_EXISTS, MYF(0), name);
- delete lex->sphead;
- lex->sphead= 0;
- goto error;
+ my_error(ER_UDF_EXISTS, MYF(0), name);
+ goto create_sp_error;
}
}
#endif
@@ -4473,7 +4482,7 @@ end_with_restore_list:
/*
If the definer is not specified, this means that CREATE-statement missed
DEFINER-clause. DEFINER-clause can be missed in two cases:
-
+
- The user submitted a statement w/o the clause. This is a normal
case, we should assign CURRENT_USER as definer.
@@ -4482,7 +4491,7 @@ end_with_restore_list:
CURRENT_USER as definer here, but also we should mark this routine
as NON-SUID. This is essential for the sake of backward
compatibility.
-
+
The problem is the slave thread is running under "special" user (@),
that actually does not exist. In the older versions we do not fail
execution of a stored routine if its definer does not exist and
@@ -4507,13 +4516,9 @@ end_with_restore_list:
if (ps_arena)
thd->restore_active_arena(ps_arena, &original_arena);
+ /* Error has been already reported. */
if (res)
- {
- /* Error has been already reported. */
- delete lex->sphead;
- lex->sphead= 0;
- goto error;
- }
+ goto create_sp_error;
if (thd->slave_thread)
lex->sphead->m_chistics->suid= SP_IS_NOT_SUID;
@@ -4524,7 +4529,7 @@ end_with_restore_list:
that the current user has SUPER privilege (in order to create a stored
routine under another user one must have SUPER privilege).
*/
-
+
else if (strcmp(lex->definer->user.str, thd->security_ctx->priv_user) ||
my_strcasecmp(system_charset_info,
lex->definer->host.str,
@@ -4533,9 +4538,7 @@ end_with_restore_list:
if (check_global_access(thd, SUPER_ACL))
{
my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER");
- delete lex->sphead;
- lex->sphead= 0;
- goto error;
+ goto create_sp_error;
}
}
@@ -4555,54 +4558,51 @@ end_with_restore_list:
#endif /* NO_EMBEDDED_ACCESS_CHECKS */
res= (result= lex->sphead->create(thd));
- if (result == SP_OK)
- {
+ switch (result) {
+ case SP_OK:
#ifndef NO_EMBEDDED_ACCESS_CHECKS
/* only add privileges if really neccessary */
if (sp_automatic_privileges && !opt_noacl &&
check_routine_access(thd, DEFAULT_CREATE_PROC_ACLS,
- lex->sphead->m_db.str, name,
+ lex->sphead->m_db.str, name,
lex->sql_command == SQLCOM_CREATE_PROCEDURE, 1))
{
if (sp_grant_privileges(thd, lex->sphead->m_db.str, name,
lex->sql_command == SQLCOM_CREATE_PROCEDURE))
- push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_PROC_AUTO_GRANT_FAIL,
- ER(ER_PROC_AUTO_GRANT_FAIL));
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_PROC_AUTO_GRANT_FAIL,
+ ER(ER_PROC_AUTO_GRANT_FAIL));
close_thread_tables(thd);
}
#endif
- lex->unit.cleanup();
- delete lex->sphead;
- lex->sphead= 0;
- send_ok(thd);
- }
- else
- {
- switch (result) {
- case SP_WRITE_ROW_FAILED:
- my_error(ER_SP_ALREADY_EXISTS, MYF(0), SP_TYPE_STRING(lex), name);
- break;
- case SP_NO_DB_ERROR:
- my_error(ER_BAD_DB_ERROR, MYF(0), lex->sphead->m_db.str);
- break;
- case SP_BAD_IDENTIFIER:
- my_error(ER_TOO_LONG_IDENT, MYF(0), name);
- break;
- case SP_BODY_TOO_LONG:
- my_error(ER_TOO_LONG_BODY, MYF(0), name);
- break;
- default:
- my_error(ER_SP_STORE_FAILED, MYF(0), SP_TYPE_STRING(lex), name);
- break;
- }
- lex->unit.cleanup();
- delete lex->sphead;
- lex->sphead= 0;
- goto error;
- }
break;
- }
+ case SP_WRITE_ROW_FAILED:
+ my_error(ER_SP_ALREADY_EXISTS, MYF(0), SP_TYPE_STRING(lex), name);
+ break;
+ case SP_BAD_IDENTIFIER:
+ my_error(ER_TOO_LONG_IDENT, MYF(0), name);
+ break;
+ case SP_BODY_TOO_LONG:
+ my_error(ER_TOO_LONG_BODY, MYF(0), name);
+ break;
+ default:
+ my_error(ER_SP_STORE_FAILED, MYF(0), SP_TYPE_STRING(lex), name);
+ break;
+ } /* end switch */
+
+ /*
+ Capture all errors within this CASE and
+ clean up the environment.
+ */
+create_sp_error:
+ lex->unit.cleanup();
+ delete lex->sphead;
+ lex->sphead= 0;
+ if (result != SP_OK )
+ goto error;
+ send_ok(thd);
+ break; /* break super switch */
+ } /* end case group bracket */
case SQLCOM_CALL:
{
sp_head *sp;
@@ -4678,8 +4678,6 @@ end_with_restore_list:
select_limit= thd->variables.select_limit;
thd->variables.select_limit= HA_POS_ERROR;
- thd->row_count_func= 0;
-
/*
We never write CALL statements into binlog:
- If the mode is non-prelocked, each statement will be logged
@@ -6974,7 +6972,10 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
than it would help them)
*/
tmp_write_to_binlog= 0;
- mysql_bin_log.rotate_and_purge(RP_FORCE_ROTATE);
+ if( mysql_bin_log.is_open() )
+ {
+ mysql_bin_log.rotate_and_purge(RP_FORCE_ROTATE);
+ }
#ifdef HAVE_REPLICATION
pthread_mutex_lock(&LOCK_active_mi);
rotate_relay_log(active_mi);
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 75d7f4c9fbf..165a82e4b27 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -37,7 +37,9 @@ static char *make_unique_key_name(const char *field_name,KEY *start,KEY *end);
static int copy_data_between_tables(TABLE *from,TABLE *to,
List<create_field> &create, bool ignore,
uint order_num, ORDER *order,
- ha_rows *copied,ha_rows *deleted);
+ ha_rows *copied,ha_rows *deleted,
+ enum enum_enable_or_disable keys_onoff);
+
static bool prepare_blob_field(THD *thd, create_field *sql_field);
static bool check_engine(THD *thd, const char *table_name,
HA_CREATE_INFO *create_info);
@@ -5196,6 +5198,54 @@ static uint compare_tables(TABLE *table, List<create_field> *create_list,
/*
+ Manages enabling/disabling of indexes for ALTER TABLE
+
+ SYNOPSIS
+ alter_table_manage_keys()
+ table Target table
+ indexes_were_disabled Whether the indexes of the from table
+ were disabled
+ keys_onoff ENABLE | DISABLE | LEAVE_AS_IS
+
+ RETURN VALUES
+ FALSE OK
+ TRUE Error
+*/
+
+static
+bool alter_table_manage_keys(TABLE *table, int indexes_were_disabled,
+ enum enum_enable_or_disable keys_onoff)
+{
+ int error= 0;
+ DBUG_ENTER("alter_table_manage_keys");
+ DBUG_PRINT("enter", ("table=%p were_disabled=%d on_off=%d",
+ table, indexes_were_disabled, keys_onoff));
+
+ switch (keys_onoff) {
+ case ENABLE:
+ error= table->file->enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
+ break;
+ case LEAVE_AS_IS:
+ if (!indexes_were_disabled)
+ break;
+ /* fall-through: disabled indexes */
+ case DISABLE:
+ error= table->file->disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
+ }
+
+ if (error == HA_ERR_WRONG_COMMAND)
+ {
+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
+ ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA), table->s->table_name);
+ error= 0;
+ } else if (error)
+ table->file->print_error(error, MYF(0));
+
+ DBUG_RETURN(error);
+}
+
+
+/*
Alter table
*/
@@ -5443,13 +5493,35 @@ view_err:
if (!(alter_info->flags & ~(ALTER_RENAME | ALTER_KEYS_ONOFF)) &&
!table->s->tmp_table) // no need to touch frm
{
- error=0;
VOID(pthread_mutex_lock(&LOCK_open));
- if (new_name != table_name || new_db != db)
+
+ switch (alter_info->keys_onoff) {
+ case LEAVE_AS_IS:
+ error= 0;
+ break;
+ case ENABLE:
+ wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
+ error= table->file->enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
+ /* COND_refresh will be signaled in close_thread_tables() */
+ break;
+ case DISABLE:
+ wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
+ error=table->file->disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
+ /* COND_refresh will be signaled in close_thread_tables() */
+ break;
+ }
+ if (error == HA_ERR_WRONG_COMMAND)
+ {
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
+ ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
+ table->alias);
+ error= 0;
+ }
+
+ if (!error && (new_name != table_name || new_db != db))
{
thd->proc_info="rename";
/* Then do a 'simple' rename of the table */
- error=0;
if (!access(new_name_buff,F_OK))
{
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name);
@@ -5472,31 +5544,14 @@ view_err:
}
}
- if (!error)
- {
- switch (alter_info->keys_onoff) {
- case LEAVE_AS_IS:
- break;
- case ENABLE:
- wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
- error= table->file->enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
- /* COND_refresh will be signaled in close_thread_tables() */
- break;
- case DISABLE:
- wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
- error=table->file->disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
- /* COND_refresh will be signaled in close_thread_tables() */
- break;
- }
- }
-
if (error == HA_ERR_WRONG_COMMAND)
{
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
table->alias);
- error=0;
+ error= 0;
}
+
if (!error)
{
write_bin_log(thd, TRUE, thd->query, thd->query_length);
@@ -5509,7 +5564,7 @@ view_err:
error= -1;
}
VOID(pthread_mutex_unlock(&LOCK_open));
- table_list->table=0; // For query cache
+ table_list->table= NULL; // For query cache
query_cache_invalidate3(thd, table_list, 0);
DBUG_RETURN(error);
}
@@ -6112,7 +6167,18 @@ view_err:
new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
new_table->next_number_field=new_table->found_next_number_field;
error=copy_data_between_tables(table, new_table, create_list, ignore,
- order_num, order, &copied, &deleted);
+ order_num, order, &copied, &deleted,
+ alter_info->keys_onoff);
+ }
+ else
+ {
+ VOID(pthread_mutex_lock(&LOCK_open));
+ wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
+ table->file->ha_external_lock(thd, F_WRLCK);
+ alter_table_manage_keys(table, table->file->indexes_are_disabled(),
+ alter_info->keys_onoff);
+ table->file->ha_external_lock(thd, F_UNLCK);
+ VOID(pthread_mutex_unlock(&LOCK_open));
}
thd->count_cuted_fields= CHECK_FIELD_IGNORE;
@@ -6529,7 +6595,8 @@ copy_data_between_tables(TABLE *from,TABLE *to,
bool ignore,
uint order_num, ORDER *order,
ha_rows *copied,
- ha_rows *deleted)
+ ha_rows *deleted,
+ enum enum_enable_or_disable keys_onoff)
{
int error;
Copy_field *copy,*copy_end;
@@ -6563,6 +6630,9 @@ copy_data_between_tables(TABLE *from,TABLE *to,
if (to->file->ha_external_lock(thd, F_WRLCK))
DBUG_RETURN(-1);
+ /* We need external lock before we can disable/enable keys */
+ alter_table_manage_keys(to, from->file->indexes_are_disabled(), keys_onoff);
+
/* We can abort alter table for any table type */
thd->no_trans_update= 0;
thd->abort_on_warning= !ignore && test(thd->variables.sql_mode &
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index fcac7eb8e05..434cd0e4cd5 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -6426,7 +6426,7 @@ function_call_generic:
}
}
/* Temporary placing the result of find_udf in $3 */
- lex->current_select->udf_list.push_front(udf);
+ $<udf>$= udf;
#endif
}
udf_expr_list ')'
@@ -6454,10 +6454,10 @@ function_call_generic:
{
#ifdef HAVE_DLOPEN
/* Retrieving the result of find_udf */
- udf_func *udf;
+ udf_func *udf= $<udf>3;
LEX *lex= Lex;
- if (NULL != (udf= lex->current_select->udf_list.pop()))
+ if (udf)
{
if (udf->type == UDFTYPE_AGGREGATE)
{
@@ -6553,7 +6553,6 @@ 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
@@ -6562,20 +6561,10 @@ udf_expr:
*/
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 if (udf)
+ else
$2->set_name($1, (uint) ($3 - $1), YYTHD->charset());
$$= $2;
}
diff --git a/sql/udf_example.c b/sql/udf_example.c
index 2fa7474eb16..bbab47e253d 100644
--- a/sql/udf_example.c
+++ b/sql/udf_example.c
@@ -165,6 +165,9 @@ void avgcost_reset( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char *error
void avgcost_clear( UDF_INIT* initid, char* is_null, char *error );
void avgcost_add( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char *error );
double avgcost( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char *error );
+my_bool is_const_init(UDF_INIT *initid, UDF_ARGS *args, char *message);
+char *is_const(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long
+ *length, char *is_null, char *error);
/*************************************************************************
@@ -1075,4 +1078,32 @@ char *myfunc_argument_name(UDF_INIT *initid __attribute__((unused)),
return result;
}
+
+
+my_bool is_const_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
+{
+ if (args->arg_count != 1)
+ {
+ strmov(message, "IS_CONST accepts only one argument");
+ return 1;
+ }
+ initid->ptr= (char*)((args->args[0] != NULL) ? 1 : 0);
+ return 0;
+}
+
+char * is_const(UDF_INIT *initid, UDF_ARGS *args __attribute__((unused)),
+ char *result, unsigned long *length,
+ char *is_null, char *error __attribute__((unused)))
+{
+ if (initid->ptr != 0) {
+ sprintf(result, "const");
+ } else {
+ sprintf(result, "not const");
+ }
+ *is_null= 0;
+ *length= strlen(result);
+ return result;
+}
+
+
#endif /* HAVE_DLOPEN */
diff --git a/sql/udf_example.def b/sql/udf_example.def
index d3081ca7768..ee107d58e51 100644
--- a/sql/udf_example.def
+++ b/sql/udf_example.def
@@ -22,3 +22,5 @@ EXPORTS
avgcost_add
avgcost_clear
avgcost
+ is_const
+ is_const_init