Below is the list of changes that have just been committed into a local
5.0-community repository of cmiller. When cmiller does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet@stripped, 2007-04-26 09:45:09-04:00, cmiller@stripped +29 -0
Merge mysqldev@stripped:my/mysql-5.0-release
into zippy.cornsilk.net:/home/cmiller/work/mysql/mysql-5.0-comeng
MERGE: 1.2410.5.14
BitKeeper/deleted/.del-configure.in.rej@stripped, 2007-04-26 09:44:15-04:00, cmiller@stripped +0 -0
Auto merged
MERGE: 1.1.1.1
configure.in@stripped, 2007-04-26 09:44:15-04:00, cmiller@stripped +0 -0
Auto merged
MERGE: 1.416.1.22
include/config-win.h@stripped, 2007-04-26 09:44:15-04:00, cmiller@stripped +0 -0
Auto merged
MERGE: 1.84.1.1
myisam/mi_open.c@stripped, 2007-04-26 09:44:16-04:00, cmiller@stripped +0 -0
Auto merged
MERGE: 1.105.1.2
mysql-test/r/information_schema.result@stripped, 2007-04-26 09:44:16-04:00, cmiller@stripped +0 -0
Auto merged
MERGE: 1.117.1.4
ndb/src/ndbapi/DictCache.cpp@stripped, 2007-04-26 09:44:16-04:00, cmiller@stripped +0 -0
Auto merged
MERGE: 1.20.1.1
sql/ha_archive.cc@stripped, 2007-04-26 09:44:16-04:00, cmiller@stripped +0 -0
Auto merged
MERGE: 1.83.1.1
sql/ha_myisam.cc@stripped, 2007-04-26 09:44:16-04:00, cmiller@stripped +0 -0
Auto merged
MERGE: 1.175.1.2
sql/ha_ndbcluster.cc@stripped, 2007-04-26 09:44:16-04:00, cmiller@stripped +0 -0
Auto merged
MERGE: 1.299.2.2
sql/item_cmpfunc.cc@stripped, 2007-04-26 09:44:16-04:00, cmiller@stripped +0 -0
Auto merged
MERGE: 1.241.1.3
sql/item_func.cc@stripped, 2007-04-26 09:44:16-04:00, cmiller@stripped +0 -0
Auto merged
MERGE: 1.328.1.5
sql/lock.cc@stripped, 2007-04-26 09:44:16-04:00, cmiller@stripped +0 -0
Auto merged
MERGE: 1.93.1.2
sql/log_event.cc@stripped, 2007-04-26 09:44:16-04:00, cmiller@stripped +0 -0
Auto merged
MERGE: 1.229.1.1
sql/mysql_priv.h@stripped, 2007-04-26 09:44:17-04:00, cmiller@stripped +0 -0
Auto merged
MERGE: 1.440.1.1
sql/mysqld.cc@stripped, 2007-04-26 09:44:17-04:00, cmiller@stripped +0 -0
Auto merged
MERGE: 1.598.1.4
sql/sp_head.cc@stripped, 2007-04-26 09:44:17-04:00, cmiller@stripped +0 -0
Auto merged
MERGE: 1.239.1.1
sql/sql_base.cc@stripped, 2007-04-26 09:44:17-04:00, cmiller@stripped +0 -0
Auto merged
MERGE: 1.360.1.15
sql/sql_class.cc@stripped, 2007-04-26 09:44:17-04:00, cmiller@stripped +0 -0
Auto merged
MERGE: 1.256.1.11
sql/sql_class.h@stripped, 2007-04-26 09:44:17-04:00, cmiller@stripped +0 -0
Auto merged
MERGE: 1.314.1.13
sql/sql_delete.cc@stripped, 2007-04-26 09:44:18-04:00, cmiller@stripped +0 -0
Auto merged
MERGE: 1.188.1.9
sql/sql_insert.cc@stripped, 2007-04-26 09:44:18-04:00, cmiller@stripped +0 -0
Auto merged
MERGE: 1.211.1.18
sql/sql_lex.cc@stripped, 2007-04-26 09:44:18-04:00, cmiller@stripped +0 -0
Auto merged
MERGE: 1.217.2.2
sql/sql_select.cc@stripped, 2007-04-26 09:44:18-04:00, cmiller@stripped +0 -0
Auto merged
MERGE: 1.500.1.2
sql/sql_show.cc@stripped, 2007-04-26 09:44:18-04:00, cmiller@stripped +0 -0
Auto merged
MERGE: 1.344.1.1
sql/sql_table.cc@stripped, 2007-04-26 09:44:18-04:00, cmiller@stripped +0 -0
Auto merged
MERGE: 1.335.1.5
sql/sql_update.cc@stripped, 2007-04-26 09:44:19-04:00, cmiller@stripped +0 -0
Auto merged
MERGE: 1.212.2.1
sql/sql_yacc.yy@stripped, 2007-04-26 09:44:19-04:00, cmiller@stripped +0 -0
Auto merged
MERGE: 1.512.1.2
sql/table.h@stripped, 2007-04-26 09:44:19-04:00, cmiller@stripped +0 -0
Auto merged
MERGE: 1.138.1.3
support-files/mysql.spec.sh@stripped, 2007-04-26 09:45:07-04:00, cmiller@stripped +1 -0
Manual merge of Enterprise advert.
MERGE: 1.169.1.1
# This is a BitKeeper patch. What follows are the unified diffs for the
# set of deltas contained in the patch. The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User: cmiller
# Host: zippy.cornsilk.net
# Root: /home/cmiller/work/mysql/mysql-5.0-comeng/RESYNC
--- 1.427/configure.in 2007-04-04 07:49:32 -04:00
+++ 1.428/configure.in 2007-04-26 09:44:15 -04:00
@@ -30,7 +30,7 @@ NDB_VERSION_STATUS=""
# Remember that regexps needs to quote [ and ] since this is run through m4
MYSQL_NO_DASH_VERSION=`echo $VERSION | sed -e "s|[[a-z]]*-.*$||"`
MYSQL_BASE_VERSION=`echo $MYSQL_NO_DASH_VERSION | sed -e "s|\.[[^.]]*$||"`
-MYSQL_VERSION_ID=`echo $MYSQL_NO_DASH_VERSION. | sed -e 's/[[^0-9.]]//g; s/\./ /g; s/ \([[0-9]]\) / 0\\1 /g; s/ //g'`
+MYSQL_VERSION_ID=`echo $MYSQL_NO_DASH_VERSION | sed -e 's|[[^0-9.]].*$||;s|$|.|' | sed -e 's/[[^0-9.]]//g; s/\./ /g; s/ \([[0-9]]\) / 0\\1 /g; s/ //g'`
# The port should be constant for a LONG time
MYSQL_TCP_PORT_DEFAULT=3306
@@ -1615,9 +1615,9 @@ fi
# dlopen, dlerror
case "$with_mysqld_ldflags " in
- *"-static "*)
+ *"-all-static "*)
# No need to check for dlopen when mysqld is linked with
- # -all-static or -static as it won't be able to load any functions.
+ # -all-static as it won't be able to load any functions.
# NOTE! It would be better if it was possible to test if dlopen
# can be used, but a good way to test it couldn't be found
@@ -2411,22 +2411,6 @@ AC_ARG_WITH(man,
[with_man=yes]
)
-if test "$with_man" = "yes"
-then
- man_dirs="man"
- man1_files=`ls -1 $srcdir/man/*.1 | sed -e 's;^.*man/;;'`
- man1_files=`echo $man1_files`
- man8_files=`ls -1 $srcdir/man/*.8 | sed -e 's;^.*man/;;'`
- man8_files=`echo $man8_files`
-else
- man_dirs=""
- man1_files=""
- man8_files=""
-fi
-AC_SUBST(man_dirs)
-AC_SUBST(man1_files)
-AC_SUBST(man8_files)
-
# Shall we build the bench code?
AC_ARG_WITH(bench,
[ --without-bench Skip building of the benchmark suite.],
@@ -2560,6 +2544,60 @@ MYSQL_CHECK_CSVDB
MYSQL_CHECK_BLACKHOLEDB
MYSQL_CHECK_NDBCLUSTER
MYSQL_CHECK_FEDERATED
+
+# Include man pages, if desired, adapted to the configured parts.
+if test X"$with_man" = Xyes
+then
+ # First, create the list of all man pages present.
+ MANLISTFIL=manlist.$$
+ TMPLISTFIL=`echo $MANLISTFIL | sed -e 's/manlist/tmplist/'`
+ if test -f $MANLISTFIL -o -f $TMPLISTFIL
+ then
+ echo "Temp file '$MANLISTFIL' or '$TMPLISTFIL' already exists in '`pwd`' - aborting"
+ exit 1
+ fi
+ touch $MANLISTFIL $TMPLISTFIL
+
+ ls $srcdir/man/*.[[18]] > $MANLISTFIL
+
+ # Then, remove all those pages from the list which are specific to parts
+ # (table handlers, features, ...) which are not configured in this run.
+ AC_MSG_CHECKING("for man pages to remove")
+ MAN_DROP="dropping"
+ if test X"$have_ndbcluster" != Xyes
+ then
+ MAN_DROP="$MAN_DROP ndbcluster"
+ grep -v '/ndb' $MANLISTFIL > $TMPLISTFIL ; mv -f $TMPLISTFIL $MANLISTFIL
+ fi
+ if test X"$with_embedded_server" != Xyes
+ then
+ MAN_DROP="$MAN_DROP embedded"
+ grep -v 'embedded' $MANLISTFIL > $TMPLISTFIL ; mv -f $TMPLISTFIL $MANLISTFIL
+ fi
+ if test X"$have_innodb" != Xyes
+ then
+ MAN_DROP="$MAN_DROP innodb"
+ grep -v 'inno' $MANLISTFIL > $TMPLISTFIL ; mv -f $TMPLISTFIL $MANLISTFIL
+ fi
+ AC_MSG_RESULT([$MAN_DROP])
+
+ # Finally, split the man pages into sections 1 and 8.
+ # Get rid of line breaks.
+ man1_files=`sed -n -e '/\.1$/s/^.*man\///p' <$MANLISTFIL`
+ man8_files=`sed -n -e '/\.8$/s/^.*man\///p' <$MANLISTFIL`
+
+ man_dirs="man"
+ man1_files=`echo $man1_files`
+ man8_files=`echo $man8_files`
+ rm -f $MANLISTFIL $TMPLISTFIL
+else
+ man_dirs=""
+ man1_files=""
+ man8_files=""
+fi
+AC_SUBST(man_dirs)
+AC_SUBST(man1_files)
+AC_SUBST(man8_files)
# If we have threads generate some library functions and test programs
sql_server_dirs=
--- 1.86/include/config-win.h 2007-04-04 07:47:31 -04:00
+++ 1.87/include/config-win.h 2007-04-26 09:44:15 -04:00
@@ -411,14 +411,8 @@ inline double ulonglong2double(ulonglong
#define shared_memory_buffer_length 16000
#define default_shared_memory_base_name "MYSQL"
-#ifdef CYBOZU
-#define MYSQL_DEFAULT_CHARSET_NAME "utf8"
-#define MYSQL_DEFAULT_COLLATION_NAME "utf8_general_cs"
-#define HAVE_UTF8_GENERAL_CS 1
-#else
#define MYSQL_DEFAULT_CHARSET_NAME "latin1"
#define MYSQL_DEFAULT_COLLATION_NAME "latin1_swedish_ci"
-#endif
#define HAVE_SPATIAL 1
#define HAVE_RTREE_KEYS 1
@@ -429,10 +423,8 @@ inline double ulonglong2double(ulonglong
/* Define charsets you want */
/* #undef HAVE_CHARSET_armscii8 */
/* #undef HAVE_CHARSET_ascii */
-#ifndef CYBOZU
#define HAVE_CHARSET_big5 1
#define HAVE_CHARSET_cp1250 1
-#endif
/* #undef HAVE_CHARSET_cp1251 */
/* #undef HAVE_CHARSET_cp1256 */
/* #undef HAVE_CHARSET_cp1257 */
@@ -441,33 +433,27 @@ inline double ulonglong2double(ulonglong
/* #undef HAVE_CHARSET_cp866 */
#define HAVE_CHARSET_cp932 1
/* #undef HAVE_CHARSET_dec8 */
-#ifndef CYBOZU
#define HAVE_CHARSET_eucjpms 1
#define HAVE_CHARSET_euckr 1
#define HAVE_CHARSET_gb2312 1
#define HAVE_CHARSET_gbk 1
-#endif
/* #undef HAVE_CHARSET_greek */
/* #undef HAVE_CHARSET_hebrew */
/* #undef HAVE_CHARSET_hp8 */
/* #undef HAVE_CHARSET_keybcs2 */
/* #undef HAVE_CHARSET_koi8r */
/* #undef HAVE_CHARSET_koi8u */
-#ifndef CYBOZU
#define HAVE_CHARSET_latin1 1
#define HAVE_CHARSET_latin2 1
-#endif
/* #undef HAVE_CHARSET_latin5 */
/* #undef HAVE_CHARSET_latin7 */
/* #undef HAVE_CHARSET_macce */
/* #undef HAVE_CHARSET_macroman */
#define HAVE_CHARSET_sjis 1
/* #undef HAVE_CHARSET_swe7 */
-#ifndef CYBOZU
#define HAVE_CHARSET_tis620 1
#define HAVE_CHARSET_ucs2 1
#define HAVE_CHARSET_ujis 1
-#endif
#define HAVE_CHARSET_utf8 1
#define HAVE_UCA_COLLATIONS 1
--- 1.178/sql/ha_myisam.cc 2007-03-28 04:22:20 -04:00
+++ 1.179/sql/ha_myisam.cc 2007-04-26 09:44:16 -04:00
@@ -673,7 +673,7 @@ int ha_myisam::check(THD* thd, HA_CHECK_
MYISAM_SHARE* share = file->s;
const char *old_proc_info=thd->proc_info;
- thd->proc_info="Checking table";
+ thd_proc_info(thd, "Checking table");
myisamchk_init(¶m);
param.thd = thd;
param.op_name = "check";
@@ -747,7 +747,7 @@ int ha_myisam::check(THD* thd, HA_CHECK_
file->update |= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
}
- thd->proc_info=old_proc_info;
+ thd_proc_info(thd, old_proc_info);
return error ? HA_ADMIN_CORRUPT : HA_ADMIN_OK;
}
@@ -1029,22 +1029,22 @@ int ha_myisam::repair(THD *thd, MI_CHECK
char buf[40];
/* TODO: respect myisam_repair_threads variable */
my_snprintf(buf, 40, "Repair with %d threads", my_count_bits(key_map));
- thd->proc_info=buf;
+ thd_proc_info(thd, buf);
error = mi_repair_parallel(¶m, file, fixed_name,
param.testflag & T_QUICK);
- thd->proc_info="Repair done"; // to reset proc_info, as
+ thd_proc_info(thd, "Repair done"); // to reset proc_info, as
// it was pointing to local buffer
}
else
{
- thd->proc_info="Repair by sorting";
+ thd_proc_info(thd, "Repair by sorting");
error = mi_repair_by_sort(¶m, file, fixed_name,
param.testflag & T_QUICK);
}
}
else
{
- thd->proc_info="Repair with keycache";
+ thd_proc_info(thd, "Repair with keycache");
param.testflag &= ~T_REP_BY_SORT;
error= mi_repair(¶m, file, fixed_name,
param.testflag & T_QUICK);
@@ -1058,7 +1058,7 @@ int ha_myisam::repair(THD *thd, MI_CHECK
(share->state.changed & STATE_NOT_SORTED_PAGES))
{
optimize_done=1;
- thd->proc_info="Sorting index";
+ thd_proc_info(thd, "Sorting index");
error=mi_sort_index(¶m,file,fixed_name);
}
if (!statistics_done && (local_testflag & T_STATISTICS))
@@ -1066,14 +1066,14 @@ int ha_myisam::repair(THD *thd, MI_CHECK
if (share->state.changed & STATE_NOT_ANALYZED)
{
optimize_done=1;
- thd->proc_info="Analyzing";
+ thd_proc_info(thd, "Analyzing");
error = chk_key(¶m, file);
}
else
local_testflag&= ~T_STATISTICS; // Don't update statistics
}
}
- thd->proc_info="Saving state";
+ thd_proc_info(thd, "Saving state");
if (!error)
{
if ((share->state.changed & STATE_CHANGED) || mi_is_crashed(file))
@@ -1111,7 +1111,7 @@ int ha_myisam::repair(THD *thd, MI_CHECK
file->update |= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
update_state_info(¶m, file, 0);
}
- thd->proc_info=old_proc_info;
+ thd_proc_info(thd, old_proc_info);
if (!thd->locked_tables)
mi_lock_database(file,F_UNLCK);
DBUG_RETURN(error ? HA_ADMIN_FAILED :
@@ -1336,7 +1336,7 @@ int ha_myisam::enable_indexes(uint mode)
THD *thd=current_thd;
MI_CHECK param;
const char *save_proc_info=thd->proc_info;
- thd->proc_info="Creating index";
+ thd_proc_info(thd, "Creating index");
myisamchk_init(¶m);
param.op_name= "recreating_index";
param.testflag= (T_SILENT | T_REP_BY_SORT | T_QUICK |
@@ -1361,7 +1361,7 @@ int ha_myisam::enable_indexes(uint mode)
thd->clear_error();
}
info(HA_STATUS_CONST);
- thd->proc_info=save_proc_info;
+ thd_proc_info(thd, save_proc_info);
}
else
{
--- 1.243/sql/item_cmpfunc.cc 2007-04-04 07:47:32 -04:00
+++ 1.244/sql/item_cmpfunc.cc 2007-04-26 09:44:16 -04:00
@@ -69,6 +69,42 @@ static void agg_result_type(Item_result
/*
+ Compare row signature of two expressions
+
+ SYNOPSIS:
+ cmp_row_type()
+ item1 the first expression
+ item2 the second expression
+
+ DESCRIPTION
+ The function checks that two expressions have compatible row signatures
+ i.e. that the number of columns they return are the same and that if they
+ are both row expressions then each component from the first expression has
+ a row signature compatible with the signature of the corresponding component
+ of the second expression.
+
+ RETURN VALUES
+ 1 type incompatibility has been detected
+ 0 otherwise
+*/
+
+static int cmp_row_type(Item* item1, Item* item2)
+{
+ uint n= item1->cols();
+ if (item2->check_cols(n))
+ return 1;
+ for (uint i=0; i<n; i++)
+ {
+ if (item2->element_index(i)->check_cols(item1->element_index(i)->cols()) ||
+ (item1->element_index(i)->result_type() == ROW_RESULT &&
+ cmp_row_type(item1->element_index(i), item2->element_index(i))))
+ return 1;
+ }
+ return 0;
+}
+
+
+/*
Aggregates result types from the array of items.
SYNOPSIS:
@@ -82,14 +118,32 @@ static void agg_result_type(Item_result
This function aggregates result types from the array of items. Found type
supposed to be used later for comparison of values of these items.
Aggregation itself is performed by the item_cmp_type() function.
+ The function also checks compatibility of row signatures for the
+ submitted items (see the spec for the cmp_row_type function).
+
+ RETURN VALUES
+ 1 type incompatibility has been detected
+ 0 otherwise
*/
-static void agg_cmp_type(THD *thd, Item_result *type, Item **items, uint nitems)
+static int agg_cmp_type(THD *thd, Item_result *type, Item **items, uint nitems)
{
uint i;
type[0]= items[0]->result_type();
for (i= 1 ; i < nitems ; i++)
+ {
type[0]= item_cmp_type(type[0], items[i]->result_type());
+ /*
+ When aggregating types of two row expressions we have to check
+ that they have the same cardinality and that each component
+ of the first row expression has a compatible row signature with
+ the signature of the corresponding component of the second row
+ expression.
+ */
+ if (type[0] == ROW_RESULT && cmp_row_type(items[0], items[i]))
+ return 1; // error found: invalid usage of rows
+ }
+ return 0;
}
@@ -1079,6 +1133,26 @@ longlong Item_func_strcmp::val_int()
}
+bool Item_func_opt_neg::eq(const Item *item, bool binary_cmp) const
+{
+ /* Assume we don't have rtti */
+ if (this == item)
+ return 1;
+ if (item->type() != FUNC_ITEM)
+ return 0;
+ Item_func *item_func=(Item_func*) item;
+ if (arg_count != item_func->arg_count ||
+ functype() != item_func->functype())
+ return 0;
+ if (negated != ((Item_func_opt_neg *) item_func)->negated)
+ return 0;
+ for (uint i=0; i < arg_count ; i++)
+ if (!args[i]->eq(item_func->arguments()[i], binary_cmp))
+ return 0;
+ return 1;
+}
+
+
void Item_func_interval::fix_length_and_dec()
{
use_decimal_comparison= (row->element_index(0)->result_type() == DECIMAL_RESULT) ||
@@ -1285,7 +1359,8 @@ void Item_func_between::fix_length_and_d
*/
if (!args[0] || !args[1] || !args[2])
return;
- agg_cmp_type(thd, &cmp_type, args, 3);
+ if ( agg_cmp_type(thd, &cmp_type, args, 3))
+ return;
if (cmp_type == STRING_RESULT &&
agg_arg_charsets(cmp_collation, args, 3, MY_COLL_CMP_CONV, 1))
return;
@@ -2001,7 +2076,8 @@ void Item_func_case::fix_length_and_dec(
for (nagg= 0; nagg < ncases/2 ; nagg++)
agg[nagg+1]= args[nagg*2];
nagg++;
- agg_cmp_type(thd, &cmp_type, agg, nagg);
+ if (agg_cmp_type(thd, &cmp_type, agg, nagg))
+ return;
if ((cmp_type == STRING_RESULT) &&
agg_arg_charsets(cmp_collation, agg, nagg, MY_COLL_CMP_CONV, 1))
return;
@@ -2690,7 +2766,8 @@ void Item_func_in::fix_length_and_dec()
uint const_itm= 1;
THD *thd= current_thd;
- agg_cmp_type(thd, &cmp_type, args, arg_count);
+ if (agg_cmp_type(thd, &cmp_type, args, arg_count))
+ return;
if (cmp_type == STRING_RESULT &&
agg_arg_charsets(cmp_collation, args, arg_count, MY_COLL_CMP_CONV, 1))
--- 1.330/sql/item_func.cc 2007-04-04 07:47:32 -04:00
+++ 1.331/sql/item_func.cc 2007-04-26 09:44:16 -04:00
@@ -230,6 +230,8 @@ void Item_func::traverse_cond(Cond_trave
(*traverser)(this, argument);
}
}
+ else
+ (*traverser)(this, argument);
}
@@ -4615,14 +4617,14 @@ void Item_func_match::init_search(bool n
fields.push_back(new Item_string(" ",1, cmp_collation.collation));
for (uint i=1; i < arg_count; i++)
fields.push_back(args[i]);
- concat=new Item_func_concat_ws(fields);
+ concat_ws=new Item_func_concat_ws(fields);
/*
Above function used only to get value and do not need fix_fields for it:
Item_string - basic constant
fields - fix_fields() was already called for this arguments
Item_func_concat_ws - do not need fix_fields() to produce value
*/
- concat->quick_fix_field();
+ concat_ws->quick_fix_field();
}
if (master)
@@ -4837,8 +4839,8 @@ double Item_func_match::val_real()
if (key == NO_SUCH_KEY)
{
- String *a= concat->val_str(&value);
- if ((null_value= (a == 0)))
+ String *a= concat_ws->val_str(&value);
+ if ((null_value= (a == 0)) || !a->length())
DBUG_RETURN(0);
DBUG_RETURN(ft_handler->please->find_relevance(ft_handler,
(byte *)a->ptr(), a->length()));
@@ -4996,10 +4998,10 @@ longlong Item_func_row_count::val_int()
}
-Item_func_sp::Item_func_sp(Name_resolution_context *context_arg,
- sp_name *name_arg)
- :Item_func(), context(context_arg), m_name(name_arg), m_sp(NULL),
- result_field(NULL)
+
+
+Item_func_sp::Item_func_sp(Name_resolution_context *context_arg, sp_name *name)
+ :Item_func(), context(context_arg), m_name(name), m_sp(NULL), sp_result_field(NULL)
{
maybe_null= 1;
m_name->init_qname(current_thd);
@@ -5008,22 +5010,22 @@ Item_func_sp::Item_func_sp(Name_resoluti
Item_func_sp::Item_func_sp(Name_resolution_context *context_arg,
- sp_name *name_arg, List<Item> &list)
- :Item_func(list), context(context_arg), m_name(name_arg), m_sp(NULL),
- result_field(NULL)
+ sp_name *name, List<Item> &list)
+ :Item_func(list), context(context_arg), m_name(name), m_sp(NULL),sp_result_field(NULL)
{
maybe_null= 1;
m_name->init_qname(current_thd);
dummy_table= (TABLE*) sql_calloc(sizeof(TABLE));
}
+
void
Item_func_sp::cleanup()
{
- if (result_field)
+ if (sp_result_field)
{
- delete result_field;
- result_field= NULL;
+ delete sp_result_field;
+ sp_result_field= NULL;
}
m_sp= NULL;
dummy_table->s= NULL;
@@ -5035,7 +5037,7 @@ Item_func_sp::func_name() const
{
THD *thd= current_thd;
/* Calculate length to avoid reallocation of string for sure */
- uint len= ((m_name->m_db.length +
+ uint len= ((m_name->m_explicit_name ? m_name->m_db.length : 0 +
m_name->m_name.length)*2 + //characters*quoting
2 + // ` and `
1 + // .
@@ -5045,89 +5047,127 @@ Item_func_sp::func_name() const
system_charset_info);
qname.length(0);
- append_identifier(thd, &qname, m_name->m_db.str, m_name->m_db.length);
- qname.append('.');
+ if (m_name->m_explicit_name)
+ {
+ append_identifier(thd, &qname, m_name->m_db.str, m_name->m_db.length);
+ qname.append('.');
+ }
append_identifier(thd, &qname, m_name->m_name.str, m_name->m_name.length);
return qname.ptr();
}
-Field *
-Item_func_sp::sp_result_field(void) const
+
+/**
+ @brief Initialize the result field by creating a temporary dummy table
+ and assign it to a newly created field object. Meta data used to
+ create the field is fetched from the sp_head belonging to the stored
+ proceedure found in the stored procedure functon cache.
+
+ @note This function should be called from fix_fields to init the result
+ field. It is some what related to Item_field.
+
+ @see Item_field
+
+ @param thd A pointer to the session and thread context.
+
+ @return Function return error status.
+ @retval TRUE is returned on an error
+ @retval FALSE is returned on success.
+*/
+bool
+Item_func_sp::init_result_field(THD *thd)
{
- Field *field;
- DBUG_ENTER("Item_func_sp::sp_result_field");
- DBUG_PRINT("info", ("sp: %s, flags: %x, level: %lu",
- (m_sp ? "YES" : "NO"),
- (m_sp ? m_sp->m_flags : (uint)0),
- (m_sp ? m_sp->m_recursion_level : (ulong)0)));
-
- if (!m_sp)
- {
- THD *thd= current_thd;
- if (!(m_sp= sp_find_routine(thd, TYPE_ENUM_FUNCTION, m_name,
- &thd->sp_func_cache, TRUE)))
- {
- my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname.str);
- DBUG_RETURN(0);
- }
+ DBUG_ENTER("Item_func_sp::init_result_field");
+
+ char *empty_name= (char *) "";
+ TABLE_SHARE *share;
+
+ DBUG_ASSERT(m_sp == NULL);
+ DBUG_ASSERT(sp_result_field == NULL);
+ DBUG_ASSERT(dummy_table->s == NULL);
+
+ if (!(m_sp= sp_find_routine(thd, TYPE_ENUM_FUNCTION, m_name,
+ &thd->sp_func_cache, TRUE)))
+ {
+ my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname.str);
+ context->process_error(thd);
+ DBUG_RETURN(TRUE);
}
- if (!dummy_table->s)
+
+ /*
+ A Field need to be attached to a Table.
+ Below we "create" a dummy table by initializing
+ the needed pointers.
+ */
+ dummy_table->s= share= &dummy_table->share_not_to_be_used;
+ dummy_table->alias = empty_name;
+ dummy_table->maybe_null = maybe_null;
+ dummy_table->in_use= thd;
+ dummy_table->copy_blobs= TRUE;
+ share->table_cache_key = empty_name;
+ share->table_name = empty_name;
+
+ if (!(sp_result_field= m_sp->create_result_field(max_length, name, dummy_table)))
{
- char *empty_name= (char *) "";
- TABLE_SHARE *share;
- dummy_table->s= share= &dummy_table->share_not_to_be_used;
- dummy_table->alias = empty_name;
- dummy_table->maybe_null = maybe_null;
- dummy_table->in_use= current_thd;
- dummy_table->copy_blobs= TRUE;
- share->table_cache_key = empty_name;
- share->table_name = empty_name;
+ DBUG_RETURN(TRUE);
}
- if (!(field= m_sp->create_result_field(max_length, name, dummy_table)))
- my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
+
+ if (sp_result_field->pack_length() > sizeof(result_buf))
+ {
+ sp_result_field->move_field(sql_alloc(sp_result_field->pack_length()));
+ } else {
+ sp_result_field->move_field(result_buf);
+ }
+
+ sp_result_field->null_ptr= (uchar *) &null_value;
+ sp_result_field->null_bit= 1;
+
- DBUG_RETURN(field);
+ DBUG_RETURN(FALSE);
}
+/**
+ @brief Initialize local members with values from the Field interface.
-/*
- Execute function & store value in field
+ @note called from Item::fix_fields.
+*/
+void Item_func_sp::fix_length_and_dec()
+{
+ DBUG_ENTER("Item_func_sp::fix_length_and_dec");
- RETURN
- 0 value <> NULL
- 1 value = NULL or error
+ DBUG_ASSERT(sp_result_field);
+ decimals= sp_result_field->decimals();
+ max_length= sp_result_field->field_length;
+ collation.set(sp_result_field->charset());
+ maybe_null= 1;
+ unsigned_flag= test(sp_result_field->flags & UNSIGNED_FLAG);
+
+ DBUG_VOID_RETURN;
+}
+
+/**
+ @brief Execute function & store value in field.
+
+ @return Function returns error status.
+ @retval FALSE on success.
+ @retval TRUE if an error occurred.
*/
bool
-Item_func_sp::execute(Field **flp)
+Item_func_sp::execute()
{
THD *thd= current_thd;
- Field *f;
-
+
/*
Get field in virtual tmp table to store result. Create the field if
invoked first time.
*/
-
- if (!(f= *flp))
- {
- if (!(*flp= f= sp_result_field()))
- {
- /* Error set by sp_result_field() */
- null_value= 1;
- return TRUE;
- }
- f->move_field((f->pack_length() > sizeof(result_buf)) ?
- sql_alloc(f->pack_length()) : result_buf);
- f->null_ptr= (uchar *)&null_value;
- f->null_bit= 1;
- }
/* Execute function and store the return value in the field. */
- if (execute_impl(thd, f))
+ if (execute_impl(thd))
{
null_value= 1;
context->process_error(thd);
@@ -5136,14 +5176,24 @@ Item_func_sp::execute(Field **flp)
/* Check that the field (the value) is not NULL. */
- null_value= f->is_null();
+ null_value= sp_result_field->is_null();
return null_value;
}
+/**
+ @brief Execute function and store the return value in the field.
+
+ @note This function was intended to be the concrete implementation of
+ the interface function execute. This was never realized.
+
+ @return The error state.
+ @retval FALSE on success
+ @retval TRUE if an error occurred.
+*/
bool
-Item_func_sp::execute_impl(THD *thd, Field *return_value_fld)
+Item_func_sp::execute_impl(THD *thd)
{
bool err_status= TRUE;
Sub_statement_state statement_state;
@@ -5160,7 +5210,7 @@ Item_func_sp::execute_impl(THD *thd, Fie
thd->security_ctx= context->security_ctx;
}
#endif
- if (find_and_check_access(thd))
+ if (sp_check_access(thd))
goto error;
/*
@@ -5169,7 +5219,7 @@ Item_func_sp::execute_impl(THD *thd, Fie
function call into binlog.
*/
thd->reset_sub_statement_state(&statement_state, SUB_STMT_FUNCTION);
- err_status= m_sp->execute_function(thd, args, arg_count, return_value_fld);
+ err_status= m_sp->execute_function(thd, args, arg_count, sp_result_field);
thd->restore_sub_statement_state(&statement_state);
error:
@@ -5184,15 +5234,9 @@ error:
void
Item_func_sp::make_field(Send_field *tmp_field)
{
- Field *field;
DBUG_ENTER("Item_func_sp::make_field");
- if ((field= sp_result_field()))
- {
- field->make_field(tmp_field);
- delete field;
- DBUG_VOID_RETURN;
- }
- init_make_field(tmp_field, MYSQL_TYPE_VARCHAR);
+ DBUG_ASSERT(sp_result_field);
+ sp_result_field->make_field(tmp_field);
DBUG_VOID_RETURN;
}
@@ -5200,67 +5244,20 @@ Item_func_sp::make_field(Send_field *tmp
enum enum_field_types
Item_func_sp::field_type() const
{
- Field *field;
DBUG_ENTER("Item_func_sp::field_type");
-
- if (result_field)
- DBUG_RETURN(result_field->type());
- if ((field= sp_result_field()))
- {
- enum_field_types result= field->type();
- delete field;
- DBUG_RETURN(result);
- }
- DBUG_RETURN(MYSQL_TYPE_VARCHAR);
+ DBUG_ASSERT(sp_result_field);
+ DBUG_RETURN(sp_result_field->type());
}
-
Item_result
Item_func_sp::result_type() const
{
- Field *field;
DBUG_ENTER("Item_func_sp::result_type");
DBUG_PRINT("info", ("m_sp = %p", m_sp));
-
- if (result_field)
- DBUG_RETURN(result_field->result_type());
- if ((field= sp_result_field()))
- {
- Item_result result= field->result_type();
- delete field;
- DBUG_RETURN(result);
- }
- DBUG_RETURN(STRING_RESULT);
+ DBUG_ASSERT(sp_result_field);
+ DBUG_RETURN(sp_result_field->result_type());
}
-void
-Item_func_sp::fix_length_and_dec()
-{
- Field *field;
- DBUG_ENTER("Item_func_sp::fix_length_and_dec");
-
- if (result_field)
- {
- decimals= result_field->decimals();
- max_length= result_field->field_length;
- collation.set(result_field->charset());
- DBUG_VOID_RETURN;
- }
-
- if (!(field= sp_result_field()))
- {
- context->process_error(current_thd);
- DBUG_VOID_RETURN;
- }
- decimals= field->decimals();
- max_length= field->field_length;
- collation.set(field->charset());
- maybe_null= 1;
- delete field;
- DBUG_VOID_RETURN;
-}
-
-
longlong Item_func_found_rows::val_int()
{
DBUG_ASSERT(fixed == 1);
@@ -5271,57 +5268,39 @@ longlong Item_func_found_rows::val_int()
Field *
Item_func_sp::tmp_table_field(TABLE *t_arg)
{
- Field *field= 0;
DBUG_ENTER("Item_func_sp::tmp_table_field");
- if (m_sp)
- field= m_sp->create_result_field(max_length, (const char*) name, t_arg);
-
- if (!field)
- field= Item_func::tmp_table_field(t_arg);
-
- if (!field)
- my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
-
- DBUG_RETURN(field);
+ DBUG_ASSERT(sp_result_field);
+ DBUG_RETURN(sp_result_field);
}
-/*
- Find the function and check access rights to the function
-
- SYNOPSIS
- find_and_check_access()
- thd thread handler
-
- RETURN
- FALSE Access granted
- TRUE Requested access can't be granted or function doesn't exists
-
- NOTES
- Checks if requested access to function can be granted to user.
+/**
+ @brief Checks if requested access to function can be granted to user.
If function isn't found yet, it searches function first.
If function can't be found or user don't have requested access
error is raised.
+
+ @param thd thread handler
+
+ @return Indication if the access was granted or not.
+ @retval FALSE Access is granted.
+ @retval TRUE Requested access can't be granted or function doesn't exists.
+
*/
bool
-Item_func_sp::find_and_check_access(THD *thd)
+Item_func_sp::sp_check_access(THD *thd)
{
- if (! m_sp && ! (m_sp= sp_find_routine(thd, TYPE_ENUM_FUNCTION, m_name,
- &thd->sp_func_cache, TRUE)))
- {
- my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname.str);
- return TRUE;
- }
-
+ DBUG_ENTER("Item_func_sp::sp_check_access");
+ DBUG_ASSERT(m_sp);
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (check_routine_access(thd, EXECUTE_ACL,
m_sp->m_db.str, m_sp->m_name.str, 0, FALSE))
- return TRUE;
+ DBUG_RETURN(TRUE);
#endif
- return FALSE;
+ DBUG_RETURN(FALSE);
}
@@ -5329,9 +5308,25 @@ bool
Item_func_sp::fix_fields(THD *thd, Item **ref)
{
bool res;
+ DBUG_ENTER("Item_func_sp::fix_fields");
DBUG_ASSERT(fixed == 0);
+
+ /*
+ We must call init_result_field before Item_func::fix_fields()
+ to make m_sp and result_field members available to fix_length_and_dec(),
+ which is called from Item_func::fix_fields().
+ */
+ res= init_result_field(thd);
+
+ if (res)
+ DBUG_RETURN(res);
+
res= Item_func::fix_fields(thd, ref);
- if (!res && thd->lex->view_prepare_mode)
+
+ if (res)
+ DBUG_RETURN(res);
+
+ if (thd->lex->view_prepare_mode)
{
/*
Here we check privileges of the stored routine only during view
@@ -5343,15 +5338,17 @@ Item_func_sp::fix_fields(THD *thd, Item
good idea especially if the view has SQL SECURITY DEFINER and
the used stored procedure has SQL SECURITY DEFINER.
*/
- res= find_and_check_access(thd);
+ res= sp_check_access(thd);
#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ /*
+ Try to set and restore the security context to see whether it's valid
+ */
Security_context *save_secutiry_ctx;
- if (!res && !(res= set_routine_security_ctx(thd, m_sp, false,
- &save_secutiry_ctx)))
- {
+ res= set_routine_security_ctx(thd, m_sp, false, &save_secutiry_ctx);
+ if (!res)
sp_restore_security_context(thd, save_secutiry_ctx);
- }
+
#endif /* ! NO_EMBEDDED_ACCESS_CHECKS */
}
- return res;
+ DBUG_RETURN(res);
}
--- 1.96/sql/lock.cc 2007-04-04 07:47:32 -04:00
+++ 1.97/sql/lock.cc 2007-04-26 09:44:16 -04:00
@@ -544,7 +544,7 @@ TABLE_LIST *mysql_lock_have_duplicate(TH
goto end;
/* A temporary table does not have locks. */
- if (table->s->tmp_table == TMP_TABLE)
+ if (table->s->tmp_table == NON_TRANSACTIONAL_TMP_TABLE)
goto end;
/* Get command lock or LOCK TABLES lock. Maybe empty for INSERT DELAYED. */
@@ -569,7 +569,7 @@ TABLE_LIST *mysql_lock_have_duplicate(TH
if (haystack->placeholder())
continue;
table2= haystack->table;
- if (table2->s->tmp_table == TMP_TABLE)
+ if (table2->s->tmp_table == NON_TRANSACTIONAL_TMP_TABLE)
continue;
/* All tables in list must be in lock. */
@@ -655,7 +655,7 @@ static MYSQL_LOCK *get_lock_data(THD *th
*write_lock_used=0;
for (i=tables=lock_count=0 ; i < count ; i++)
{
- if (table_ptr[i]->s->tmp_table != TMP_TABLE)
+ if (table_ptr[i]->s->tmp_table != NON_TRANSACTIONAL_TMP_TABLE)
{
tables+=table_ptr[i]->file->lock_count();
lock_count++;
@@ -697,7 +697,7 @@ static MYSQL_LOCK *get_lock_data(THD *th
TABLE *table;
enum thr_lock_type lock_type;
- if ((table=table_ptr[i])->s->tmp_table == TMP_TABLE)
+ if ((table=table_ptr[i])->s->tmp_table == NON_TRANSACTIONAL_TMP_TABLE)
continue;
lock_type= table->reginfo.lock_type;
if (lock_type >= TL_WRITE_ALLOW_WRITE)
--- 1.231/sql/log_event.cc 2007-04-04 07:47:32 -04:00
+++ 1.232/sql/log_event.cc 2007-04-26 09:44:16 -04:00
@@ -669,19 +669,34 @@ int Log_event::read_log_event(IO_CACHE*
LOG_READ_TOO_LARGE);
goto end;
}
- packet->append(buf, sizeof(buf));
+
+ /* Append the log event header to packet */
+ if (packet->append(buf, sizeof(buf)))
+ {
+ /* Failed to allocate packet */
+ result= LOG_READ_MEM;
+ goto end;
+ }
data_len-= LOG_EVENT_MINIMAL_HEADER_LEN;
if (data_len)
{
+ /* Append rest of event, read directly from file into packet */
if (packet->append(file, data_len))
{
/*
- Here if we hit EOF it's really an error: as data_len is >=0
- there's supposed to be more bytes available.
- EOF means we are reading the event partially, which should
- never happen: either we read badly or the binlog is truncated.
+ Fatal error occured when appending rest of the event
+ to packet, possible failures:
+ 1. EOF occured when reading from file, it's really an error
+ as data_len is >=0 there's supposed to be more bytes available.
+ file->error will have been set to number of bytes left to read
+ 2. Read was interrupted, file->error would normally be set to -1
+ 3. Failed to allocate memory for packet, my_errno
+ will be ENOMEM(file->error shuold be 0, but since the
+ memory allocation occurs before the call to read it might
+ be uninitialized)
*/
- result= file->error >= 0 ? LOG_READ_TRUNC: LOG_READ_IO;
+ result= (my_errno == ENOMEM ? LOG_READ_MEM :
+ (file->error >= 0 ? LOG_READ_TRUNC: LOG_READ_IO));
/* Implicit goto end; */
}
}
--- 1.442/sql/mysql_priv.h 2007-04-04 07:47:32 -04:00
+++ 1.443/sql/mysql_priv.h 2007-04-26 09:44:17 -04:00
@@ -850,6 +850,8 @@ bool mysql_insert(THD *thd,TABLE_LIST *t
bool ignore);
int check_that_all_fields_are_given_values(THD *thd, TABLE *entry,
TABLE_LIST *table_list);
+void prepare_triggers_for_insert_stmt(THD *thd, TABLE *table,
+ enum_duplicates duplic);
void mark_fields_used_by_triggers_for_insert_stmt(THD *thd, TABLE *table,
enum_duplicates duplic);
bool mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds);
--- 1.600/sql/mysqld.cc 2007-04-04 07:47:32 -04:00
+++ 1.601/sql/mysqld.cc 2007-04-26 09:44:17 -04:00
@@ -2238,14 +2238,13 @@ static void init_signals(void)
#ifdef SIGTSTP
sigaddset(&set,SIGTSTP);
#endif
- sigaddset(&set,THR_SERVER_ALARM);
+ if (thd_lib_detected != THD_LIB_LT)
+ sigaddset(&set,THR_SERVER_ALARM);
if (test_flags & TEST_SIGINT)
{
// May be SIGINT
sigdelset(&set, thr_kill_signal);
}
- // For alarms
- sigdelset(&set, thr_client_alarm);
sigprocmask(SIG_SETMASK,&set,NULL);
pthread_sigmask(SIG_SETMASK,&set,NULL);
DBUG_VOID_RETURN;
@@ -3427,7 +3426,7 @@ int main(int argc, char **argv)
#else
thr_kill_signal= SIGINT;
#endif
-
+
#ifdef _CUSTOMSTARTUPCONFIG_
if (_cust_check_startup())
{
@@ -6133,12 +6132,12 @@ The minimum value for this variable is 4
(gptr*) &max_system_variables.tmp_table_size, 0, GET_ULL,
REQUIRED_ARG, 32*1024*1024L, 1024, MAX_MEM_TABLE_SIZE, 0, 1, 0},
{"transaction_alloc_block_size", OPT_TRANS_ALLOC_BLOCK_SIZE,
- "Allocation block size for transactions to be stored in binary log",
+ "Allocation block size for various transaction-related structures",
(gptr*) &global_system_variables.trans_alloc_block_size,
(gptr*) &max_system_variables.trans_alloc_block_size, 0, GET_ULONG,
REQUIRED_ARG, QUERY_ALLOC_BLOCK_SIZE, 1024, ~0L, 0, 1024, 0},
{"transaction_prealloc_size", OPT_TRANS_PREALLOC_SIZE,
- "Persistent buffer for transactions to be stored in binary log",
+ "Persistent buffer for various transaction-related structures",
(gptr*) &global_system_variables.trans_prealloc_size,
(gptr*) &max_system_variables.trans_prealloc_size, 0, GET_ULONG,
REQUIRED_ARG, TRANS_ALLOC_PREALLOC_SIZE, 1024, ~0L, 0, 1024, 0},
--- 1.366/sql/sql_base.cc 2007-04-04 07:47:33 -04:00
+++ 1.367/sql/sql_base.cc 2007-04-26 09:44:17 -04:00
@@ -1640,6 +1640,9 @@ TABLE *open_table(THD *thd, TABLE_LIST *
table->used_keys= table->s->keys_for_keyread;
table->fulltext_searched= 0;
table->file->ft_handler= 0;
+ /* Catch wrong handling of the auto_increment_field_not_null. */
+ DBUG_ASSERT(!table->auto_increment_field_not_null);
+ table->auto_increment_field_not_null= FALSE;
if (table->timestamp_field)
table->timestamp_field_type= table->timestamp_field->get_auto_set_type();
table->pos_in_table_list= table_list;
@@ -2950,7 +2953,7 @@ TABLE *open_temporary_table(THD *thd, co
share= tmp_table->s;
tmp_table->reginfo.lock_type=TL_WRITE; // Simulate locked
share->tmp_table= (tmp_table->file->has_transactions() ?
- TRANSACTIONAL_TMP_TABLE : TMP_TABLE);
+ TRANSACTIONAL_TMP_TABLE : NON_TRANSACTIONAL_TMP_TABLE);
share->table_cache_key= (char*) (tmp_table+1);
share->db= share->table_cache_key;
share->key_length= (uint) (strmov(((char*) (share->table_name=
@@ -4865,7 +4868,6 @@ bool setup_tables_and_check_access(THD *
TABLE_LIST *leaves_tmp = NULL;
bool first_table= true;
- thd->leaf_count= 0;
if (setup_tables (thd, context, from_clause, tables, conds,
&leaves_tmp, select_insert))
return TRUE;
@@ -4883,7 +4885,6 @@ bool setup_tables_and_check_access(THD *
return TRUE;
}
first_table= false;
- thd->leaf_count++;
}
return FALSE;
}
@@ -5274,6 +5275,11 @@ err_no_arena:
values values to fill with
ignore_errors TRUE if we should ignore errors
+ NOTE
+ fill_record() may set table->auto_increment_field_not_null and a
+ caller should make sure that it is reset after their last call to this
+ function.
+
RETURN
FALSE OK
TRUE error occured
@@ -5286,27 +5292,52 @@ fill_record(THD * thd, List<Item> &field
List_iterator_fast<Item> f(fields),v(values);
Item *value, *fld;
Item_field *field;
+ TABLE *table= 0;
DBUG_ENTER("fill_record");
+ /*
+ Reset the table->auto_increment_field_not_null as it is valid for
+ only one row.
+ */
+ if (fields.elements)
+ {
+ /*
+ On INSERT or UPDATE fields are checked to be from the same table,
+ thus we safely can take table from the first field.
+ */
+ fld= (Item_field*)f++;
+ if (!(field= fld->filed_for_view_update()))
+ {
+ my_error(ER_NONUPDATEABLE_COLUMN, MYF(0), fld->name);
+ goto err;
+ }
+ table= field->field->table;
+ table->auto_increment_field_not_null= FALSE;
+ f.rewind();
+ }
while ((fld= f++))
{
if (!(field= fld->filed_for_view_update()))
{
my_error(ER_NONUPDATEABLE_COLUMN, MYF(0), fld->name);
- DBUG_RETURN(TRUE);
+ goto err;
}
value=v++;
Field *rfield= field->field;
- TABLE *table= rfield->table;
+ table= rfield->table;
if (rfield == table->next_number_field)
table->auto_increment_field_not_null= TRUE;
if ((value->save_in_field(rfield, 0) < 0) && !ignore_errors)
{
my_message(ER_UNKNOWN_ERROR, ER(ER_UNKNOWN_ERROR), MYF(0));
- DBUG_RETURN(TRUE);
+ goto err;
}
}
DBUG_RETURN(thd->net.report_error);
+err:
+ if (table)
+ table->auto_increment_field_not_null= FALSE;
+ DBUG_RETURN(TRUE);
}
@@ -5355,6 +5386,11 @@ fill_record_n_invoke_before_triggers(THD
values list of fields
ignore_errors TRUE if we should ignore errors
+ NOTE
+ fill_record() may set table->auto_increment_field_not_null and a
+ caller should make sure that it is reset after their last call to this
+ function.
+
RETURN
FALSE OK
TRUE error occured
@@ -5365,19 +5401,38 @@ fill_record(THD *thd, Field **ptr, List<
{
List_iterator_fast<Item> v(values);
Item *value;
+ TABLE *table= 0;
DBUG_ENTER("fill_record");
Field *field;
+ /*
+ Reset the table->auto_increment_field_not_null as it is valid for
+ only one row.
+ */
+ if (*ptr)
+ {
+ /*
+ On INSERT or UPDATE fields are checked to be from the same table,
+ thus we safely can take table from the first field.
+ */
+ table= (*ptr)->table;
+ table->auto_increment_field_not_null= FALSE;
+ }
while ((field = *ptr++))
{
value=v++;
- TABLE *table= field->table;
+ table= field->table;
if (field == table->next_number_field)
table->auto_increment_field_not_null= TRUE;
if (value->save_in_field(field, 0) == -1)
- DBUG_RETURN(TRUE);
+ goto err;
}
DBUG_RETURN(thd->net.report_error);
+
+err:
+ if (table)
+ table->auto_increment_field_not_null= FALSE;
+ DBUG_RETURN(TRUE);
}
--- 1.261/sql/sql_class.cc 2007-04-04 07:47:33 -04:00
+++ 1.262/sql/sql_class.cc 2007-04-26 09:44:17 -04:00
@@ -616,6 +616,18 @@ void THD::cleanup_after_query()
clear_next_insert_id= 0;
next_insert_id= 0;
}
+ /*
+ Reset rand_used so that detection of calls to rand() will save random
+ seeds if needed by the slave.
+
+ Do not reset rand_used if inside a stored function or trigger because
+ only the call to these operations is logged. Thus only the calling
+ statement needs to detect rand() calls made by its substatements. These
+ substatements must not set rand_used to 0 because it would remove the
+ detection of rand() by the calling statement.
+ */
+ if (!in_sub_stmt)
+ rand_used= 0;
/* Free Items that were created during this execution */
free_items();
/* Reset where. */
--- 1.319/sql/sql_class.h 2007-04-04 07:47:33 -04:00
+++ 1.320/sql/sql_class.h 2007-04-26 09:44:17 -04:00
@@ -1500,9 +1500,6 @@ public:
query_id_t first_query_id;
} binlog_evt_union;
- /* pass up the count of "leaf" tables in a JOIN out of setup_tables() */
- byte leaf_count;
-
THD();
~THD();
--- 1.193/sql/sql_delete.cc 2007-04-04 07:47:33 -04:00
+++ 1.194/sql/sql_delete.cc 2007-04-26 09:44:18 -04:00
@@ -60,6 +60,27 @@ bool mysql_delete(THD *thd, TABLE_LIST *
if (mysql_prepare_delete(thd, table_list, &conds))
DBUG_RETURN(TRUE);
+ /* check ORDER BY even if it can be ignored */
+ if (order && order->elements)
+ {
+ TABLE_LIST tables;
+ List<Item> fields;
+ List<Item> all_fields;
+
+ bzero((char*) &tables,sizeof(tables));
+ tables.table = table;
+ tables.alias = table_list->alias;
+
+ if (select_lex->setup_ref_array(thd, order->elements) ||
+ setup_order(thd, select_lex->ref_pointer_array, &tables,
+ fields, all_fields, (ORDER*) order->first))
+ {
+ delete select;
+ free_underlaid_joins(thd, &thd->lex->select_lex);
+ DBUG_RETURN(TRUE);
+ }
+ }
+
const_cond= (!conds || conds->const_item());
safe_update=test(thd->options & OPTION_SAFE_UPDATES);
if (safe_update && const_cond)
@@ -148,23 +169,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *
{
uint length= 0;
SORT_FIELD *sortorder;
- TABLE_LIST tables;
- List<Item> fields;
- List<Item> all_fields;
ha_rows examined_rows;
-
- bzero((char*) &tables,sizeof(tables));
- tables.table = table;
- tables.alias = table_list->alias;
-
- if (select_lex->setup_ref_array(thd, order->elements) ||
- setup_order(thd, select_lex->ref_pointer_array, &tables,
- fields, all_fields, (ORDER*) order->first))
- {
- delete select;
- free_underlaid_joins(thd, &thd->lex->select_lex);
- DBUG_RETURN(TRUE);
- }
if ((!select || table->quick_keys.is_clear_all()) && limit != HA_POS_ERROR)
usable_index= get_index_for_order(table, (ORDER*)(order->first), limit);
@@ -212,7 +217,19 @@ bool mysql_delete(THD *thd, TABLE_LIST *
thd_proc_info(thd, "updating");
if (table->triggers)
+ {
table->triggers->mark_fields_used(thd, TRG_EVENT_DELETE);
+ if (table->triggers->has_triggers(TRG_EVENT_DELETE,
+ TRG_ACTION_AFTER))
+ {
+ /*
+ The table has AFTER DELETE triggers that might access to subject table
+ and therefore might need delete to be done immediately. So we turn-off
+ the batching.
+ */
+ (void) table->file->extra(HA_EXTRA_DELETE_CANNOT_BATCH);
+ }
+ }
while (!(error=info.read_record(&info)) && !thd->killed &&
!thd->net.report_error)
@@ -535,7 +552,19 @@ multi_delete::initialize_tables(JOIN *jo
else
normal_tables= 1;
if (tbl->triggers)
+ {
tbl->triggers->mark_fields_used(thd, TRG_EVENT_DELETE);
+ if (tbl->triggers->has_triggers(TRG_EVENT_DELETE,
+ TRG_ACTION_AFTER))
+ {
+ /*
+ The table has AFTER DELETE triggers that might access to subject
+ table and therefore might need delete to be done immediately.
+ So we turn-off the batching.
+ */
+ (void) tbl->file->extra(HA_EXTRA_DELETE_CANNOT_BATCH);
+ }
+ }
}
else if ((tab->type != JT_SYSTEM && tab->type != JT_CONST) &&
walk == delete_tables)
--- 1.216/sql/sql_insert.cc 2007-04-04 07:47:33 -04:00
+++ 1.217/sql/sql_insert.cc 2007-04-26 09:44:18 -04:00
@@ -330,6 +330,51 @@ static int check_update_fields(THD *thd,
/*
+ Prepare triggers for INSERT-like statement.
+
+ SYNOPSIS
+ prepare_triggers_for_insert_stmt()
+ thd The current thread
+ table Table to which insert will happen
+ duplic Type of duplicate handling for insert which will happen
+
+ NOTE
+ Prepare triggers for INSERT-like statement by marking fields
+ used by triggers and inform handlers that batching of UPDATE/DELETE
+ cannot be done if there are BEFORE UPDATE/DELETE triggers.
+*/
+
+void prepare_triggers_for_insert_stmt(THD *thd, TABLE *table,
+ enum_duplicates duplic)
+{
+ if (table->triggers)
+ {
+ if (table->triggers->has_triggers(TRG_EVENT_DELETE,
+ TRG_ACTION_AFTER))
+ {
+ /*
+ The table has AFTER DELETE triggers that might access to
+ subject table and therefore might need delete to be done
+ immediately. So we turn-off the batching.
+ */
+ (void) table->file->extra(HA_EXTRA_DELETE_CANNOT_BATCH);
+ }
+ if (table->triggers->has_triggers(TRG_EVENT_UPDATE,
+ TRG_ACTION_AFTER))
+ {
+ /*
+ The table has AFTER UPDATE triggers that might access to subject
+ table and therefore might need update to be done immediately.
+ So we turn-off the batching.
+ */
+ (void) table->file->extra(HA_EXTRA_UPDATE_CANNOT_BATCH);
+ }
+ mark_fields_used_by_triggers_for_insert_stmt(thd, table, duplic);
+ }
+}
+
+
+/*
Mark fields used by triggers for INSERT-like statement.
SYNOPSIS
@@ -589,7 +634,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *t
(MODE_STRICT_TRANS_TABLES |
MODE_STRICT_ALL_TABLES)));
- mark_fields_used_by_triggers_for_insert_stmt(thd, table, duplic);
+ prepare_triggers_for_insert_stmt(thd, table, duplic);
if (table_list->prepare_where(thd, 0, TRUE) ||
table_list->prepare_check_option(thd))
@@ -757,6 +802,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *t
table->next_number_field=0;
thd->count_cuted_fields= CHECK_FIELD_IGNORE;
thd->next_insert_id=0; // Reset this if wrongly used
+ table->auto_increment_field_not_null= FALSE;
if (duplic != DUP_ERROR || ignore)
table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
if (duplic == DUP_REPLACE &&
@@ -2349,14 +2395,12 @@ bool mysql_insert_select_prepare(THD *th
DBUG_ASSERT(select_lex->leaf_tables != 0);
lex->leaf_tables_insert= select_lex->leaf_tables;
/* skip all leaf tables belonged to view where we are insert */
- for (first_select_leaf_table= select_lex->leaf_tables->next_leaf,
- thd->leaf_count --;
+ for (first_select_leaf_table= select_lex->leaf_tables->next_leaf;
first_select_leaf_table &&
first_select_leaf_table->belong_to_view &&
first_select_leaf_table->belong_to_view ==
lex->leaf_tables_insert->belong_to_view;
- first_select_leaf_table= first_select_leaf_table->next_leaf,
- thd->leaf_count --)
+ first_select_leaf_table= first_select_leaf_table->next_leaf)
{}
select_lex->leaf_tables= first_select_leaf_table;
DBUG_RETURN(FALSE);
@@ -2529,8 +2573,8 @@ select_insert::prepare(List<Item> &value
table_list->prepare_check_option(thd));
if (!res)
- mark_fields_used_by_triggers_for_insert_stmt(thd, table,
- info.handle_duplicates);
+ prepare_triggers_for_insert_stmt(thd, table,
+ info.handle_duplicates);
DBUG_RETURN(res);
}
@@ -2573,6 +2617,7 @@ select_insert::~select_insert()
if (table)
{
table->next_number_field=0;
+ table->auto_increment_field_not_null= FALSE;
table->file->reset();
}
thd->count_cuted_fields= CHECK_FIELD_IGNORE;
--- 1.509/sql/sql_select.cc 2007-04-15 00:34:13 -04:00
+++ 1.510/sql/sql_select.cc 2007-04-26 09:44:18 -04:00
@@ -742,6 +742,7 @@ JOIN::optimize()
if (thd->lex->orig_sql_command != SQLCOM_SHOW_STATUS)
thd->status_var.last_query_cost= 0.0;
+ thd_proc_info(thd, "optimizing");
row_limit= ((select_distinct || order || group_list) ? HA_POS_ERROR :
unit->select_limit_cnt);
/* select_limit is used to decide if we are likely to scan the whole table */
@@ -857,7 +858,14 @@ JOIN::optimize()
thd->fatal_error();
error= res;
DBUG_PRINT("error",("Error from opt_sum_query"));
- DBUG_RETURN(1);
+ DBUG_RETURN(1);
+ }
+ if (res < 0)
+ {
+ DBUG_PRINT("info",("No matching min/max row"));
+ zero_result_cause= "No matching min/max row";
+ error=0;
+ DBUG_RETURN(0);
}
DBUG_PRINT("info",("Select tables optimized away"));
zero_result_cause= "Select tables optimized away";
@@ -893,7 +901,7 @@ JOIN::optimize()
sort_by_table= get_sort_by_table(order, group_list, select_lex->leaf_tables);
/* Calculate how to do the join */
- thd->proc_info= "statistics";
+ thd_proc_info(thd, "statistics");
if (make_join_statistics(this, select_lex->leaf_tables, conds, &keyuse) ||
thd->is_fatal_error)
{
@@ -903,7 +911,7 @@ JOIN::optimize()
/* Remove distinct if only const tables */
select_distinct= select_distinct && (const_tables != tables);
- thd->proc_info= "preparing";
+ thd_proc_info(thd, "preparing");
if (result->initialize_tables(this))
{
DBUG_PRINT("error",("Error: initialize_tables() failed"));
@@ -1267,8 +1275,9 @@ JOIN::optimize()
join_tab[const_tables].type != JT_REF_OR_NULL &&
(order && simple_order || group_list && simple_group))
{
- if (add_ref_to_table_cond(thd,&join_tab[const_tables]))
+ if (add_ref_to_table_cond(thd,&join_tab[const_tables])) {
DBUG_RETURN(1);
+ }
}
if (!(select_options & SELECT_BIG_RESULT) &&
@@ -1326,7 +1335,7 @@ JOIN::optimize()
if (need_tmp)
{
DBUG_PRINT("info",("Creating tmp table"));
- thd->proc_info="Creating tmp table";
+ thd_proc_info(thd, "Creating tmp table");
init_items_ref_array();
@@ -1355,7 +1364,9 @@ JOIN::optimize()
select_options,
tmp_rows_limit,
(char *) "")))
+ {
DBUG_RETURN(1);
+ }
/*
We don't have to store rows in temp table that doesn't match HAVING if:
@@ -1375,28 +1386,34 @@ JOIN::optimize()
if (group_list && simple_group)
{
DBUG_PRINT("info",("Sorting for group"));
- thd->proc_info="Sorting for group";
+ thd_proc_info(thd, "Sorting for group");
if (create_sort_index(thd, this, group_list,
HA_POS_ERROR, HA_POS_ERROR) ||
alloc_group_fields(this, group_list) ||
make_sum_func_list(all_fields, fields_list, 1) ||
setup_sum_funcs(thd, sum_funcs))
- DBUG_RETURN(1);
+ {
+ DBUG_RETURN(1);
+ }
group_list=0;
}
else
{
if (make_sum_func_list(all_fields, fields_list, 0) ||
setup_sum_funcs(thd, sum_funcs))
- DBUG_RETURN(1);
+ {
+ DBUG_RETURN(1);
+ }
+
if (!group_list && ! exec_tmp_table1->distinct && order && simple_order)
{
- DBUG_PRINT("info",("Sorting for order"));
- thd->proc_info="Sorting for order";
- if (create_sort_index(thd, this, order,
+ thd_proc_info(thd, "Sorting for order");
+ if (create_sort_index(thd, this, order,
HA_POS_ERROR, HA_POS_ERROR))
- DBUG_RETURN(1);
- order=0;
+ {
+ DBUG_RETURN(1);
+ }
+ order=0;
}
}
@@ -1519,6 +1536,7 @@ JOIN::exec()
int tmp_error;
DBUG_ENTER("JOIN::exec");
+ thd_proc_info(thd, "executing");
error= 0;
if (procedure)
{
@@ -1658,7 +1676,7 @@ JOIN::exec()
curr_tmp_table= exec_tmp_table1;
/* Copy data to the temporary table */
- thd->proc_info= "Copying to tmp table";
+ thd_proc_info(thd, "Copying to tmp table");
DBUG_PRINT("info", ("%s", thd->proc_info));
if ((tmp_error= do_select(curr_join, (List<Item> *) 0, curr_tmp_table, 0)))
{
@@ -1781,7 +1799,7 @@ JOIN::exec()
}
if (curr_join->group_list)
{
- thd->proc_info= "Creating sort index";
+ thd_proc_info(thd, "Creating sort index");
if (curr_join->join_tab == join_tab && save_join_tab())
{
DBUG_VOID_RETURN;
@@ -1795,7 +1813,7 @@ JOIN::exec()
sortorder= curr_join->sortorder;
}
- thd->proc_info="Copying to group table";
+ thd_proc_info(thd, "Copying to group table");
DBUG_PRINT("info", ("%s", thd->proc_info));
tmp_error= -1;
if (curr_join != this)
@@ -1851,7 +1869,7 @@ JOIN::exec()
curr_join->join_free(); /* Free quick selects */
if (curr_join->select_distinct && ! curr_join->group_list)
{
- thd->proc_info="Removing duplicates";
+ thd_proc_info(thd, "Removing duplicates");
if (curr_join->tmp_having)
curr_join->tmp_having->update_used_tables();
if (remove_duplicates(curr_join, curr_tmp_table,
@@ -1912,7 +1930,7 @@ JOIN::exec()
if (curr_join->group_list || curr_join->order)
{
DBUG_PRINT("info",("Sorting for send_fields"));
- thd->proc_info="Sorting result";
+ thd_proc_info(thd, "Sorting result");
/* If we have already done the group, add HAVING to sorted table */
if (curr_join->tmp_having && ! curr_join->group_list &&
! curr_join->sort_and_group)
@@ -2036,7 +2054,7 @@ JOIN::exec()
}
else
{
- thd->proc_info="Sending data";
+ thd_proc_info(thd, "Sending data");
DBUG_PRINT("info", ("%s", thd->proc_info));
result->send_fields((procedure ? curr_join->procedure_fields_list :
*curr_fields_list),
@@ -2184,7 +2202,7 @@ mysql_select(THD *thd, Item ***rref_poin
{
if (!(join= new JOIN(thd, fields, select_options, result)))
DBUG_RETURN(TRUE);
- thd->proc_info="init";
+ thd_proc_info(thd, "init");
thd->used_tables=0; // Updated by setup_fields
if (err= join->prepare(rref_pointer_array, tables, wild_num,
conds, og_num, order, group, having, proc_param,
@@ -2229,8 +2247,9 @@ mysql_select(THD *thd, Item ***rref_poin
err:
if (free_join)
{
- thd->proc_info="end";
+ thd_proc_info(thd, "end");
err|= select_lex->cleanup();
+ thd_proc_info(thd, "end");
DBUG_RETURN(err || thd->net.report_error);
}
DBUG_RETURN(join->error);
@@ -10001,7 +10020,7 @@ free_tmp_table(THD *thd, TABLE *entry)
DBUG_PRINT("enter",("table: %s",entry->alias));
save_proc_info=thd->proc_info;
- thd->proc_info="removing tmp table";
+ thd_proc_info(thd, "removing tmp table");
if (entry->file)
{
@@ -10029,7 +10048,7 @@ free_tmp_table(THD *thd, TABLE *entry)
bitmap_clear_bit(&temp_pool, entry->temp_pool_slot);
free_root(&own_root, MYF(0)); /* the table is allocated in its own root */
- thd->proc_info=save_proc_info;
+ thd_proc_info(thd, save_proc_info);
DBUG_VOID_RETURN;
}
@@ -10059,7 +10078,7 @@ bool create_myisam_from_heap(THD *thd, T
DBUG_RETURN(1); // End of memory
save_proc_info=thd->proc_info;
- thd->proc_info="converting HEAP to MyISAM";
+ thd_proc_info(thd, "converting HEAP to MyISAM");
if (create_myisam_tmp_table(&new_table,param,
thd->lex->select_lex.options | thd->options))
@@ -10112,8 +10131,8 @@ bool create_myisam_from_heap(THD *thd, T
table->s= &table->share_not_to_be_used;
table->file->change_table_ptr(table);
if (save_proc_info)
- thd->proc_info= (!strcmp(save_proc_info,"Copying to tmp table") ?
- "Copying to tmp table on disk" : save_proc_info);
+ thd_proc_info(thd, (!strcmp(save_proc_info,"Copying to tmp table") ?
+ "Copying to tmp table on disk" : save_proc_info));
DBUG_RETURN(0);
err:
@@ -10125,7 +10144,7 @@ bool create_myisam_from_heap(THD *thd, T
new_table.file->delete_table(new_table.s->table_name);
delete new_table.file;
err2:
- thd->proc_info=save_proc_info;
+ thd_proc_info(thd, save_proc_info);
DBUG_RETURN(1);
}
--- 1.337/sql/sql_table.cc 2007-04-04 07:47:34 -04:00
+++ 1.338/sql/sql_table.cc 2007-04-26 09:44:18 -04:00
@@ -407,22 +407,25 @@ static int sort_keys(KEY *a, KEY *b)
set_or_name "SET" or "ENUM" string for warning message
name name of the checked column
typelib list of values for the column
+ dup_val_count returns count of duplicate elements
DESCRIPTION
This function prints an warning for each value in list
which has some duplicates on its right
RETURN VALUES
- void
+ 0 ok
+ 1 Error
*/
-void check_duplicates_in_interval(const char *set_or_name,
+bool check_duplicates_in_interval(const char *set_or_name,
const char *name, TYPELIB *typelib,
- CHARSET_INFO *cs)
+ CHARSET_INFO *cs, unsigned int *dup_val_count)
{
TYPELIB tmp= *typelib;
const char **cur_value= typelib->type_names;
unsigned int *cur_length= typelib->type_lengths;
+ *dup_val_count= 0;
for ( ; tmp.count > 1; cur_value++, cur_length++)
{
@@ -431,12 +434,21 @@ void check_duplicates_in_interval(const
tmp.count--;
if (find_type2(&tmp, (const char*)*cur_value, *cur_length, cs))
{
+ if ((current_thd->variables.sql_mode &
+ (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES)))
+ {
+ my_error(ER_DUPLICATED_VALUE_IN_TYPE, MYF(0),
+ name,*cur_value,set_or_name);
+ return 1;
+ }
push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_DUPLICATED_VALUE_IN_TYPE,
ER(ER_DUPLICATED_VALUE_IN_TYPE),
name,*cur_value,set_or_name);
+ (*dup_val_count)++;
}
}
+ return 0;
}
@@ -498,6 +510,7 @@ int prepare_create_field(create_field *s
int *timestamps, int *timestamps_with_niladic,
uint table_flags)
{
+ unsigned int dup_val_count;
DBUG_ENTER("prepare_field");
/*
@@ -571,9 +584,10 @@ int prepare_create_field(create_field *s
if (sql_field->charset->state & MY_CS_BINSORT)
sql_field->pack_flag|=FIELDFLAG_BINARY;
sql_field->unireg_check=Field::INTERVAL_FIELD;
- check_duplicates_in_interval("ENUM",sql_field->field_name,
- sql_field->interval,
- sql_field->charset);
+ if (check_duplicates_in_interval("ENUM",sql_field->field_name,
+ sql_field->interval,
+ sql_field->charset, &dup_val_count))
+ DBUG_RETURN(1);
break;
case FIELD_TYPE_SET:
sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) |
@@ -581,9 +595,16 @@ int prepare_create_field(create_field *s
if (sql_field->charset->state & MY_CS_BINSORT)
sql_field->pack_flag|=FIELDFLAG_BINARY;
sql_field->unireg_check=Field::BIT_FIELD;
- check_duplicates_in_interval("SET",sql_field->field_name,
- sql_field->interval,
- sql_field->charset);
+ if (check_duplicates_in_interval("SET",sql_field->field_name,
+ sql_field->interval,
+ sql_field->charset, &dup_val_count))
+ DBUG_RETURN(1);
+ /* Check that count of unique members is not more then 64 */
+ if (sql_field->interval->count - dup_val_count > sizeof(longlong)*8)
+ {
+ my_error(ER_TOO_BIG_SET, MYF(0), sql_field->field_name);
+ DBUG_RETURN(1);
+ }
break;
case FIELD_TYPE_DATE: // Rest of string types
case FIELD_TYPE_NEWDATE:
@@ -1697,6 +1718,7 @@ bool mysql_create_table(THD *thd,const c
alias);
DBUG_RETURN(FALSE);
}
+ DBUG_PRINT("info",("1"));
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), alias);
DBUG_RETURN(TRUE);
}
@@ -1707,6 +1729,7 @@ bool mysql_create_table(THD *thd,const c
{
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
goto warn;
+ DBUG_PRINT("info",("2"));
my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
goto end;
}
@@ -1725,14 +1748,25 @@ bool mysql_create_table(THD *thd,const c
{
bool create_if_not_exists =
create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS;
- if (ha_table_exists_in_engine(thd, db, table_name))
+ int retcode = ha_table_exists_in_engine(thd, db, table_name);
+ DBUG_PRINT("info", ("exists_in_engine: %u",retcode));
+ switch (retcode)
{
- DBUG_PRINT("info", ("Table with same name already existed in handler"));
+ case HA_ERR_NO_SUCH_TABLE:
+ /* Normal case, no table exists. we can go and create it */
+ break;
+ case HA_ERR_TABLE_EXIST:
+ DBUG_PRINT("info", ("Table existed in handler"));
- if (create_if_not_exists)
- goto warn;
- my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
- goto end;
+ if (create_if_not_exists)
+ goto warn;
+ my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
+ goto end;
+ break;
+ default:
+ DBUG_PRINT("info", ("error: %u from storage engine", retcode));
+ my_error(retcode, MYF(0),table_name);
+ goto end;
}
}
@@ -2068,7 +2102,9 @@ static int prepare_for_repair(THD* thd,
/*
Check if this is a table type that stores index and data separately,
- like ISAM or MyISAM
+ like ISAM or MyISAM. We assume fixed order of engine file name
+ extentions array. First element of engine file name extentions array
+ is meta/index file extention. Second element - data file extention.
*/
if (!ext[0] || !ext[1])
goto end; // No data file
@@ -4058,7 +4094,9 @@ copy_data_between_tables(TABLE *from,TAB
{
copy_ptr->do_copy(copy_ptr);
}
- if ((error=to->file->write_row((byte*) to->record[0])))
+ error=to->file->write_row((byte*) to->record[0]);
+ to->auto_increment_field_not_null= FALSE;
+ if (error)
{
if (!ignore ||
(error != HA_ERR_FOUND_DUPP_KEY &&
--- 1.214/sql/sql_update.cc 2007-04-04 07:47:35 -04:00
+++ 1.215/sql/sql_update.cc 2007-04-26 09:44:19 -04:00
@@ -436,7 +436,19 @@ int mysql_update(THD *thd,
MODE_STRICT_ALL_TABLES)));
if (table->triggers)
+ {
table->triggers->mark_fields_used(thd, TRG_EVENT_UPDATE);
+ if (table->triggers->has_triggers(TRG_EVENT_UPDATE,
+ TRG_ACTION_AFTER))
+ {
+ /*
+ The table has AFTER UPDATE triggers that might access to subject
+ table and therefore might need update to be done immediately.
+ So we turn-off the batching.
+ */
+ (void) table->file->extra(HA_EXTRA_UPDATE_CANNOT_BATCH);
+ }
+ }
/*
We can use compare_record() to optimize away updates if
@@ -1001,6 +1013,20 @@ int multi_update::prepare(List<Item> &no
table->no_keyread=1;
table->used_keys.clear_all();
table->pos_in_table_list= tl;
+ if (table->triggers)
+ {
+ table->triggers->mark_fields_used(thd, TRG_EVENT_UPDATE);
+ if (table->triggers->has_triggers(TRG_EVENT_UPDATE,
+ TRG_ACTION_AFTER))
+ {
+ /*
+ The table has AFTER UPDATE triggers that might access to subject
+ table and therefore might need update to be done immediately.
+ So we turn-off the batching.
+ */
+ (void) table->file->extra(HA_EXTRA_UPDATE_CANNOT_BATCH);
+ }
+ }
}
}
--- 1.514/sql/sql_yacc.yy 2007-04-04 07:47:35 -04:00
+++ 1.515/sql/sql_yacc.yy 2007-04-26 09:44:19 -04:00
@@ -1105,7 +1105,7 @@ bool my_yyoverflow(short **a, YYSTYPE **
key_alg opt_btree_or_rtree
%type <string_list>
- key_usage_list key_usage_list_inner using_list
+ key_usage_list using_list
%type <key_part>
key_part
@@ -1590,7 +1590,7 @@ sp_name:
my_error(ER_SP_WRONG_NAME, MYF(0), $3.str);
MYSQL_YYABORT;
}
- $$= new sp_name($1, $3);
+ $$= new sp_name($1, $3, true);
$$->init_qname(YYTHD);
}
| ident
@@ -1604,7 +1604,7 @@ sp_name:
}
if (thd->copy_db_to(&db.str, &db.length))
MYSQL_YYABORT;
- $$= new sp_name(db, $1);
+ $$= new sp_name(db, $1, false);
if ($$)
$$->init_qname(YYTHD);
}
@@ -5054,7 +5054,7 @@ simple_expr:
| ident '.' ident '(' opt_expr_list ')'
{
LEX *lex= Lex;
- sp_name *name= new sp_name($1, $3);
+ sp_name *name= new sp_name($1, $3, true);
name->init_qname(YYTHD);
sp_add_used_routine(lex, YYTHD, name, TYPE_ENUM_FUNCTION);
@@ -5169,7 +5169,7 @@ simple_expr:
LEX_STRING db;
if (thd->copy_db_to(&db.str, &db.length))
MYSQL_YYABORT;
- sp_name *name= new sp_name(db, $1);
+ sp_name *name= new sp_name(db, $1, false);
if (name)
name->init_qname(thd);
@@ -5920,19 +5920,15 @@ opt_key_definition:
sel->use_index_ptr= &sel->use_index;
sel->table_join_options|= TL_OPTION_FORCE_INDEX;
}
- | IGNORE_SYM key_or_index opt_for_join key_usage_list_inner
+ | IGNORE_SYM key_usage_list
{
SELECT_LEX *sel= Select;
- sel->ignore_index= *$4;
+ sel->ignore_index= *$2;
sel->ignore_index_ptr= &sel->ignore_index;
};
key_usage_list:
- key_or_index key_usage_list_inner
- { $$= $2; }
- ;
-
-key_usage_list_inner:
+ key_or_index opt_for_join
{ Select->interval_list.empty(); }
'(' key_list_or_empty ')'
{ $$= &Select->interval_list; }
@@ -9142,7 +9138,8 @@ grant_ident:
| table_ident
{
LEX *lex=Lex;
- if (!lex->current_select->add_table_to_list(lex->thd, $1,NULL,0))
+ if (!lex->current_select->add_table_to_list(lex->thd, $1,NULL,
+ TL_OPTION_UPDATING))
MYSQL_YYABORT;
if (lex->grant == GLOBAL_ACLS)
lex->grant = TABLE_ACLS & ~GRANT_ACL;
--- 1.141/sql/table.h 2007-04-04 07:47:35 -04:00
+++ 1.142/sql/table.h 2007-04-26 09:44:19 -04:00
@@ -55,7 +55,8 @@ typedef struct st_grant_info
ulong orig_want_privilege;
} GRANT_INFO;
-enum tmp_table_type {NO_TMP_TABLE=0, TMP_TABLE=1, TRANSACTIONAL_TMP_TABLE=2,
+enum tmp_table_type {NO_TMP_TABLE=0,
+ NON_TRANSACTIONAL_TMP_TABLE=1, TRANSACTIONAL_TMP_TABLE=2,
SYSTEM_TMP_TABLE=3};
enum frm_type_enum
@@ -273,6 +274,11 @@ struct st_table {
my_bool no_cache;
/* To signal that we should reset query_id for tables and cols */
my_bool clear_query_id;
+ /*
+ To indicate that a non-null value of the auto_increment field
+ was provided by the user or retrieved from the current record.
+ Used only in the MODE_NO_AUTO_VALUE_ON_ZERO mode.
+ */
my_bool auto_increment_field_not_null;
my_bool insert_or_update; /* Can be used by the handler */
my_bool alias_name_used; /* true if table_name is alias */
--- 1.172/support-files/mysql.spec.sh 2007-04-06 22:14:27 -04:00
+++ 1.173/support-files/mysql.spec.sh 2007-04-26 09:45:07 -04:00
@@ -481,6 +481,12 @@ chmod -R og-rw $mysql_datadir/mysql
# Allow safe_mysqld to start mysqld and print a message before we exit
sleep 2
+echo "Thank you for installing the MySQL Community Server! For Production
+systems, we recommend MySQL Enterprise, which contains enterprise-ready
+software, intelligent advisory services, and full production support with
+scheduled service packs and more. Visit www.mysql.com/enterprise for more
+information."
+
%post ndb-storage
mysql_clusterdir=/var/lib/mysql-cluster
--- 1.85/sql/ha_archive.cc 2007-04-04 07:47:31 -04:00
+++ 1.86/sql/ha_archive.cc 2007-04-26 09:44:16 -04:00
@@ -503,8 +503,8 @@ int ha_archive::init_archive_writer()
We just implement one additional file extension.
*/
static const char *ha_archive_exts[] = {
- ARZ,
ARM,
+ ARZ,
NullS
};
--- 1.124/mysql-test/r/information_schema.result 2007-04-04 07:47:31 -04:00
+++ 1.125/mysql-test/r/information_schema.result 2007-04-26 09:44:16 -04:00
@@ -688,7 +688,7 @@ Warnings:
Warning 1356 View 'test.v2' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
show create table v3;
View Create View
-v3 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v3` AS select `test`.`sub1`(1) AS `c`
+v3 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v3` AS select `sub1`(1) AS `c`
Warnings:
Warning 1356 View 'test.v3' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
drop view v2;
--- 1.21/ndb/src/ndbapi/DictCache.cpp 2007-02-22 10:03:02 -05:00
+++ 1.22/ndb/src/ndbapi/DictCache.cpp 2007-04-26 09:44:16 -04:00
@@ -141,7 +141,7 @@ void GlobalDictCache::printCache()
}
NdbTableImpl *
-GlobalDictCache::get(const char * name)
+GlobalDictCache::get(const char * name, int *error)
{
DBUG_ENTER("GlobalDictCache::get");
DBUG_PRINT("enter", ("name: %s", name));
@@ -151,6 +151,11 @@ GlobalDictCache::get(const char * name)
versions = m_tableHash.getData(name, len);
if(versions == 0){
versions = new Vector<TableVersion>(2);
+ if (versions == NULL)
+ {
+ *error = -1;
+ DBUG_RETURN(0);
+ }
m_tableHash.insertKey(name, len, 0, versions);
}
@@ -180,7 +185,11 @@ GlobalDictCache::get(const char * name)
tmp.m_impl = 0;
tmp.m_status = RETREIVING;
tmp.m_refCount = 1; // The one retreiving it
- versions->push_back(tmp);
+ if (versions->push_back(tmp))
+ {
+ *error = -1;
+ DBUG_RETURN(0);
+ }
DBUG_RETURN(0);
}
--- 1.310/sql/ha_ndbcluster.cc 2007-04-18 10:41:33 -04:00
+++ 1.311/sql/ha_ndbcluster.cc 2007-04-26 09:44:16 -04:00
@@ -5971,14 +5971,14 @@ ha_ndbcluster::register_query_cache_tabl
if (!is_autocommit)
{
- DBUG_PRINT("exit", ("Can't register table during transaction"))
+ DBUG_PRINT("exit", ("Can't register table during transaction"));
DBUG_RETURN(FALSE);
}
if (ndb_get_commitcount(thd, m_dbname, m_tabname, &commit_count))
{
*engine_data= 0;
- DBUG_PRINT("exit", ("Error, could not get commitcount"))
+ DBUG_PRINT("exit", ("Error, could not get commitcount"));
DBUG_RETURN(FALSE);
}
*engine_data= commit_count;
--- 1.241/sql/sp_head.cc 2007-04-04 07:47:33 -04:00
+++ 1.242/sql/sp_head.cc 2007-04-26 09:44:17 -04:00
@@ -954,6 +954,12 @@ sp_head::execute(THD *thd)
m_first_instance->m_last_cached_sp == this) ||
(m_recursion_level + 1 == m_next_cached_sp->m_recursion_level));
+ /*
+ NOTE: The SQL Standard does not specify the context that should be
+ preserved for stored routines. However, at SAP/Walldorf meeting it was
+ decided that current database should be preserved.
+ */
+
if (m_db.length &&
(err_status= sp_use_new_db(thd, m_db, &old_db, 0, &dbchanged)))
goto done;
| Thread |
|---|
| • bk commit into 5.0-community tree (cmiller:1.2469) | Chad MILLER | 26 Apr |