summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/authors.h9
-rw-r--r--sql/examples/ha_example.cc2
-rw-r--r--sql/ha_ndbcluster.cc21
-rw-r--r--sql/handler.h2
-rw-r--r--sql/item.cc57
-rw-r--r--sql/item.h4
-rw-r--r--sql/item_cmpfunc.cc2
-rw-r--r--sql/item_strfunc.cc65
-rw-r--r--sql/item_strfunc.h35
-rw-r--r--sql/mysql_priv.h2
-rw-r--r--sql/mysqld.cc3
-rw-r--r--sql/opt_range.cc21
-rw-r--r--sql/sp_head.cc20
-rw-r--r--sql/sql_class.cc1
-rw-r--r--sql/sql_class.h6
-rw-r--r--sql/sql_parse.cc12
-rw-r--r--sql/sql_show.cc1
-rw-r--r--sql/sql_table.cc34
-rw-r--r--sql/sql_update.cc14
-rw-r--r--sql/table.cc14
20 files changed, 224 insertions, 101 deletions
diff --git a/sql/authors.h b/sql/authors.h
index fa68b20c7a1..1c6e1d468c4 100644
--- a/sql/authors.h
+++ b/sql/authors.h
@@ -44,8 +44,7 @@ struct show_table_authors_st show_table_authors[]= {
"Unicode and character sets (4.1)" },
{ "Omer BarNir", "Sunnyvale, CA, USA",
"Testing (sometimes) and general QA stuff" },
- { "Guilhem Bichot", "Salles, France",
- "Replication, backup, mysql_tableinfo" },
+ { "Guilhem Bichot", "Bordeaux, France", "Replication (since 4.0)" },
{ "John Birrell", "", "Emulation of pthread_mutex() for OS/2" },
{ "Andreas F. Bobak", "", "AGGREGATE extension to user-defined functions" },
{ "Alexey Botchkov (Holyfoot)", "Izhevsk, Russia",
@@ -72,9 +71,12 @@ struct show_table_authors_st show_table_authors[]= {
{ "Nikolay Grishakin", "Austin, TX, USA", "Testing - Server" },
{ "Wei He", "", "Chinese (GBK) character set" },
{ "Eric Herman", "Amsterdam, Netherlands", "Bug fixing - federated" },
+ { "Alexander (Alexi) Ivanov", "St. Petersburg, Russia", "Replication" },
{ "Alexander (Salle) Keremidarski", "Sofia, Bulgaria",
"Bug fixing" },
+ { "Mats Kindahl", "Storvreta, Sweden", "Replication" },
{ "Serge Kozlov", "Velikie Luki, Russia", "Testing - Cluster" },
+ { "Greg (Groggy) Lehey", "Uchunga, SA, Australia", "Backup" },
{ "Matthias Leich", "Berlin, Germany", "Testing - Server" },
{ "Dmitri Lenev", "Moscow, Russia",
"Time zones support (4.1), Triggers (5.0)" },
@@ -86,6 +88,7 @@ struct show_table_authors_st show_table_authors[]= {
"UNION (4.0), Subqueries in FROM clause (4.1), many other features" },
{ "Jonathan (Jeb) Miller", "Kyle, TX, USA",
"Testing - Cluster, Replication" },
+ { "Elliot Murphy", "Cocoa, FL, USA", "Replication and backup" },
{ "Kristian Nielsen", "Copenhagen, Denmark",
"General build stuff" },
{ "Pekka Nouisiainen", "Stockholm, Sweden",
@@ -97,7 +100,7 @@ struct show_table_authors_st show_table_authors[]= {
"NDB Cluster, Online Backup, lots of other things" },
{ "Konstantin Osipov", "Moscow, Russia",
"Prepared statements (4.1), Cursors (5.0)" },
- { "Sasha Pachev", "",
+ { "Alexander (Sasha) Pachev", "Provo, UT, USA",
"Statement-based replication, SHOW CREATE TABLE, mysql-bench" },
{ "Irena Pancirov", "", "Port to Windows with Borland compiler" },
{ "Jan Pazdziora", "", "Czech sorting order" },
diff --git a/sql/examples/ha_example.cc b/sql/examples/ha_example.cc
index 38e0171774e..5b32b549e8d 100644
--- a/sql/examples/ha_example.cc
+++ b/sql/examples/ha_example.cc
@@ -495,6 +495,8 @@ int ha_example::rnd_pos(byte * buf, byte *pos)
/*
::info() is used to return information to the optimizer.
+ see my_base.h for the complete description
+
Currently this table handler doesn't implement most of the fields
really needed. SHOW also makes use of this data
Another note, you will probably want to have the following in your
diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc
index 09bd48a3cd7..75ee136c916 100644
--- a/sql/ha_ndbcluster.cc
+++ b/sql/ha_ndbcluster.cc
@@ -3435,17 +3435,20 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type)
DBUG_PRINT("info", ("Table schema version: %d",
tab->getObjectVersion()));
}
- if (m_table != (void *)tab)
- {
- m_table= (void *)tab;
- m_table_version = tab->getObjectVersion();
- }
- else if (m_table_version < tab->getObjectVersion())
+ if (m_table_version < tab->getObjectVersion())
{
/*
The table has been altered, caller has to retry
*/
- DBUG_RETURN(my_errno= HA_ERR_TABLE_DEF_CHANGED);
+ NdbError err= ndb->getNdbError(NDB_INVALID_SCHEMA_OBJECT);
+ DBUG_RETURN(ndb_to_mysql_error(&err));
+ }
+ if (m_table != (void *)tab)
+ {
+ m_table= (void *)tab;
+ m_table_version = tab->getObjectVersion();
+ if (!(my_errno= build_index_list(ndb, table, ILBP_OPEN)))
+ DBUG_RETURN(my_errno);
}
m_table_info= tab_info;
}
@@ -3936,8 +3939,8 @@ int ha_ndbcluster::create(const char *name,
uint pack_length, length, i, pk_length= 0;
const void *data, *pack_data;
char name2[FN_HEADLEN];
- bool create_from_engine= test(info->table_options &
- HA_OPTION_CREATE_FROM_ENGINE);
+ bool create_from_engine= (info->table_options & HA_OPTION_CREATE_FROM_ENGINE);
+
DBUG_ENTER("ha_ndbcluster::create");
DBUG_PRINT("enter", ("name: %s", name));
diff --git a/sql/handler.h b/sql/handler.h
index dc6e3edc40c..b4b90cbfaa8 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -1174,7 +1174,7 @@ public:
key_range *max_key)
{ return (ha_rows) 10; }
virtual void position(const byte *record)=0;
- virtual void info(uint)=0;
+ virtual void info(uint)=0; // see my_base.h for full description
virtual int extra(enum ha_extra_function operation)
{ return 0; }
virtual int extra_opt(enum ha_extra_function operation, ulong cache_size)
diff --git a/sql/item.cc b/sql/item.cc
index 1c2016049ad..438741581bb 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -601,16 +601,8 @@ bool Item::eq(const Item *item, bool binary_cmp) const
Item *Item::safe_charset_converter(CHARSET_INFO *tocs)
{
- /*
- Allow conversion from and to "binary".
- Don't allow automatic conversion to non-Unicode charsets,
- as it potentially loses data.
- */
- if (collation.collation != &my_charset_bin &&
- tocs != &my_charset_bin &&
- !(tocs->state & MY_CS_UNICODE))
- return NULL; // safe conversion is not possible
- return new Item_func_conv_charset(this, tocs);
+ Item_func_conv_charset *conv= new Item_func_conv_charset(this, tocs, 1);
+ return conv->safe ? conv : NULL;
}
@@ -700,23 +692,15 @@ Item *Item_param::safe_charset_converter(CHARSET_INFO *tocs)
{
if (const_item())
{
- Item_string *conv;
uint cnv_errors;
- char buf[MAX_FIELD_WIDTH];
- String tmp(buf, sizeof(buf), &my_charset_bin);
- String cstr, *ostr= val_str(&tmp);
- /*
- As safe_charset_converter is not executed for
- a parameter bound to NULL, ostr should never be 0.
- */
- cstr.copy(ostr->ptr(), ostr->length(), ostr->charset(), tocs, &cnv_errors);
- if (cnv_errors || !(conv= new Item_string(cstr.ptr(), cstr.length(),
- cstr.charset(),
- collation.derivation)))
- return NULL;
- conv->str_value.copy();
- conv->str_value.mark_as_const();
- return conv;
+ String *ostr= val_str(&cnvstr);
+ cnvitem->str_value.copy(ostr->ptr(), ostr->length(),
+ ostr->charset(), tocs, &cnv_errors);
+ if (cnv_errors)
+ return NULL;
+ cnvitem->str_value.mark_as_const();
+ cnvitem->max_length= cnvitem->str_value.numchars() * tocs->mbmaxlen;
+ return cnvitem;
}
return NULL;
}
@@ -2105,6 +2089,8 @@ Item_param::Item_param(unsigned pos_in_query_arg) :
value is set.
*/
maybe_null= 1;
+ cnvitem= new Item_string("", 0, &my_charset_bin, DERIVATION_COERCIBLE);
+ cnvstr.set(cnvbuf, sizeof(cnvbuf), &my_charset_bin);
}
@@ -5302,7 +5288,7 @@ Item_result item_cmp_type(Item_result a,Item_result b)
void resolve_const_item(THD *thd, Item **ref, Item *comp_item)
{
Item *item= *ref;
- Item *new_item;
+ Item *new_item= NULL;
if (item->basic_const_item())
return; // Can't be better
Item_result res_type=item_cmp_type(comp_item->result_type(),
@@ -5335,7 +5321,16 @@ void resolve_const_item(THD *thd, Item **ref, Item *comp_item)
break;
}
case ROW_RESULT:
+ if (item->type() == Item::ROW_ITEM && comp_item->type() == Item::ROW_ITEM)
{
+ /*
+ Substitute constants only in Item_rows. Don't affect other Items
+ with ROW_RESULT (eg Item_singlerow_subselect).
+
+ For such Items more optimal is to detect if it is constant and replace
+ it with Item_row. This would optimize queries like this:
+ SELECT * FROM t1 WHERE (a,b) = (SELECT a,b FROM t2 LIMIT 1);
+ */
Item_row *item_row= (Item_row*) item;
Item_row *comp_item_row= (Item_row*) comp_item;
uint col;
@@ -5353,6 +5348,7 @@ void resolve_const_item(THD *thd, Item **ref, Item *comp_item)
resolve_const_item(thd, item_row->addr(col), comp_item_row->el(col));
break;
}
+ /* Fallthrough */
case REAL_RESULT:
{ // It must REAL_RESULT
double result= item->val_real();
@@ -5858,8 +5854,11 @@ bool Item_type_holder::join_types(THD *thd, Item *item)
{
int delta1= max_length_orig - decimals_orig;
int delta2= item->max_length - item->decimals;
- max_length= min(max(delta1, delta2) + decimals,
- (fld_type == MYSQL_TYPE_FLOAT) ? FLT_DIG+6 : DBL_DIG+7);
+ if (fld_type == MYSQL_TYPE_DECIMAL)
+ max_length= max(delta1, delta2) + decimals;
+ else
+ max_length= min(max(delta1, delta2) + decimals,
+ (fld_type == MYSQL_TYPE_FLOAT) ? FLT_DIG+6 : DBL_DIG+7);
}
else
max_length= (fld_type == MYSQL_TYPE_FLOAT) ? FLT_DIG+6 : DBL_DIG+7;
diff --git a/sql/item.h b/sql/item.h
index 711050395de..4f06d75675c 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -1084,7 +1084,11 @@ public:
class Item_param :public Item
{
+ char cnvbuf[MAX_FIELD_WIDTH];
+ String cnvstr;
+ Item *cnvitem;
public:
+
enum enum_item_param_state
{
NO_VALUE, NULL_VALUE, INT_VALUE, REAL_VALUE,
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index a8ccc8771c9..51d19a385ec 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -3662,7 +3662,7 @@ void Item_equal::merge(Item_equal *item)
the multiple equality already contains a constant and its
value is not equal to the value of c.
*/
- add(const_item);
+ add(c);
}
cond_false|= item->cond_false;
}
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index a8c51bb6662..8c0dea4efb2 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -48,6 +48,38 @@ static void my_coll_agg_error(DTCollation &c1, DTCollation &c2,
}
+String *Item_str_func::check_well_formed_result(String *str)
+{
+ /* Check whether we got a well-formed string */
+ CHARSET_INFO *cs= str->charset();
+ int well_formed_error;
+ uint wlen= cs->cset->well_formed_len(cs,
+ str->ptr(), str->ptr() + str->length(),
+ str->length(), &well_formed_error);
+ if (wlen < str->length())
+ {
+ THD *thd= current_thd;
+ char hexbuf[7];
+ enum MYSQL_ERROR::enum_warning_level level;
+ uint diff= str->length() - wlen;
+ set_if_smaller(diff, 3);
+ octet2hex(hexbuf, str->ptr() + wlen, diff);
+ if (thd->variables.sql_mode &
+ (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES))
+ {
+ level= MYSQL_ERROR::WARN_LEVEL_ERROR;
+ null_value= 1;
+ str= 0;
+ }
+ else
+ level= MYSQL_ERROR::WARN_LEVEL_WARN;
+ push_warning_printf(thd, level, ER_INVALID_CHARACTER_STRING,
+ ER(ER_INVALID_CHARACTER_STRING), cs->csname, hexbuf);
+ }
+ return str;
+}
+
+
double Item_str_func::val_real()
{
DBUG_ASSERT(fixed == 1);
@@ -1984,34 +2016,7 @@ String *Item_func_char::val_str(String *str)
}
str->set_charset(collation.collation);
str->realloc(str->length()); // Add end 0 (for Purify)
-
- /* Check whether we got a well-formed string */
- CHARSET_INFO *cs= collation.collation;
- int well_formed_error;
- uint wlen= cs->cset->well_formed_len(cs,
- str->ptr(), str->ptr() + str->length(),
- str->length(), &well_formed_error);
- if (wlen < str->length())
- {
- THD *thd= current_thd;
- char hexbuf[7];
- enum MYSQL_ERROR::enum_warning_level level;
- uint diff= str->length() - wlen;
- set_if_smaller(diff, 3);
- octet2hex(hexbuf, str->ptr() + wlen, diff);
- if (thd->variables.sql_mode &
- (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES))
- {
- level= MYSQL_ERROR::WARN_LEVEL_ERROR;
- null_value= 1;
- str= 0;
- }
- else
- level= MYSQL_ERROR::WARN_LEVEL_WARN;
- push_warning_printf(thd, level, ER_INVALID_CHARACTER_STRING,
- ER(ER_INVALID_CHARACTER_STRING), cs->csname, hexbuf);
- }
- return str;
+ return check_well_formed_result(str);
}
@@ -2311,6 +2316,8 @@ String *Item_func_conv::val_str(String *str)
String *Item_func_conv_charset::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
+ if (use_cached_value)
+ return null_value ? 0 : &str_value;
String *arg= args[0]->val_str(str);
uint dummy_errors;
if (!arg)
@@ -2320,7 +2327,7 @@ String *Item_func_conv_charset::val_str(String *str)
}
null_value= str_value.copy(arg->ptr(),arg->length(),arg->charset(),
conv_charset, &dummy_errors);
- return null_value ? 0 : &str_value;
+ return null_value ? 0 : check_well_formed_result(&str_value);
}
void Item_func_conv_charset::fix_length_and_dec()
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index 81f809d2b67..50ec0b36ce8 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -35,6 +35,7 @@ public:
double val_real();
enum Item_result result_type () const { return STRING_RESULT; }
void left_right_max_length();
+ String *check_well_formed_result(String *str);
};
class Item_func_md5 :public Item_str_func
@@ -651,10 +652,40 @@ public:
class Item_func_conv_charset :public Item_str_func
{
+ bool use_cached_value;
public:
+ bool safe;
CHARSET_INFO *conv_charset; // keep it public
- Item_func_conv_charset(Item *a, CHARSET_INFO *cs) :Item_str_func(a)
- { conv_charset=cs; }
+ Item_func_conv_charset(Item *a, CHARSET_INFO *cs) :Item_str_func(a)
+ { conv_charset= cs; use_cached_value= 0; safe= 0; }
+ Item_func_conv_charset(Item *a, CHARSET_INFO *cs, bool cache_if_const)
+ :Item_str_func(a)
+ {
+ DBUG_ASSERT(args[0]->fixed);
+ conv_charset= cs;
+ if (cache_if_const && args[0]->const_item())
+ {
+ uint errors= 0;
+ String tmp, *str= args[0]->val_str(&tmp);
+ if (!str || str_value.copy(str->ptr(), str->length(),
+ str->charset(), conv_charset, &errors))
+ null_value= 1;
+ use_cached_value= 1;
+ safe= (errors == 0);
+ }
+ else
+ {
+ use_cached_value= 0;
+ /*
+ Conversion from and to "binary" is safe.
+ Conversion to Unicode is safe.
+ Other kind of conversions are potentially lossy.
+ */
+ safe= (args[0]->collation.collation == &my_charset_bin ||
+ cs == &my_charset_bin ||
+ (cs->state & MY_CS_UNICODE));
+ }
+ }
String *val_str(String *);
void fix_length_and_dec();
const char *func_name() const { return "convert"; }
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 33e6ac8bb39..4b7a1fc00a8 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -1463,7 +1463,7 @@ int calc_weekday(long daynr,bool sunday_first_day_of_week);
uint calc_week(TIME *l_time, uint week_behaviour, uint *year);
void find_date(char *pos,uint *vek,uint flag);
TYPELIB *convert_strings_to_array_type(my_string *typelibs, my_string *end);
-TYPELIB *typelib(List<String> &strings);
+TYPELIB *typelib(MEM_ROOT *mem_root, List<String> &strings);
ulong get_form_pos(File file, uchar *head, TYPELIB *save_names);
ulong make_new_entry(File file,uchar *fileinfo,TYPELIB *formnames,
const char *newname);
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 8b92e953062..f344becffde 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -1647,6 +1647,7 @@ void end_thread(THD *thd, bool put_in_cache)
wake_thread--;
thd=thread_cache.get();
thd->real_id=pthread_self();
+ thd->thread_stack= (char *) &thd;
(void) thd->store_globals();
thd->thr_create_time= time(NULL);
threads.append(thd);
@@ -7003,10 +7004,10 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
case OPT_MYISAM_STATS_METHOD:
{
ulong method_conv;
+ int method;
LINT_INIT(method_conv);
myisam_stats_method_str= argument;
- int method;
if ((method=find_type(argument, &myisam_stats_method_typelib, 2)) <= 0)
{
fprintf(stderr, "Invalid value of myisam_stats_method: %s.\n", argument);
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 2645a798896..625a956eea2 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -3142,10 +3142,10 @@ TRP_ROR_INTERSECT *get_best_covering_ror_intersect(PARAM *param,
/* F=F-covered by first(I) */
bitmap_union(&covered_fields, &(*ror_scan_mark)->covered_fields);
all_covered= bitmap_is_subset(&param->needed_fields, &covered_fields);
- } while (!all_covered && (++ror_scan_mark < ror_scans_end));
-
- if (!all_covered)
- DBUG_RETURN(NULL); /* should not happen actually */
+ } while ((++ror_scan_mark < ror_scans_end) && !all_covered);
+
+ if (!all_covered || (ror_scan_mark - tree->ror_scans) == 1)
+ DBUG_RETURN(NULL);
/*
Ok, [tree->ror_scans .. ror_scan) holds covering index_intersection with
@@ -7211,6 +7211,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
{
select_items_it.rewind();
cur_used_key_parts.clear_all();
+ uint max_key_part= 0;
while ((item= select_items_it++))
{
item_field= (Item_field*) item; /* (SA5) already checked above. */
@@ -7228,7 +7229,19 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
cur_group_prefix_len+= cur_part->store_length;
cur_used_key_parts.set_bit(key_part_nr);
++cur_group_key_parts;
+ max_key_part= max(max_key_part,key_part_nr);
}
+ /*
+ Check that used key parts forms a prefix of the index.
+ To check this we compare bits in all_parts and cur_parts.
+ all_parts have all bits set from 0 to (max_key_part-1).
+ cur_parts have bits set for only used keyparts.
+ */
+ ulonglong all_parts, cur_parts;
+ all_parts= (1<<max_key_part) - 1;
+ cur_parts= cur_used_key_parts.to_ulonglong() >> 1;
+ if (all_parts != cur_parts)
+ goto next_index;
}
else
DBUG_ASSERT(FALSE);
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index 0800089209c..8b176b03756 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -2215,6 +2215,26 @@ sp_instr_set::exec_core(THD *thd, uint *nextp)
{
int res= thd->spcont->set_item_eval(thd, m_offset, &m_value, m_type);
+ if (res < 0 &&
+ thd->spcont->get_item(m_offset) == NULL &&
+ thd->spcont->found_handler_here())
+ {
+ /*
+ Failed to evaluate the value, the variable is still not initialized,
+ and a handler has been found. Set to null so we can continue.
+ */
+ Item *it= new Item_null();
+
+ if (!it || thd->spcont->set_item_eval(thd, m_offset, &it, m_type) < 0)
+ { /* If this also failed, we have to abort */
+ sp_rcontext *spcont= thd->spcont;
+
+ thd->spcont= 0; /* Avoid handlers */
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ spcont->clear_handler();
+ thd->spcont= spcont;
+ }
+ }
*nextp = m_ip+1;
return res;
}
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 38bed255215..fc86bd473e5 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -183,6 +183,7 @@ THD::THD()
spcont(NULL)
{
stmt_arena= this;
+ thread_stack= 0;
db= 0;
catalog= (char*)"std"; // the only catalog we have for now
main_security_ctx.init();
diff --git a/sql/sql_class.h b/sql/sql_class.h
index e075e46fb03..3ac95bc1ad8 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -1241,14 +1241,16 @@ public:
free_root(&mem_root,MYF(MY_KEEP_PREALLOC));
#endif
}
-#ifdef USING_TRANSACTIONS
st_transactions()
{
+#ifdef USING_TRANSACTIONS
bzero((char*)this, sizeof(*this));
xid_state.xid.null();
init_sql_alloc(&mem_root, ALLOC_ROOT_MIN_BLOCK_SIZE, 0);
- }
+#else
+ xid_state.xa_state= XA_NOTR;
#endif
+ }
} transaction;
Field *dupp_field;
#ifndef __WIN__
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 57d7059dd8f..2e2a6f4d1b1 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -4844,11 +4844,15 @@ end_with_restore_list:
/*
- The return value for ROW_COUNT() is "implementation dependent" if
- the statement is not DELETE, INSERT or UPDATE (or a CALL executing
- such a statement), but -1 is what JDBC and ODBC wants.
+ The return value for ROW_COUNT() is "implementation dependent" if the
+ statement is not DELETE, INSERT or UPDATE, but -1 is what JDBC and ODBC
+ wants.
+
+ We do not change the value for a CALL or EXECUTE statement, so the value
+ generated by the last called (or executed) statement is preserved.
*/
- if (lex->sql_command != SQLCOM_CALL && uc_update_queries[lex->sql_command]<2)
+ if (lex->sql_command != SQLCOM_CALL && lex->sql_command != SQLCOM_EXECUTE &&
+ uc_update_queries[lex->sql_command]<2)
thd->row_count_func= -1;
goto cleanup;
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index e33fc2e1c56..eaf10a3b074 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -911,7 +911,6 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet)
}
key_info= table->key_info;
- file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK | HA_STATUS_TIME);
bzero((char*) &create_info, sizeof(create_info));
file->update_create_info(&create_info);
primary_key= share->primary_key;
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index c8775ebc923..ff562cf2a39 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -799,7 +799,14 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
*/
if (!interval)
{
- interval= sql_field->interval= typelib(sql_field->interval_list);
+ /*
+ Create the typelib in prepared statement memory if we're
+ executing one.
+ */
+ MEM_ROOT *stmt_root= thd->stmt_arena->mem_root;
+
+ interval= sql_field->interval= typelib(stmt_root,
+ sql_field->interval_list);
List_iterator<String> it(sql_field->interval_list);
String conv, *tmp;
for (uint i= 0; (tmp= it++); i++)
@@ -810,7 +817,7 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
{
uint cnv_errs;
conv.copy(tmp->ptr(), tmp->length(), tmp->charset(), cs, &cnv_errs);
- interval->type_names[i]= strmake_root(thd->mem_root, conv.ptr(),
+ interval->type_names[i]= strmake_root(stmt_root, conv.ptr(),
conv.length());
interval->type_lengths[i]= conv.length();
}
@@ -830,8 +837,22 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
*/
if (sql_field->def && cs != sql_field->def->collation.collation)
{
- if (!(sql_field->def=
- sql_field->def->safe_charset_converter(cs)))
+ Query_arena backup_arena;
+ bool need_to_change_arena= !thd->stmt_arena->is_conventional();
+ if (need_to_change_arena)
+ {
+ /* Asser that we don't do that at every PS execute */
+ DBUG_ASSERT(thd->stmt_arena->is_first_stmt_execute() ||
+ thd->stmt_arena->is_first_sp_execute());
+ thd->set_n_backup_active_arena(thd->stmt_arena, &backup_arena);
+ }
+
+ sql_field->def= sql_field->def->safe_charset_converter(cs);
+
+ if (need_to_change_arena)
+ thd->restore_active_arena(thd->stmt_arena, &backup_arena);
+
+ if (! sql_field->def)
{
/* Could not convert */
my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
@@ -4132,7 +4153,10 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0), def->change);
DBUG_RETURN(TRUE);
}
- def->def=alter->def; // Use new default
+ if ((def->def=alter->def)) // Use new default
+ def->flags&= ~NO_DEFAULT_VALUE_FLAG;
+ else
+ def->flags|= NO_DEFAULT_VALUE_FLAG;
alter_it.remove();
}
}
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index b0d35407eef..79e6a4766a5 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -516,7 +516,12 @@ int mysql_update(THD *thd,
}
else if (!ignore || error != HA_ERR_FOUND_DUPP_KEY)
{
- thd->fatal_error(); // Force error message
+ /*
+ If (ignore && error == HA_ERR_FOUND_DUPP_KEY) we don't have to
+ do anything; otherwise...
+ */
+ if (error != HA_ERR_FOUND_DUPP_KEY)
+ thd->fatal_error(); /* Other handler errors are fatal */
table->file->print_error(error,MYF(0));
error= 1;
break;
@@ -1365,7 +1370,12 @@ bool multi_update::send_data(List<Item> &not_used_values)
updated--;
if (!ignore || error != HA_ERR_FOUND_DUPP_KEY)
{
- thd->fatal_error(); // Force error message
+ /*
+ If (ignore && error == HA_ERR_FOUND_DUPP_KEY) we don't have to
+ do anything; otherwise...
+ */
+ if (error != HA_ERR_FOUND_DUPP_KEY)
+ thd->fatal_error(); /* Other handler errors are fatal */
table->file->print_error(error,MYF(0));
DBUG_RETURN(1);
}
diff --git a/sql/table.cc b/sql/table.cc
index d2e22ffd5f7..ff29a33ef03 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -1721,15 +1721,15 @@ fix_type_pointers(const char ***array, TYPELIB *point_to_type, uint types,
} /* fix_type_pointers */
-TYPELIB *typelib(List<String> &strings)
+TYPELIB *typelib(MEM_ROOT *mem_root, List<String> &strings)
{
- TYPELIB *result=(TYPELIB*) sql_alloc(sizeof(TYPELIB));
+ TYPELIB *result= (TYPELIB*) alloc_root(mem_root, sizeof(TYPELIB));
if (!result)
return 0;
result->count=strings.elements;
result->name="";
uint nbytes= (sizeof(char*) + sizeof(uint)) * (result->count + 1);
- if (!(result->type_names= (const char**) sql_alloc(nbytes)))
+ if (!(result->type_names= (const char**) alloc_root(mem_root, nbytes)))
return 0;
result->type_lengths= (uint*) (result->type_names + result->count + 1);
List_iterator<String> it(strings);
@@ -1879,10 +1879,10 @@ File create_frm(THD *thd, const char *name, const char *db,
#if SIZEOF_OFF_T > 4
/* Fix this when we have new .frm files; Current limit is 4G rows (QQ) */
- if (create_info->max_rows > ~(ulong) 0)
- create_info->max_rows= ~(ulong) 0;
- if (create_info->min_rows > ~(ulong) 0)
- create_info->min_rows= ~(ulong) 0;
+ if (create_info->max_rows > UINT_MAX32)
+ create_info->max_rows= UINT_MAX32;
+ if (create_info->min_rows > UINT_MAX32)
+ create_info->min_rows= UINT_MAX32;
#endif
/*
Ensure that raid_chunks can't be larger than 255, as this would cause