List:Commits« Previous MessageNext Message »
From:Chad MILLER Date:May 7 2007 8:59pm
Subject:bk commit into 5.1 tree (cmiller:1.2479)
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 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-05-07 16:59:03-04:00, cmiller@stripped +22 -0
  Merge zippy.cornsilk.net:/home/cmiller/work/mysql/mysql-5.1-unified02
  into  zippy.cornsilk.net:/home/cmiller/work/mysql/mysql-5.1-comeng-unification
  MERGE: 1.2475.1.34

  configure.in@stripped, 2007-05-07 16:58:19-04:00, cmiller@stripped +0 -0
    Auto merged
    MERGE: 1.456.1.2

  libmysqld/Makefile.am@stripped, 2007-05-07 16:58:19-04:00, cmiller@stripped +0 -0
    Auto merged
    MERGE: 1.111.1.1

  mysql-test/r/information_schema.result@stripped, 2007-05-07 16:58:19-04:00, cmiller@stripped +0 -0
    Auto merged
    MERGE: 1.151.1.1

  sql/Makefile.am@stripped, 2007-05-07 16:59:00-04:00, cmiller@stripped +0 -0
    SCCS merged
    MERGE: 1.182.1.1

  sql/ha_ndbcluster.cc@stripped, 2007-05-07 16:58:20-04:00, cmiller@stripped +0 -0
    Auto merged
    MERGE: 1.438.3.1

  sql/item_cmpfunc.cc@stripped, 2007-05-07 16:58:20-04:00, cmiller@stripped +0 -0
    Auto merged
    MERGE: 1.267.1.4

  sql/item_func.cc@stripped, 2007-05-07 16:58:20-04:00, cmiller@stripped +0 -0
    Auto merged
    MERGE: 1.379.1.1

  sql/mysql_priv.h@stripped, 2007-05-07 16:58:20-04:00, cmiller@stripped +0 -0
    Auto merged
    MERGE: 1.501.1.3

  sql/mysqld.cc@stripped, 2007-05-07 16:58:20-04:00, cmiller@stripped +0 -0
    Auto merged
    MERGE: 1.636.1.2

  sql/sql_base.cc@stripped, 2007-05-07 16:58:21-04:00, cmiller@stripped +0 -0
    Auto merged
    MERGE: 1.396.1.1

  sql/sql_delete.cc@stripped, 2007-05-07 16:58:21-04:00, cmiller@stripped +0 -0
    Auto merged
    MERGE: 1.218.1.1

  sql/sql_lex.cc@stripped, 2007-05-07 16:58:21-04:00, cmiller@stripped +0 -0
    Auto merged
    MERGE: 1.236.1.1

  sql/sql_lex.h@stripped, 2007-05-07 16:58:21-04:00, cmiller@stripped +0 -0
    Auto merged
    MERGE: 1.271.1.2

  sql/sql_parse.cc@stripped, 2007-05-07 16:58:21-04:00, cmiller@stripped +0 -0
    Auto merged
    MERGE: 1.662.1.2

  sql/sql_select.cc@stripped, 2007-05-07 16:58:22-04:00, cmiller@stripped +0 -0
    Auto merged
    MERGE: 1.515.1.6

  sql/sql_show.cc@stripped, 2007-05-07 16:58:22-04:00, cmiller@stripped +0 -0
    Auto merged
    MERGE: 1.407.1.1

  sql/sql_table.cc@stripped, 2007-05-07 16:58:22-04:00, cmiller@stripped +0 -0
    Auto merged
    MERGE: 1.407.1.1

  sql/sql_update.cc@stripped, 2007-05-07 16:58:22-04:00, cmiller@stripped +0 -0
    Auto merged
    MERGE: 1.237.1.1

  sql/sql_view.cc@stripped, 2007-05-07 16:58:22-04:00, cmiller@stripped +0 -0
    Auto merged
    MERGE: 1.131.1.1

  sql/sql_yacc.yy@stripped, 2007-05-07 16:58:23-04:00, cmiller@stripped +0 -0
    Auto merged
    MERGE: 1.564.1.1

  sql/table.h@stripped, 2007-05-07 16:58:23-04:00, cmiller@stripped +0 -0
    Auto merged
    MERGE: 1.166.1.1

  support-files/mysql.spec.sh@stripped, 2007-05-07 16:58:23-04:00, cmiller@stripped +0 -0
    Auto merged
    MERGE: 1.191.1.2

# 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.1-comeng-unification/RESYNC

--- 1.459/configure.in	2007-05-02 14:13:30 -04:00
+++ 1.460/configure.in	2007-05-07 16:58:19 -04:00
@@ -426,6 +426,22 @@ AC_SUBST(PERL5)
 
 # icheck, used for ABI check
 AC_PATH_PROG(ICHECK, icheck, no)
+# "icheck" is also the name of a file system check program on Tru64.
+# Verify the program found is really the interface checker.
+if test "x$ICHECK" != "xno"
+then
+  AC_MSG_CHECKING(if $ICHECK works as expected)
+  echo "int foo;" > conftest.h
+  $ICHECK --canonify -o conftest.ic conftest.h 2>/dev/null
+  if test -f "conftest.ic"
+  then
+    AC_MSG_RESULT(yes)
+  else
+    AC_MSG_RESULT(no)
+    ICHECK=no
+  fi
+  rm -f conftest.ic conftest.h
+fi
 AC_SUBST(ICHECK)
 
 # Lock for PS
@@ -2340,28 +2356,6 @@ AC_ARG_WITH(man,
     [with_man=yes]
 )
 
-if test X"$with_man" = Xyes
-then
-  man_dirs="man"
-  if test X"$have_ndbcluster" = Xyes
-  then
-    man1_files=`ls $srcdir/man/*.1 | sed -e 's;^.*man/;;'`
-    man8_files=`ls $srcdir/man/*.8 | sed -e 's;^.*man/;;'`
-  else
-    man1_files=`ls $srcdir/man/*.1 | grep -v '/ndb' | sed -e 's;^.*man/;;'`
-    man8_files=`ls $srcdir/man/*.8 | grep -v '/ndb' | sed -e 's;^.*man/;;'`
-  fi
-  man1_files=`echo $man1_files`
-  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)
-
 # Don't build readline, i have it already
 AC_ARG_WITH(readline,
     [  --without-readline      Use system readline instead of bundled copy.],
@@ -2487,6 +2481,61 @@ AC_SUBST(readline_basedir)
 AC_SUBST(readline_link)
 AC_SUBST(readline_h_ln_cmd)
 
+
+
+# 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"$with_plugin_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"$with_plugin_innobase" != 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.184/sql/Makefile.am	2007-04-24 11:41:53 -04:00
+++ 1.185/sql/Makefile.am	2007-05-07 16:59:00 -04:00
@@ -48,6 +48,7 @@ noinst_HEADERS =	item.h item_func.h item
 			procedure.h sql_class.h sql_lex.h sql_list.h \
 			sql_map.h sql_string.h unireg.h \
 			sql_error.h field.h handler.h mysqld_suffix.h \
+ 			sql_profile.h \
 			ha_ndbcluster.h ha_ndbcluster_cond.h \
 			ha_ndbcluster_binlog.h ha_ndbcluster_tables.h \
 			ha_partition.h rpl_constants.h \
@@ -83,6 +84,7 @@ mysqld_SOURCES =	sql_lex.cc sql_handler.
 			sql_connect.cc scheduler.cc sql_parse.cc \
 			set_var.cc sql_yacc.yy \
 			sql_base.cc table.cc sql_select.cc sql_insert.cc \
+			sql_profile.cc \
 			sql_prepare.cc sql_error.cc sql_locale.cc \
 			sql_update.cc sql_delete.cc uniques.cc sql_do.cc \
 			procedure.cc sql_test.cc \

--- 1.268/sql/item_cmpfunc.cc	2007-04-27 16:37:16 -04:00
+++ 1.269/sql/item_cmpfunc.cc	2007-05-07 16:58:20 -04:00
@@ -437,7 +437,9 @@ void Item_bool_func2::fix_length_and_dec
     if (arg_real_item->type() == FIELD_ITEM)
     {
       Field *field=((Item_field*) arg_real_item)->field;
-      if (field->can_be_compared_as_longlong())
+      if (field->can_be_compared_as_longlong() &&
+          !(arg_real_item->is_datetime() &&
+            args[1]->result_type() == STRING_RESULT))
       {
         if (convert_constant_item(thd, field,&args[1]))
         {
@@ -452,7 +454,9 @@ void Item_bool_func2::fix_length_and_dec
     if (arg_real_item->type() == FIELD_ITEM)
     {
       Field *field=((Item_field*) arg_real_item)->field;
-      if (field->can_be_compared_as_longlong())
+      if (field->can_be_compared_as_longlong() &&
+          !(arg_real_item->is_datetime() &&
+            args[0]->result_type() == STRING_RESULT))
       {
         if (convert_constant_item(thd, field,&args[0]))
         {
@@ -571,6 +575,335 @@ int Arg_comparator::set_compare_func(Ite
 }
 
 
+/*
+  Convert date provided in a string to the int representation.
+
+  SYNOPSIS
+    get_date_from_str()
+    thd              Thread handle
+    str              a string to convert
+    warn_type        type of the timestamp for issuing the warning
+    warn_name        field name for issuing the warning
+    error_arg  [out] TRUE if string isn't a DATETIME or clipping occur
+
+  DESCRIPTION
+    Convert date provided in the string str to the int representation.
+    if the string contains wrong date or doesn't contain it at all
+    then the warning is issued and TRUE returned in the error_arg argument.
+    The warn_type and the warn_name arguments are used as the name and the
+    type of the field when issuing the warning.
+
+  RETURN
+    converted value.
+*/
+
+static ulonglong
+get_date_from_str(THD *thd, String *str, timestamp_type warn_type,
+                  char *warn_name, bool *error_arg)
+{
+  ulonglong value= 0;
+  int error;
+  MYSQL_TIME l_time;
+  enum_mysql_timestamp_type ret;
+  *error_arg= TRUE;
+
+  ret= str_to_datetime(str->ptr(), str->length(), &l_time,
+                       (TIME_FUZZY_DATE | MODE_INVALID_DATES |
+                        (thd->variables.sql_mode &
+                         (MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE))),
+                       &error);
+  if ((ret == MYSQL_TIMESTAMP_DATETIME || ret == MYSQL_TIMESTAMP_DATE))
+  {
+    value= TIME_to_ulonglong_datetime(&l_time);
+    *error_arg= FALSE;
+  }
+
+  if (error || *error_arg)
+  {
+    make_truncated_value_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+                                 str->ptr(), str->length(),
+                                 warn_type, warn_name);
+    *error_arg= TRUE;
+  }
+  return value;
+}
+
+
+/*
+  Check whether compare_datetime() can be used to compare items.
+
+  SYNOPSIS
+    Arg_comparator::can_compare_as_dates()
+    a, b          [in]  items to be compared
+    const_value   [out] converted value of the string constant, if any
+
+  DESCRIPTION
+    Check several cases when the DATE/DATETIME comparator should be used.
+    The following cases are checked:
+      1. Both a and b is a DATE/DATETIME field/function returning string or
+         int result.
+      2. Only a or b is a DATE/DATETIME field/function returning string or
+         int result and the other item (b or a) is an item with string result.
+         If the second item is a constant one then it's checked to be
+         convertible to the DATE/DATETIME type. If the constant can't be
+         converted to a DATE/DATETIME then the compare_datetime() comparator
+         isn't used and the warning about wrong DATE/DATETIME value is issued.
+      In all other cases (date-[int|real|decimal]/[int|real|decimal]-date)
+      the comparison is handled by other comparators.
+    If the datetime comparator can be used and one the operands of the
+    comparison is a string constant that was successfully converted to a
+    DATE/DATETIME type then the result of the conversion is returned in the
+    const_value if it is provided.  If there is no constant or
+    compare_datetime() isn't applicable then the *const_value remains
+    unchanged.
+
+  RETURN
+    the found type of date comparison
+*/
+
+enum Arg_comparator::enum_date_cmp_type
+Arg_comparator::can_compare_as_dates(Item *a, Item *b, ulonglong *const_value)
+{
+  enum enum_date_cmp_type cmp_type= CMP_DATE_DFLT;
+  Item *str_arg= 0, *date_arg= 0;
+
+  if (a->type() == Item::ROW_ITEM || b->type() == Item::ROW_ITEM)
+    return CMP_DATE_DFLT;
+
+  if (a->is_datetime())
+  {
+    if (b->is_datetime())
+      cmp_type= CMP_DATE_WITH_DATE;
+    else if (b->result_type() == STRING_RESULT)
+    {
+      cmp_type= CMP_DATE_WITH_STR;
+      date_arg= a;
+      str_arg= b;
+    }
+  }
+  else if (b->is_datetime() && a->result_type() == STRING_RESULT)
+  {
+    cmp_type= CMP_STR_WITH_DATE;
+    date_arg= b;
+    str_arg= a;
+  }
+
+  if (cmp_type != CMP_DATE_DFLT)
+  {
+    if (cmp_type != CMP_DATE_WITH_DATE && str_arg->const_item())
+    {
+      THD *thd= current_thd;
+      ulonglong value;
+      bool error;
+      String tmp, *str_val= 0;
+      timestamp_type t_type= (date_arg->field_type() == MYSQL_TYPE_DATE ?
+                              MYSQL_TIMESTAMP_DATE : MYSQL_TIMESTAMP_DATETIME);
+
+      str_val= str_arg->val_str(&tmp);
+      if (str_arg->null_value)
+        return CMP_DATE_DFLT;
+      value= get_date_from_str(thd, str_val, t_type, date_arg->name, &error);
+      if (error)
+        return CMP_DATE_DFLT;
+      if (const_value)
+        *const_value= value;
+    }
+  }
+  return cmp_type;
+}
+
+
+int Arg_comparator::set_cmp_func(Item_bool_func2 *owner_arg,
+                                        Item **a1, Item **a2,
+                                        Item_result type)
+{
+  enum enum_date_cmp_type cmp_type;
+  ulonglong const_value;
+  a= a1;
+  b= a2;
+
+  if ((cmp_type= can_compare_as_dates(*a, *b, &const_value)))
+  {
+    thd= current_thd;
+    owner= owner_arg;
+    a_type= (*a)->field_type();
+    b_type= (*b)->field_type();
+    a_cache= 0;
+    b_cache= 0;
+
+    if (cmp_type != CMP_DATE_WITH_DATE &&
+        ((*b)->const_item() || (*a)->const_item()))
+    {
+      Item_cache_int *cache= new Item_cache_int();
+      /* Mark the cache as non-const to prevent re-caching. */
+      cache->set_used_tables(1);
+      if (!(*a)->is_datetime())
+      {
+        cache->store((*a), const_value);
+        a_cache= cache;
+        a= (Item **)&a_cache;
+      }
+      else
+      {
+        cache->store((*b), const_value);
+        b_cache= cache;
+        b= (Item **)&b_cache;
+      }
+    }
+    is_nulls_eq= test(owner && owner->functype() == Item_func::EQUAL_FUNC);
+    func= &Arg_comparator::compare_datetime;
+    return 0;
+  }
+  return set_compare_func(owner_arg, type);
+}
+
+
+void Arg_comparator::set_datetime_cmp_func(Item **a1, Item **b1)
+{
+  thd= current_thd;
+  /* A caller will handle null values by itself. */
+  owner= NULL;
+  a= a1;
+  b= b1;
+  a_type= (*a)->field_type();
+  b_type= (*b)->field_type();
+  a_cache= 0;
+  b_cache= 0;
+  is_nulls_eq= FALSE;
+  func= &Arg_comparator::compare_datetime;
+}
+
+/*
+  Retrieves correct DATETIME value from given item.
+
+  SYNOPSIS
+    get_datetime_value()
+    thd                 thread handle
+    item_arg   [in/out] item to retrieve DATETIME value from
+    cache_arg  [in/out] pointer to place to store the caching item to
+    warn_item  [in]     item for issuing the conversion warning
+    is_null    [out]    TRUE <=> the item_arg is null
+
+  DESCRIPTION
+    Retrieves the correct DATETIME value from given item for comparison by the
+    compare_datetime() function.
+    If item's result can be compared as longlong then its int value is used
+    and its string value is used otherwise. Strings are always parsed and
+    converted to int values by the get_date_from_str() function.
+    This allows us to compare correctly string dates with missed insignificant
+    zeros. If an item is a constant one then its value is cached and it isn't
+    get parsed again. An Item_cache_int object is used for caching values. It
+    seamlessly substitutes the original item.  The cache item is marked as
+    non-constant to prevent re-caching it again.  In order to compare
+    correctly DATE and DATETIME items the result of the former are treated as
+    a DATETIME with zero time (00:00:00).
+
+  RETURN
+    obtained value
+*/
+
+ulonglong
+get_datetime_value(THD *thd, Item ***item_arg, Item **cache_arg,
+                   Item *warn_item, bool *is_null)
+{
+  ulonglong value= 0;
+  String buf, *str= 0;
+  Item *item= **item_arg;
+
+  if (item->result_as_longlong())
+  {
+    value= item->val_int();
+    *is_null= item->null_value;
+    if (item->field_type() == MYSQL_TYPE_DATE)
+      value*= 1000000L;
+  }
+  else
+  {
+    str= item->val_str(&buf);
+    *is_null= item->null_value;
+  }
+  if (*is_null)
+    return -1;
+  /*
+    Convert strings to the integer DATE/DATETIME representation.
+    Even if both dates provided in strings we can't compare them directly as
+    strings as there is no warranty that they are correct and do not miss
+    some insignificant zeros.
+  */
+  if (str)
+  {
+    bool error;
+    enum_field_types f_type= warn_item->field_type();
+    timestamp_type t_type= f_type ==
+      MYSQL_TYPE_DATE ? MYSQL_TIMESTAMP_DATE : MYSQL_TIMESTAMP_DATETIME;
+    value= get_date_from_str(thd, str, t_type, warn_item->name, &error);
+  }
+  if (item->const_item() && cache_arg)
+  {
+    Item_cache_int *cache= new Item_cache_int();
+    /* Mark the cache as non-const to prevent re-caching. */
+    cache->set_used_tables(1);
+    cache->store(item, value);
+    *cache_arg= cache;
+    *item_arg= cache_arg;
+  }
+  return value;
+}
+
+/*
+  Compare items values as dates.
+
+  SYNOPSIS
+    Arg_comparator::compare_datetime()
+
+  DESCRIPTION
+    Compare items values as DATE/DATETIME for both EQUAL_FUNC and from other
+    comparison functions. The correct DATETIME values are obtained
+    with help of the get_datetime_value() function.
+
+  RETURN
+    If is_nulls_eq is TRUE:
+       1    if items are equal or both are null
+       0    otherwise
+    If is_nulls_eq is FALSE:
+      -1   a < b or one of items is null
+       0   a == b
+       1   a > b
+*/
+
+int Arg_comparator::compare_datetime()
+{
+  bool is_null= FALSE;
+  ulonglong a_value, b_value;
+
+  /* Get DATE/DATETIME value of the 'a' item. */
+  a_value= get_datetime_value(thd, &a, &a_cache, *b, &is_null);
+  if (!is_nulls_eq && is_null)
+  {
+    if (owner)
+      owner->null_value= 1;
+    return -1;
+  }
+
+  /* Get DATE/DATETIME value of the 'b' item. */
+  b_value= get_datetime_value(thd, &b, &b_cache, *a, &is_null);
+  if (is_null)
+  {
+    if (owner)
+      owner->null_value= is_nulls_eq ? 0 : 1;
+    return is_nulls_eq ? 1 : -1;
+  }
+
+  if (owner)
+    owner->null_value= 0;
+
+  /* Compare values. */
+  if (is_nulls_eq)
+    return (a_value == b_value);
+  return a_value < b_value ? -1 : (a_value > b_value ? 1 : 0);
+}
+
+
 int Arg_comparator::compare_string()
 {
   String *res1,*res2;
@@ -1420,8 +1753,10 @@ bool Item_func_between::fix_fields(THD *
 
 void Item_func_between::fix_length_and_dec()
 {
-   max_length= 1;
-   THD *thd= current_thd;
+  max_length= 1;
+  int i;
+  bool datetime_found= FALSE;
+  compare_as_dates= TRUE;
 
   /*
     As some compare functions are generated after sql_yacc,
@@ -1436,26 +1771,29 @@ void Item_func_between::fix_length_and_d
    return;
 
   /*
-    Make a special case of compare with date/time and longlong fields.
-    They are compared as integers, so for const item this time-consuming
-    conversion can be done only once, not for every single comparison
+    Detect the comparison of DATE/DATETIME items.
+    At least one of items should be a DATE/DATETIME item and other items
+    should return the STRING result.
   */
-  if (args[0]->real_item()->type() == FIELD_ITEM &&
-      thd->lex->sql_command != SQLCOM_CREATE_VIEW &&
-      thd->lex->sql_command != SQLCOM_SHOW_CREATE)
+  for (i= 0; i < 3; i++)
   {
-    Field *field=((Item_field*) (args[0]->real_item()))->field;
-    if (field->can_be_compared_as_longlong())
+    if (args[i]->is_datetime())
     {
-      /*
-        The following can't be recoded with || as convert_constant_item
-        changes the argument
-      */
-      if (convert_constant_item(thd, field,&args[1]))
-	cmp_type=INT_RESULT;			// Works for all types.
-      if (convert_constant_item(thd, field,&args[2]))
-	cmp_type=INT_RESULT;			// Works for all types.
+      datetime_found= TRUE;
+      continue;
     }
+    if (args[i]->result_type() == STRING_RESULT)
+      continue;
+    compare_as_dates= FALSE;
+    break;
+  }
+  if (!datetime_found)
+    compare_as_dates= FALSE;
+
+  if (compare_as_dates)
+  {
+    ge_cmp.set_datetime_cmp_func(args, args + 1);
+    le_cmp.set_datetime_cmp_func(args, args + 2);
   }
 }
 
@@ -1463,7 +1801,27 @@ void Item_func_between::fix_length_and_d
 longlong Item_func_between::val_int()
 {						// ANSI BETWEEN
   DBUG_ASSERT(fixed == 1);
-  if (cmp_type == STRING_RESULT)
+  if (compare_as_dates)
+  {
+    int ge_res, le_res;
+
+    ge_res= ge_cmp.compare();
+    if ((null_value= args[0]->null_value))
+      return 0;
+    le_res= le_cmp.compare();
+
+    if (!args[1]->null_value && !args[2]->null_value)
+      return (longlong) ((ge_res >= 0 && le_res <=0) != negated);
+    else if (args[1]->null_value)
+    {
+      null_value= le_res > 0;			// not null if false range.
+    }
+    else
+    {
+      null_value= ge_res < 0;
+    }
+  }
+  else if (cmp_type == STRING_RESULT)
   {
     String *value,*a,*b;
     value=args[0]->val_str(&value0);

--- 1.385/sql/item_func.cc	2007-05-07 07:09:47 -04:00
+++ 1.386/sql/item_func.cc	2007-05-07 16:58:20 -04:00
@@ -3361,7 +3361,7 @@ void debug_sync_point(const char* lock_n
     Structure is now initialized.  Try to get the lock.
     Set up control struct to allow others to abort locks
   */
-  thd->proc_info="User lock";
+  thd_proc_info(thd, "User lock");
   thd->mysys_var->current_mutex= &LOCK_user_locks;
   thd->mysys_var->current_cond=  &ull->cond;
 
@@ -3386,7 +3386,7 @@ void debug_sync_point(const char* lock_n
   }
   pthread_mutex_unlock(&LOCK_user_locks);
   pthread_mutex_lock(&thd->mysys_var->mutex);
-  thd->proc_info=0;
+  thd_proc_info(thd, 0);
   thd->mysys_var->current_mutex= 0;
   thd->mysys_var->current_cond=  0;
   pthread_mutex_unlock(&thd->mysys_var->mutex);
@@ -3467,7 +3467,7 @@ longlong Item_func_get_lock::val_int()
     Structure is now initialized.  Try to get the lock.
     Set up control struct to allow others to abort locks.
   */
-  thd->proc_info="User lock";
+  thd_proc_info(thd, "User lock");
   thd->mysys_var->current_mutex= &LOCK_user_locks;
   thd->mysys_var->current_cond=  &ull->cond;
 
@@ -3505,7 +3505,7 @@ longlong Item_func_get_lock::val_int()
   pthread_mutex_unlock(&LOCK_user_locks);
 
   pthread_mutex_lock(&thd->mysys_var->mutex);
-  thd->proc_info=0;
+  thd_proc_info(thd, 0);
   thd->mysys_var->current_mutex= 0;
   thd->mysys_var->current_cond=  0;
   pthread_mutex_unlock(&thd->mysys_var->mutex);

--- 1.503/sql/mysql_priv.h	2007-05-02 14:13:30 -04:00
+++ 1.504/sql/mysql_priv.h	2007-05-07 16:58:20 -04:00
@@ -1890,6 +1890,8 @@ void make_date(const DATE_TIME_FORMAT *f
 void make_time(const DATE_TIME_FORMAT *format, const MYSQL_TIME *l_time,
                String *str);
 int my_time_compare(MYSQL_TIME *a, MYSQL_TIME *b);
+ulonglong get_datetime_value(THD *thd, Item ***item_arg, Item **cache_arg,
+                             Item *warn_item, bool *is_null);
 
 int test_if_number(char *str,int *res,bool allow_wildcards);
 void change_byte(byte *,uint,char,char);
@@ -1905,7 +1907,8 @@ ha_rows filesort(THD *thd, TABLE *form,s
                  ha_rows *examined_rows);
 void filesort_free_buffers(TABLE *table, bool full);
 void change_double_for_sort(double nr,byte *to);
-double my_double_round(double value, int dec, bool truncate);
+double my_double_round(double value, longlong dec, bool dec_unsigned,
+                       bool truncate);
 int get_quick_record(SQL_SELECT *select);
 
 int calc_weekday(long daynr,bool sunday_first_day_of_week);

--- 1.638/sql/mysqld.cc	2007-04-26 10:02:53 -04:00
+++ 1.639/sql/mysqld.cc	2007-05-07 16:58:20 -04:00
@@ -514,7 +514,7 @@ const char *log_output_str= "TABLE";
 
 double log_10[32];			/* 10 potences */
 double log_01[32];
-time_t server_start_time;
+time_t server_start_time, flush_status_time;
 
 char mysql_home[FN_REFLEN], pidfile_name[FN_REFLEN], system_time_zone[30];
 char *default_tz_name;
@@ -576,6 +576,7 @@ MY_LOCALE *my_default_lc_time_names;
 SHOW_COMP_OPTION have_ssl, have_symlink, have_dlopen, have_query_cache;
 SHOW_COMP_OPTION have_geometry, have_rtree_keys;
 SHOW_COMP_OPTION have_crypt, have_compress;
+SHOW_COMP_OPTION have_community_features;
 
 /* Thread specific variables */
 
@@ -2720,7 +2721,7 @@ static int init_common_variables(const c
   tzset();			// Set tzname
 
   max_system_variables.pseudo_thread_id= (ulong)~0;
-  server_start_time= time((time_t*) 0);
+  server_start_time= flush_status_time= time((time_t*) 0);
   rpl_filter= new Rpl_filter;
   binlog_filter= new Rpl_filter;
   if (!rpl_filter || !binlog_filter) 
@@ -5048,6 +5049,7 @@ enum options_mysqld
   OPT_PLUGIN_DIR,
   OPT_LOG_OUTPUT,
   OPT_PORT_OPEN_TIMEOUT,
+  OPT_PROFILING,
   OPT_GENERAL_LOG,
   OPT_SLOW_LOG,
   OPT_MERGE,
@@ -5688,6 +5690,12 @@ Disable with --skip-ndbcluster (will sav
    "Maximum time in seconds to wait for the port to become free. "
    "(Default: no wait)", (gptr*) &mysqld_port_timeout,
    (gptr*) &mysqld_port_timeout, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
+  {"profiling_history_size", OPT_PROFILING, "Limit of query profiling memory",
+   (gptr*) &global_system_variables.profiling_history_size,
+   (gptr*) &max_system_variables.profiling_history_size,
+   0, GET_ULONG, REQUIRED_ARG, 15, 0, 100, 0, 0, 0},
+#endif
   {"relay-log", OPT_RELAY_LOG,
    "The location and name to use for relay logs.",
    (gptr*) &opt_relay_logname, (gptr*) &opt_relay_logname, 0,
@@ -6522,6 +6530,16 @@ static int show_starttime(THD *thd, SHOW
   return 0;
 }
 
+#ifdef COMMUNITY_SERVER
+static int show_flushstatustime(THD *thd, SHOW_VAR *var, char *buff)
+{
+  var->type= SHOW_LONG;
+  var->value= buff;
+  *((long *)buff)= (long) (thd->query_start() - flush_status_time);
+  return 0;
+}
+#endif
+
 #ifdef HAVE_REPLICATION
 static int show_rpl_status(THD *thd, SHOW_VAR *var, char *buff)
 {
@@ -7074,6 +7092,9 @@ SHOW_VAR status_vars[]= {
   {"Threads_created",	       (char*) &thread_created,		SHOW_LONG_NOFLUSH},
   {"Threads_running",          (char*) &thread_running,         SHOW_INT},
   {"Uptime",                   (char*) &show_starttime,         SHOW_FUNC},
+#ifdef COMMUNITY_SERVER
+  {"Uptime_since_flush_status",(char*) &show_flushstatustime,   SHOW_FUNC},
+#endif
   {NullS, NullS, SHOW_LONG}
 };
 
@@ -7298,6 +7319,11 @@ static void mysql_init_variables(void)
 #else
     have_partition_db= SHOW_OPTION_NO;
 #endif
+#ifdef COMMUNITY_SERVER
+    have_community_features = SHOW_OPTION_YES;
+#else
+    have_community_features = SHOW_OPTION_NO;
+#endif
 #ifdef WITH_NDBCLUSTER_STORAGE_ENGINE
   have_ndbcluster=SHOW_OPTION_DISABLED;
   global_system_variables.ndb_index_stat_enable=FALSE;
@@ -8346,6 +8372,9 @@ void refresh_status(THD *thd)
 
   /* Reset the counters of all key caches (default and named). */
   process_key_caches(reset_key_cache_counters);
+#ifdef COMMUNITY_SERVER
+  flush_status_time= time((time_t*) 0);
+#endif
   pthread_mutex_unlock(&LOCK_status);
 
   /*

--- 1.397/sql/sql_base.cc	2007-04-27 16:43:24 -04:00
+++ 1.398/sql/sql_base.cc	2007-05-07 16:58:21 -04:00
@@ -5575,6 +5575,7 @@ int setup_wild(THD *thd, TABLE_LIST *tab
   */
   arena= thd->activate_stmt_arena_if_needed(&backup);
 
+  thd->lex->current_select->cur_pos_in_select_list= 0;
   while (wild_num && (item= it++))
   {
     if (item->type() == Item::FIELD_ITEM &&
@@ -5616,7 +5617,10 @@ int setup_wild(THD *thd, TABLE_LIST *tab
       }
       wild_num--;
     }
+    else
+      thd->lex->current_select->cur_pos_in_select_list++;
   }
+  thd->lex->current_select->cur_pos_in_select_list= UNDEF_POS;
   if (arena)
   {
     /* make * substituting permanent */
@@ -6099,6 +6103,7 @@ insert_fields(THD *thd, Name_resolution_
       }
       else
         thd->used_tables|= item->used_tables();
+      thd->lex->current_select->cur_pos_in_select_list++;
     }
     /*
       In case of stored tables, all fields are considered as used,

--- 1.219/sql/sql_delete.cc	2007-04-26 10:02:53 -04:00
+++ 1.220/sql/sql_delete.cc	2007-05-07 16:58:21 -04:00
@@ -48,7 +48,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *
 	     table_list->view_db.str, table_list->view_name.str);
     DBUG_RETURN(TRUE);
   }
-  thd->proc_info="init";
+  thd_proc_info(thd, "init");
   table->map=1;
 
   if (mysql_prepare_delete(thd, table_list, &conds))
@@ -220,7 +220,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *
     init_read_record_idx(&info, thd, table, 1, usable_index);
 
   init_ftfuncs(thd, select_lex, 1);
-  thd->proc_info="updating";
+  thd_proc_info(thd, "updating");
   if (table->triggers && 
       table->triggers->has_triggers(TRG_EVENT_DELETE,
                                     TRG_ACTION_AFTER))
@@ -296,7 +296,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *
       table->file->print_error(loc_error,MYF(0));
     error=1;
   }
-  thd->proc_info= "end";
+  thd_proc_info(thd, "end");
   end_read_record(&info);
   if (options & OPTION_QUICK)
     (void) table->file->extra(HA_EXTRA_NORMAL);
@@ -537,7 +537,7 @@ multi_delete::prepare(List<Item> &values
   DBUG_ENTER("multi_delete::prepare");
   unit= u;
   do_delete= 1;
-  thd->proc_info="deleting from main table";
+  thd_proc_info(thd, "deleting from main table");
   DBUG_RETURN(0);
 }
 
@@ -821,7 +821,7 @@ int multi_delete::do_deletes()
 
 bool multi_delete::send_eof()
 {
-  thd->proc_info="deleting from reference tables";
+  thd_proc_info(thd, "deleting from reference tables");
 
   /* Does deletes for the last n - 1 tables, returns 0 if ok */
   int local_error= do_deletes();		// returns 0 if success
@@ -830,7 +830,7 @@ bool multi_delete::send_eof()
   local_error= local_error || error;
 
   /* reset used flags */
-  thd->proc_info="end";
+  thd_proc_info(thd, "end");
 
   /*
     We must invalidate the query cache before binlog writing and
@@ -1011,7 +1011,7 @@ trunc_by_del:
   /* Probably InnoDB table */
   ulonglong save_options= thd->options;
   table_list->lock_type= TL_WRITE;
-  thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_NOT_AUTOCOMMIT);
+  thd->options&= ~(OPTION_BEGIN | OPTION_NOT_AUTOCOMMIT);
   ha_enable_transaction(thd, FALSE);
   mysql_init_select(thd->lex);
   bool save_binlog_row_based= thd->current_stmt_binlog_row_based;

--- 1.237/sql/sql_lex.cc	2007-04-17 09:44:25 -04:00
+++ 1.238/sql/sql_lex.cc	2007-05-07 16:58:21 -04:00
@@ -199,7 +199,7 @@ void lex_start(THD *thd, const char *buf
   lex->name.str= 0;
   lex->name.length= 0;
   lex->event_parse_data= NULL;
-
+  lex->profile_options= PROFILE_NONE;
   lex->nest_level=0 ;
   lex->allow_sum_func= 0;
   lex->in_sum_func= NULL;

--- 1.273/sql/sql_lex.h	2007-04-24 09:03:02 -04:00
+++ 1.274/sql/sql_lex.h	2007-05-07 16:58:21 -04:00
@@ -113,9 +113,13 @@ enum enum_sql_command {
   SQLCOM_CREATE_SERVER, SQLCOM_DROP_SERVER, SQLCOM_ALTER_SERVER,
   SQLCOM_CREATE_EVENT, SQLCOM_ALTER_EVENT, SQLCOM_DROP_EVENT,
   SQLCOM_SHOW_CREATE_EVENT, SQLCOM_SHOW_EVENTS, 
+  SQLCOM_SHOW_PROFILE, SQLCOM_SHOW_PROFILES,
 
+  /*
+    When a command is added here, be sure it's also added in mysqld.cc
+    in "struct show_var_st status_vars[]= {" ...
+  */
   /* This should be the last !!! */
-
   SQLCOM_END
 };
 
@@ -1111,6 +1115,9 @@ typedef struct st_lex : public Query_tab
   enum enum_var_type option_type;
   enum enum_view_create_mode create_view_mode;
   enum enum_drop_mode drop_mode;
+
+  uint profile_query_id;
+  uint profile_options;
   uint uint_geom_type;
   uint grant, grant_tot_col, which_columns;
   uint fk_delete_opt, fk_update_opt, fk_match_option;

--- 1.663/sql/sql_parse.cc	2007-04-27 16:43:24 -04:00
+++ 1.664/sql/sql_parse.cc	2007-05-07 16:58:21 -04:00
@@ -4602,7 +4602,8 @@ check_access(THD *thd, ulong want_access
 
   if (schema_db)
   {
-    if (want_access & ~(SELECT_ACL | EXTRA_ACL))
+    if (!(sctx->master_access & FILE_ACL) && (want_access & FILE_ACL) ||
+        (want_access & ~(SELECT_ACL | EXTRA_ACL | FILE_ACL)))
     {
       if (!no_errors)
       {
@@ -6004,7 +6005,7 @@ bool st_select_lex_unit::add_fake_select
   fake_select_lex->context.resolve_in_select_list= TRUE;
   fake_select_lex->context.select_lex= fake_select_lex;
 
-  if (!first_sl->next_select())
+  if (!is_union())
   {
     /* 
       This works only for 

--- 1.516/sql/sql_select.cc	2007-04-27 16:43:24 -04:00
+++ 1.517/sql/sql_select.cc	2007-05-07 16:58:22 -04:00
@@ -231,7 +231,8 @@ bool handle_select(THD *thd, LEX *lex, s
   register SELECT_LEX *select_lex = &lex->select_lex;
   DBUG_ENTER("handle_select");
 
-  if (select_lex->next_select() || select_lex->master_unit()->fake_select_lex)
+  if (select_lex->master_unit()->is_union() || 
+      select_lex->master_unit()->fake_select_lex)
     res= mysql_union(thd, lex, result, &lex->unit, setup_tables_done_option);
   else
   {
@@ -442,7 +443,7 @@ JOIN::prepare(Item ***rref_pointer_array
   select_lex= select_lex_arg;
   select_lex->join= this;
   join_list= &select_lex->top_join_list;
-  union_part= (unit_arg->first_select()->next_select() != 0);
+  union_part= unit_arg->is_union();
 
   thd->lex->current_select->is_item_list_lookup= 1;
   /*
@@ -1199,7 +1200,7 @@ JOIN::optimize()
   if (!group_list && !order &&
       unit->item && unit->item->substype() == Item_subselect::IN_SUBS &&
       tables == 1 && conds &&
-      !unit->first_select()->next_select())
+      !unit->is_union())
   {
     if (!having)
     {
@@ -1452,14 +1453,13 @@ JOIN::optimize()
       }
     }
 
-    if (select_lex->uncacheable && !is_top_level_join())
-    {
-      /* If this join belongs to an uncacheable subquery */
-      if (!(tmp_join= (JOIN*)thd->alloc(sizeof(JOIN))))
-	DBUG_RETURN(-1);
-      error= 0;				// Ensure that tmp_join.error= 0
-      restore_tmp();
-    }
+    /* 
+      If this join belongs to an uncacheable subquery save 
+      the original join 
+    */
+    if (select_lex->uncacheable && !is_top_level_join() &&
+        init_save_join_tab())
+      DBUG_RETURN(-1);                         /* purecov: inspected */
   }
 
   error= 0;
@@ -1521,6 +1521,27 @@ JOIN::reinit()
   DBUG_RETURN(0);
 }
 
+/**
+   @brief Save the original join layout
+      
+   @details Saves the original join layout so it can be reused in 
+   re-execution and for EXPLAIN.
+             
+   @return Operation status
+   @retval 0      success.
+   @retval 1      error occurred.
+*/
+
+bool
+JOIN::init_save_join_tab()
+{
+  if (!(tmp_join= (JOIN*)thd->alloc(sizeof(JOIN))))
+    return 1;                                  /* purecov: inspected */
+  error= 0;				       // Ensure that tmp_join.error= 0
+  restore_tmp();
+  return 0;
+}
+
 
 bool
 JOIN::save_join_tab()
@@ -3184,7 +3205,7 @@ add_key_fields(JOIN *join, KEY_FIELD **k
       if (!join->group_list && !join->order &&
           join->unit->item && 
           join->unit->item->substype() == Item_subselect::IN_SUBS &&
-          !join->unit->first_select()->next_select())
+          !join->unit->is_union())
       {
         KEY_FIELD *save= *key_fields;
         add_key_fields(join, key_fields, and_level, cond_arg, usable_tables,
@@ -5633,8 +5654,9 @@ static void add_not_null_conds(JOIN *joi
   for (uint i=join->const_tables ; i < join->tables ; i++)
   {
     JOIN_TAB *tab=join->join_tab+i;
-    if ((tab->type == JT_REF || tab->type == JT_REF_OR_NULL) &&
-         !tab->table->maybe_null)
+    if ((tab->type == JT_REF || tab->type == JT_EQ_REF || 
+         tab->type == JT_REF_OR_NULL) &&
+        !tab->table->maybe_null)
     {
       for (uint keypart= 0; keypart < tab->ref.key_parts; keypart++)
       {
@@ -5890,6 +5912,12 @@ make_join_select(JOIN *join,SQL_SELECT *
         tab->ref.key= -1;
 	tab->ref.key_parts=0;		// Don't use ref key.
 	join->best_positions[i].records_read= rows2double(tab->quick->records);
+        /* 
+          We will use join cache here : prevent sorting of the first
+          table only and sort at the end.
+        */
+        if (i != join->const_tables && join->tables > join->const_tables + 1)
+          join->full_join= 1;
       }
 
       tmp= NULL;
@@ -6172,11 +6200,14 @@ make_join_readinfo(JOIN *join, ulonglong
       disable join cache because it will change the ordering of the results.
       Code handles sort table that is at any location (not only first after 
       the const tables) despite the fact that it's currently prohibited.
+      We must disable join cache if the first non-const table alone is
+      ordered. If there is a temp table the ordering is done as a last
+      operation and doesn't prevent join cache usage.
     */
-    if (!ordered_set && 
-        (table == join->sort_by_table &&
+    if (!ordered_set && !join->need_tmp &&
+        ((table == join->sort_by_table &&
          (!join->order || join->skip_sort_order)) ||
-        (join->sort_by_table == (TABLE *) 1 && i != join->const_tables))
+        (join->sort_by_table == (TABLE *) 1 && i != join->const_tables)))
       ordered_set= 1;
 
     tab->sorted= sorted;
@@ -8875,17 +8906,13 @@ static bool
 test_if_equality_guarantees_uniqueness(Item *l, Item *r)
 {
   return r->const_item() &&
-    /* elements must be of the same result type */
-    (r->result_type() == l->result_type() ||
-    /* or dates compared to longs */
-     (((l->type() == Item::FIELD_ITEM &&
-        ((Item_field *)l)->field->can_be_compared_as_longlong()) ||
-       (l->type() == Item::FUNC_ITEM &&
-        ((Item_func *)l)->result_as_longlong())) &&
-      r->result_type() == INT_RESULT))
-    /* and must have the same collation if compared as strings */
-    && (l->result_type() != STRING_RESULT ||
-        l->collation.collation == r->collation.collation);
+    /* elements must be compared as dates */
+     (Arg_comparator::can_compare_as_dates(l, r, 0) ||
+      /* or of the same result type */
+      (r->result_type() == l->result_type() &&
+       /* and must have the same collation if compared as strings */
+       (l->result_type() != STRING_RESULT ||
+        l->collation.collation == r->collation.collation)));
 }
 
 /*
@@ -10789,7 +10816,6 @@ static enum_nested_loop_state
 evaluate_join_record(JOIN *join, JOIN_TAB *join_tab,
                      int error, my_bool *report_error)
 {
-  bool not_exists_optimize= join_tab->table->reginfo.not_exists_optimize;
   bool not_used_in_distinct=join_tab->not_used_in_distinct;
   ha_rows found_records=join->found_records;
   COND *select_cond= join_tab->select_cond;
@@ -10826,6 +10852,8 @@ evaluate_join_record(JOIN *join, JOIN_TA
       first_unmatched->found= 1;
       for (JOIN_TAB *tab= first_unmatched; tab <= join_tab; tab++)
       {
+        if (tab->table->reginfo.not_exists_optimize)
+          return NESTED_LOOP_NO_MORE_ROWS;
         /* Check all predicates that has just been activated. */
         /*
           Actually all predicates non-guarded by first_unmatched->found
@@ -10871,8 +10899,6 @@ evaluate_join_record(JOIN *join, JOIN_TA
     if (found)
     {
       enum enum_nested_loop_state rc;
-      if (not_exists_optimize)
-        return NESTED_LOOP_NO_MORE_ROWS;
       /* A match from join_tab is found for the current partial join. */
       rc= (*join_tab->next_select)(join, join_tab+1, 0);
       if (rc != NESTED_LOOP_OK && rc != NESTED_LOOP_NO_MORE_ROWS)
@@ -12659,6 +12685,12 @@ test_if_skip_sort_order(JOIN_TAB *tab,OR
     uint nr;
     key_map keys;
 
+    /* 
+      filesort() and join cache are usually faster than reading in 
+      index order and not using join cache
+    */
+    if (tab->type == JT_ALL && tab->join->tables > tab->join->const_tables + 1)
+      DBUG_RETURN(0);
     /*
       If not used with LIMIT, only use keys if the whole query can be
       resolved with a key;  This is because filesort() is usually faster than
@@ -14825,7 +14857,7 @@ bool JOIN::rollup_init()
     for (j=0 ; j < fields_list.elements ; j++)
       rollup.fields[i].push_back(rollup.null_items[i]);
   }
-  List_iterator_fast<Item> it(all_fields);
+  List_iterator<Item> it(all_fields);
   Item *item;
   while ((item= it++))
   {
@@ -14838,6 +14870,32 @@ bool JOIN::rollup_init()
       {
         item->maybe_null= 1;
         found_in_group= 1;
+        if (item->const_item())
+        {
+          /*
+            For ROLLUP queries each constant item referenced in GROUP BY list
+            is wrapped up into an Item_func object yielding the same value
+            as the constant item. The objects of the wrapper class are never
+            considered as constant items and besides they inherit all
+            properties of the Item_result_field class.
+            This wrapping allows us to ensure writing constant items
+            into temporary tables whenever the result of the ROLLUP
+            operation has to be written into a temporary table, e.g. when
+            ROLLUP is used together with DISTINCT in the SELECT list.
+            Usually when creating temporary tables for a intermidiate
+            result we do not include fields for constant expressions.
+	  */           
+          Item* new_item= new Item_func_rollup_const(item);
+          if (!new_item)
+            return 1;
+          new_item->fix_fields(thd, (Item **) 0);
+          thd->change_item_tree(it.ref(), new_item);
+          for (ORDER *tmp= group_tmp; tmp; tmp= tmp->next)
+          { 
+            if (*tmp->item == item)
+              thd->change_item_tree(tmp->item, new_item);
+          }
+        }
       }
     }
     if (item->type() == Item::FUNC_ITEM && !found_in_group)
@@ -15486,6 +15544,8 @@ static void select_describe(JOIN *join, 
             break;
           }
         }
+        if (tab->next_select == sub_select_cache)
+          extra.append(STRING_WITH_LEN("; Using join cache"));
         
         /* Skip initial "; "*/
         const char *str= extra.ptr();
@@ -15542,7 +15602,7 @@ bool mysql_explain_union(THD *thd, SELEC
 		 "UNION")));
     sl->options|= SELECT_DESCRIBE;
   }
-  if (first->next_select())
+  if (unit->is_union())
   {
     unit->fake_select_lex->select_number= UINT_MAX; // jost for initialization
     unit->fake_select_lex->type= "UNION RESULT";

--- 1.408/sql/sql_show.cc	2007-04-25 08:15:04 -04:00
+++ 1.409/sql/sql_show.cc	2007-05-07 16:58:22 -04:00
@@ -5915,6 +5915,8 @@ ST_SCHEMA_TABLE schema_tables[]=
     fill_plugins, make_old_format, 0, -1, -1, 0},
   {"PROCESSLIST", processlist_fields_info, create_schema_table,
     fill_schema_processlist, make_old_format, 0, -1, -1, 0},
+  {"PROFILING", query_profile_statistics_info, create_schema_table,
+    fill_query_profile_statistics_info, NULL, NULL, -1, -1, false},
   {"REFERENTIAL_CONSTRAINTS", referential_constraints_fields_info,
    create_schema_table, get_all_tables, 0, get_referential_constraints_record,
    1, 9, 0},

--- 1.413/sql/sql_table.cc	2007-05-01 04:38:07 -04:00
+++ 1.414/sql/sql_table.cc	2007-05-07 16:58:22 -04:00
@@ -3526,7 +3526,7 @@ bool mysql_create_table_internal(THD *th
     }
   }
 
-  thd->proc_info="creating table";
+  thd_proc_info(thd, "creating table");
   create_info->table_existed= 0;		// Mark that table is created
 
   if (thd->variables.sql_mode & MODE_NO_DIR_IN_CREATE)
@@ -3566,7 +3566,7 @@ unlock_and_end:
   VOID(pthread_mutex_unlock(&LOCK_open));
 
 err:
-  thd->proc_info="After create";
+  thd_proc_info(thd, "After create");
   delete file;
   DBUG_RETURN(error);
 
@@ -4948,7 +4948,7 @@ mysql_discard_or_import_tablespace(THD *
     ALTER TABLE
   */
 
-  thd->proc_info="discard_or_import_tablespace";
+  thd_proc_info(thd, "discard_or_import_tablespace");
 
   discard= test(tablespace_op == DISCARD_TABLESPACE);
 
@@ -4965,7 +4965,7 @@ mysql_discard_or_import_tablespace(THD *
 
   error=table->file->discard_or_import_tablespace(discard);
 
-  thd->proc_info="end";
+  thd_proc_info(thd, "end");
 
   if (error)
     goto err;
@@ -5412,7 +5412,7 @@ bool mysql_alter_table(THD *thd,char *ne
     }
   }
 
-  thd->proc_info="init";
+  thd_proc_info(thd, "init");
   if (!(create_info= copy_create_info(lex_create_info)))
   {
     DBUG_RETURN(TRUE);
@@ -5584,7 +5584,7 @@ view_err:
     DBUG_RETURN(TRUE);
   }
   
-  thd->proc_info="setup";
+  thd_proc_info(thd, "setup");
   if (!(alter_info->flags & ~(ALTER_RENAME | ALTER_KEYS_ONOFF)) &&
       !table->s->tmp_table) // no need to touch frm
   {
@@ -5639,7 +5639,7 @@ view_err:
 
     if (!error && (new_name != table_name || new_db != db))
     {
-      thd->proc_info="rename";
+      thd_proc_info(thd, "rename");
       /* Then do a 'simple' rename of the table */
       if (!access(new_name_buff,F_OK))
       {
@@ -6296,7 +6296,7 @@ view_err:
   /* Copy the data if necessary. */
   thd->count_cuted_fields= CHECK_FIELD_WARN;	// calc cuted fields
   thd->cuted_fields=0L;
-  thd->proc_info="copy to tmp table";
+  thd_proc_info(thd, "copy to tmp table");
   copied=deleted=0;
   if (new_table && !(new_table->file->ha_table_flags() & HA_NO_COPY_ON_ALTER))
   {
@@ -6521,7 +6521,7 @@ view_err:
     from the cache, free all locks, close the old table and remove it.
   */
 
-  thd->proc_info="rename result table";
+  thd_proc_info(thd, "rename result table");
   my_snprintf(old_name, sizeof(old_name), "%s2-%lx-%lx", tmp_file_prefix,
 	      current_pid, thd->thread_id);
   if (lower_case_table_names)
@@ -6696,7 +6696,7 @@ view_err:
     if (error)
       goto err;
   }
-  thd->proc_info="end";
+  thd_proc_info(thd, "end");
 
   ha_binlog_log_query(thd, create_info->db_type, LOGCOM_ALTER_TABLE,
                       thd->query, thd->query_length,

--- 1.239/sql/sql_update.cc	2007-04-27 20:15:51 -04:00
+++ 1.240/sql/sql_update.cc	2007-05-07 16:58:22 -04:00
@@ -162,7 +162,7 @@ int mysql_update(THD *thd,
        mysql_handle_derived(thd->lex, &mysql_derived_filling)))
     DBUG_RETURN(1);
 
-  thd->proc_info="init";
+  thd_proc_info(thd, "init");
   table= table_list->table;
 
   /* Calculate "table->covering_keys" based on the WHERE */
@@ -379,7 +379,7 @@ int mysql_update(THD *thd,
       else
         init_read_record_idx(&info, thd, table, 1, used_index);
 
-      thd->proc_info="Searching rows for update";
+      thd_proc_info(thd, "Searching rows for update");
       uint tmp_limit= limit;
 
       while (!(error=info.read_record(&info)) && !thd->killed)
@@ -446,7 +446,7 @@ int mysql_update(THD *thd,
   updated= found= 0;
   thd->count_cuted_fields= CHECK_FIELD_WARN;		/* calc cuted fields */
   thd->cuted_fields=0L;
-  thd->proc_info="Updating";
+  thd_proc_info(thd, "Updating");
 
   transactional_table= table->file->has_transactions();
   thd->no_trans_update.stmt= FALSE;
@@ -644,7 +644,7 @@ int mysql_update(THD *thd,
   table->file->try_semi_consistent_read(0);
   end_read_record(&info);
   delete select;
-  thd->proc_info= "end";
+  thd_proc_info(thd, "end");
   VOID(table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY));
 
   /*
@@ -1096,7 +1096,7 @@ int multi_update::prepare(List<Item> &no
 
   thd->count_cuted_fields= CHECK_FIELD_WARN;
   thd->cuted_fields=0L;
-  thd->proc_info="updating main table";
+  thd_proc_info(thd, "updating main table");
 
   tables_to_update= get_table_map(fields);
 
@@ -1665,11 +1665,11 @@ bool multi_update::send_eof()
 {
   char buff[STRING_BUFFER_USUAL_SIZE];
   ulonglong id;
-  thd->proc_info="updating reference tables";
+  thd_proc_info(thd, "updating reference tables");
 
   /* Does updates for the last n - 1 tables, returns 0 if ok */
   int local_error = (table_count) ? do_updates(0) : 0;
-  thd->proc_info= "end";
+  thd_proc_info(thd, "end");
 
   /* We must invalidate the query cache before binlog writing and
   ha_autocommit_... */

--- 1.565/sql/sql_yacc.yy	2007-04-27 16:43:24 -04:00
+++ 1.566/sql/sql_yacc.yy	2007-05-07 16:58:23 -04:00
@@ -7829,7 +7829,7 @@ order_clause:
               yet.
             */
             SELECT_LEX *first_sl= unit->first_select();
-            if (!first_sl->next_select() &&
+            if (!unit->is_union() &&
                 (first_sl->order_list.elements || 
                  first_sl->select_limit) &&            
                 unit->add_fake_select_lex(lex->thd))

--- 1.167/sql/table.h	2007-04-25 08:15:04 -04:00
+++ 1.168/sql/table.h	2007-05-07 16:58:23 -04:00
@@ -535,6 +535,7 @@ enum enum_schema_tables
   SCH_PARTITIONS,
   SCH_PLUGINS,
   SCH_PROCESSLIST,
+  SCH_PROFILING,
   SCH_REFERENTIAL_CONSTRAINTS,
   SCH_PROCEDURES,
   SCH_SCHEMATA,

--- 1.192/support-files/mysql.spec.sh	2007-04-27 16:43:25 -04:00
+++ 1.193/support-files/mysql.spec.sh	2007-05-07 16:58:23 -04:00
@@ -549,7 +549,7 @@ fi
 %doc %attr(644, root, man) %{_mandir}/man1/mysqld_multi.1*
 %doc %attr(644, root, man) %{_mandir}/man1/mysqld_safe.1*
 %doc %attr(644, root, man) %{_mandir}/man1/mysql_fix_privilege_tables.1*
-%doc %attr(644, root, man) %{_mandir}/man1/mysql_install_db.1
+%doc %attr(644, root, man) %{_mandir}/man1/mysql_install_db.1*
 %doc %attr(644, root, man) %{_mandir}/man1/mysql_upgrade.1*
 %doc %attr(644, root, man) %{_mandir}/man1/mysqlhotcopy.1*
 %doc %attr(644, root, man) %{_mandir}/man1/mysqlman.1*
@@ -655,7 +655,6 @@ fi
 %attr(755, root, root) %{_bindir}/ndb_size.pl
 %attr(755, root, root) %{_bindir}/ndb_test_platform
 %attr(755, root, root) %{_bindir}/ndb_waiter
-%attr(-, root, root) %{_datadir}/mysql/ndb_size.tmpl
 %doc %attr(644, root, man) %{_mandir}/man1/ndb_config.1*
 %doc %attr(644, root, man) %{_mandir}/man1/ndb_desc.1*
 %doc %attr(644, root, man) %{_mandir}/man1/ndb_error_reporter.1*
@@ -731,6 +730,11 @@ fi
 # itself - note that they must be ordered by date (important when
 # merging BK trees)
 %changelog
+* Wed May 02 2007 Joerg Bruehe <joerg@stripped>
+
+- "ndb_size.tmpl" is not needed any more, 
+  "man1/mysql_install_db.1" lacked the trailing '*'.
+
 * Sat Apr 07 2007 Kent Boortz <kent@stripped>
 
 - Removed man page for "mysql_create_system_tables"

--- 1.132/sql/sql_view.cc	2007-04-24 09:03:03 -04:00
+++ 1.133/sql/sql_view.cc	2007-05-07 16:58:22 -04:00
@@ -602,7 +602,7 @@ bool mysql_create_view(THD *thd, TABLE_L
   DBUG_RETURN(0);
 
 err:
-  thd->proc_info= "end";
+  thd_proc_info(thd, "end");
   lex->link_first_table_back(view, link_to_local);
   unit->cleanup();
   DBUG_RETURN(res || thd->net.report_error);

--- 1.152/mysql-test/r/information_schema.result	2007-04-27 16:43:23 -04:00
+++ 1.153/mysql-test/r/information_schema.result	2007-05-07 16:58:19 -04:00
@@ -290,7 +290,7 @@ explain select a.ROUTINE_NAME from infor
 information_schema.SCHEMATA b where
 a.ROUTINE_SCHEMA = b.SCHEMA_NAME;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	SIMPLE	#	ALL	NULL	NULL	NULL	NULL	2	
+1	SIMPLE	#	ALL	NULL	NULL	NULL	NULL	2	Using join cache
 1	SIMPLE	#	ALL	NULL	NULL	NULL	NULL	2	Using where
 select a.ROUTINE_NAME, b.name from information_schema.ROUTINES a,
 mysql.proc b where a.ROUTINE_NAME = convert(b.name using utf8) order by 1;

--- 1.113/libmysqld/Makefile.am	2007-05-02 08:05:42 -04:00
+++ 1.114/libmysqld/Makefile.am	2007-05-07 16:58:19 -04:00
@@ -59,6 +59,7 @@ sqlsources = derror.cc field.cc field_co
 	protocol.cc net_serv.cc opt_range.cc \
 	opt_sum.cc procedure.cc records.cc sql_acl.cc \
 	sql_load.cc discover.cc sql_locale.cc \
+	sql_profile.cc \
 	sql_analyse.cc sql_base.cc sql_cache.cc sql_class.cc \
 	sql_crypt.cc sql_db.cc sql_delete.cc sql_error.cc sql_insert.cc \
 	sql_lex.cc sql_list.cc sql_manager.cc sql_map.cc \
Thread
bk commit into 5.1 tree (cmiller:1.2479)Chad MILLER7 May