List:Internals« Previous MessageNext Message »
From:guilhem Date:November 18 2005 3:39pm
Subject:bk commit into 5.1 tree (guilhem:1.1961)
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 repository of guilhem. When guilhem 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
  1.1961 05/11/18 16:38:01 guilhem@stripped +42 -0
  Merge mysql.com:/home/mysql_src/mysql-5.0
  into  mysql.com:/home/mysql_src/mysql-5.1-merge-of-5.0 (not all files are good,
  I'll fix; I'll ask some devs to check their part)

  storage/ndb/src/ndbapi/NdbRecAttr.cpp
    1.25 05/11/18 16:37:56 guilhem@stripped +3 -0
    merge

  sql/sql_yacc.yy
    1.421 05/11/18 16:37:56 guilhem@stripped +3 -4
    merge

  sql/sql_show.cc
    1.278 05/11/18 16:37:56 guilhem@stripped +3 -3
    merge (bad, will fix)

  sql/share/errmsg.txt
    1.53 05/11/18 16:37:56 guilhem@stripped +2 -8
    merge (bad, will fix)

  sql/set_var.cc
    1.145 05/11/18 16:37:56 guilhem@stripped +0 -3
    merge

  sql/log.cc
    1.175 05/11/18 16:37:56 guilhem@stripped +1 -2
    merge

  sql/handler.h
    1.166 05/11/18 16:37:56 guilhem@stripped +2 -2
    merge

  sql/ha_innodb.cc
    1.236 05/11/18 16:37:55 guilhem@stripped +0 -2
    merge

  sql/examples/ha_tina.cc
    1.22 05/11/18 16:37:55 guilhem@stripped +0 -0
    merge

  mysql-test/r/ps_1general.result
    1.53 05/11/18 16:37:55 guilhem@stripped +0 -0
    merge ("ul", will fix)

  configure.in
    1.309 05/11/18 16:37:55 guilhem@stripped +0 -2
    merge

  support-files/mysql.spec.sh
    1.116 05/11/18 16:06:35 guilhem@stripped +0 -0
    Auto merged

  storage/ndb/src/ndbapi/ndb_cluster_connection.cpp
    1.34 05/11/18 16:06:35 guilhem@stripped +0 -0
    Auto merged

  storage/ndb/src/ndbapi/NdbImpl.hpp
    1.15 05/11/18 16:06:35 guilhem@stripped +0 -0
    Auto merged

  storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
    1.94 05/11/18 16:06:35 guilhem@stripped +0 -0
    Auto merged

  storage/myisam/mi_key.c
    1.46 05/11/18 16:06:35 guilhem@stripped +0 -0
    Auto merged

  sql/table.h
    1.116 05/11/18 16:06:35 guilhem@stripped +0 -0
    Auto merged

  sql/sql_table.cc
    1.277 05/11/18 16:06:35 guilhem@stripped +0 -0
    Auto merged

  sql/sql_select.h
    1.100 05/11/18 16:06:35 guilhem@stripped +0 -0
    Auto merged

  sql/sql_select.cc
    1.368 05/11/18 16:06:34 guilhem@stripped +0 -0
    Auto merged

  sql/sql_repl.cc
    1.144 05/11/18 16:06:34 guilhem@stripped +0 -0
    Auto merged

  sql/sql_prepare.cc
    1.154 05/11/18 16:06:34 guilhem@stripped +0 -0
    Auto merged

  sql/sql_parse.cc
    1.482 05/11/18 16:06:34 guilhem@stripped +0 -0
    Auto merged

  sql/sql_lex.h
    1.205 05/11/18 16:06:34 guilhem@stripped +0 -0
    Auto merged

  sql/sql_lex.cc
    1.165 05/11/18 16:06:34 guilhem@stripped +0 -0
    Auto merged

  sql/sql_class.h
    1.268 05/11/18 16:06:33 guilhem@stripped +0 -0
    Auto merged

  sql/sql_acl.cc
    1.159 05/11/18 16:06:33 guilhem@stripped +0 -0
    Auto merged

  sql/sp_head.cc
    1.195 05/11/18 16:06:33 guilhem@stripped +0 -0
    Auto merged

  sql/sp.cc
    1.94 05/11/18 16:06:33 guilhem@stripped +0 -0
    Auto merged

  sql/set_var.h
    1.75 05/11/18 16:06:33 guilhem@stripped +0 -0
    Auto merged

  sql/opt_range.cc
    1.182 05/11/18 16:06:33 guilhem@stripped +0 -0
    Auto merged

  sql/mysqld.cc
    1.492 05/11/18 16:06:33 guilhem@stripped +0 -0
    Auto merged

  sql/mysql_priv.h
    1.343 05/11/18 16:06:32 guilhem@stripped +0 -0
    Auto merged

  sql/item.cc
    1.152 05/11/18 16:06:32 guilhem@stripped +0 -0
    Auto merged

  sql/field.cc
    1.288 05/11/18 16:06:32 guilhem@stripped +0 -0
    Auto merged

  scripts/mysql_fix_privilege_tables.sql
    1.28 05/11/18 16:06:32 guilhem@stripped +0 -0
    Auto merged

  mysql-test/t/view.test
    1.123 05/11/18 16:06:32 guilhem@stripped +0 -0
    Auto merged

  mysql-test/r/information_schema.result
    1.89 05/11/18 16:06:32 guilhem@stripped +0 -0
    Auto merged

  mysql-test/mysql-test-run.sh
    1.279 05/11/18 16:06:32 guilhem@stripped +0 -0
    Auto merged

  mysql-test/mysql-test-run.pl
    1.41 05/11/18 16:06:32 guilhem@stripped +0 -0
    Auto merged

  storage/ndb/src/ndbapi/ndb_cluster_connection.cpp
    1.29.3.2 05/11/18 16:06:31 guilhem@stripped +0 -0
    Merge rename: ndb/src/ndbapi/ndb_cluster_connection.cpp -> storage/ndb/src/ndbapi/ndb_cluster_connection.cpp

  storage/ndb/src/ndbapi/NdbRecAttr.cpp
    1.20.3.2 05/11/18 16:06:31 guilhem@stripped +0 -0
    Merge rename: ndb/src/ndbapi/NdbRecAttr.cpp -> storage/ndb/src/ndbapi/NdbRecAttr.cpp

  storage/ndb/src/ndbapi/NdbImpl.hpp
    1.8.5.2 05/11/18 16:06:31 guilhem@stripped +0 -0
    Merge rename: ndb/src/ndbapi/NdbImpl.hpp -> storage/ndb/src/ndbapi/NdbImpl.hpp

  storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
    1.73.11.3 05/11/18 16:06:31 guilhem@stripped +0 -0
    Merge rename: ndb/src/kernel/blocks/dbtc/DbtcMain.cpp -> storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp

  storage/myisam/mi_key.c
    1.38.8.3 05/11/18 16:06:31 guilhem@stripped +0 -0
    Merge rename: myisam/mi_key.c -> storage/myisam/mi_key.c

  include/my_global.h
    1.114 05/11/18 16:06:31 guilhem@stripped +0 -0
    Auto merged

  BitKeeper/etc/ignore
    1.214 05/11/18 16:06:24 guilhem@stripped +139 -139
    auto-union

# 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:	guilhem
# Host:	gbichot3.local
# Root:	/home/mysql_src/mysql-5.1-merge-of-5.0/RESYNC

--- 1.308/configure.in	2005-11-08 07:36:52 +01:00
+++ 1.309/configure.in	2005-11-18 16:37:55 +01:00
@@ -311,6 +311,10 @@
       # Use the built-in alloca()
       CFLAGS="$CFLAGS -Kalloca"
       CXXFLAGS="$CFLAGS -Kalloca"
+      # Use no_implicit for templates
+      CXXFLAGS="$CXXFLAGS -Tno_implicit"
+      AC_DEFINE([HAVE_EXPLICIT_TEMPLATE_INSTANTIATION],
+        [1], [Defined by configure. Use explicit template instantiation.])
     fi
   ;;
 esac

--- 1.278/mysql-test/mysql-test-run.sh	2005-11-04 21:09:53 +01:00
+++ 1.279/mysql-test/mysql-test-run.sh	2005-11-18 16:06:32 +01:00
@@ -1275,7 +1275,7 @@
           --language=$LANGUAGE \
           --innodb_data_file_path=ibdata1:128M:autoextend \
 	  --open-files-limit=1024 \
-          --log-bin-trust-routine-creators \
+          --log-bin-trust-function-creators \
 	   $MASTER_40_ARGS \
            $SMALL_SERVER \
            $EXTRA_MASTER_OPT $EXTRA_MASTER_MYSQLD_OPT \
@@ -1296,7 +1296,7 @@
           --tmpdir=$MYSQL_TMP_DIR \
           --language=$LANGUAGE \
           --innodb_data_file_path=ibdata1:128M:autoextend \
-          --log-bin-trust-routine-creators \
+          --log-bin-trust-function-creators \
 	   $MASTER_40_ARGS \
            $SMALL_SERVER \
            $EXTRA_MASTER_OPT $EXTRA_MASTER_MYSQLD_OPT \
@@ -1429,7 +1429,7 @@
           --report-port=$slave_port \
           --master-retry-count=10 \
           -O slave_net_timeout=10 \
-          --log-bin-trust-routine-creators \
+          --log-bin-trust-function-creators \
            $SMALL_SERVER \
            $EXTRA_SLAVE_OPT $EXTRA_SLAVE_MYSQLD_OPT"
   CUR_MYERR=$slave_err

--- 1.287/sql/field.cc	2005-11-04 21:09:54 +01:00
+++ 1.288/sql/field.cc	2005-11-18 16:06:32 +01:00
@@ -6224,9 +6224,16 @@
     This is done to ensure that ALTER TABLE will convert old VARCHAR fields
     to now VARCHAR fields.
   */
-  return new Field_varstring(field_length, maybe_null(),
-                             field_name, new_table,
-                             charset());
+  Field *new_field= new Field_varstring(field_length, maybe_null(),
+                                        field_name, new_table,
+                                        charset());
+  /*
+    delayed_insert::get_local_table() needs a ptr copied from old table.
+    This is what other new_field() methods do too. The above method of
+    Field_varstring sets ptr to NULL.
+  */
+  new_field->ptr= ptr;
+  return new_field;
 }
 
 /****************************************************************************
@@ -7986,7 +7993,7 @@
 {
   int delta;
 
-  for (; !*from && length; from++, length--);          // skip left 0's
+  for (; length && !*from; from++, length--);          // skip left 0's
   delta= field_length - length;
 
   if (delta < -1 ||
@@ -8235,7 +8242,7 @@
   int delta;
   uchar bits= create_length & 7;
 
-  for (; !*from && length; from++, length--);          // skip left 0's
+  for (; length && !*from; from++, length--);          // skip left 0's
   delta= field_length - length;
 
   if (delta < 0 ||

--- 1.165/sql/handler.h	2005-11-07 16:24:40 +01:00
+++ 1.166/sql/handler.h	2005-11-18 16:37:56 +01:00
@@ -42,6 +42,7 @@
 #define HA_ADMIN_REJECT          -6
 #define HA_ADMIN_TRY_ALTER       -7
 #define HA_ADMIN_WRONG_CHECKSUM  -8
+#define HA_ADMIN_NOT_BASE_TABLE  -9
 
 /* Bits in table_flags() to show what database can do */
 
@@ -431,10 +432,11 @@
 /* Possible flags of a handlerton */
 #define HTON_NO_FLAGS                 0
 #define HTON_CLOSE_CURSORS_AT_COMMIT (1 << 0)
-#define HTON_ALTER_NOT_SUPPORTED     (1 << 1)
-#define HTON_CAN_RECREATE            (1 << 2)
-#define HTON_FLUSH_AFTER_RENAME      (1 << 3)
-#define HTON_NOT_USER_SELECTABLE     (1 << 4)
+#define HTON_ALTER_NOT_SUPPORTED     (1 << 1) //Engine does not support alter
+#define HTON_CAN_RECREATE            (1 << 2) //Delete all is used fro truncate
+#define HTON_HIDDEN                  (1 << 3) //Engine does not appear in lists
+#define HTON_FLUSH_AFTER_RENAME      (1 << 4)
+#define HTON_NOT_USER_SELECTABLE     (1 << 5)
 
 typedef struct st_thd_trans
 {

--- 1.151/sql/item.cc	2005-11-04 21:09:54 +01:00
+++ 1.152/sql/item.cc	2005-11-18 16:06:32 +01:00
@@ -4943,8 +4943,7 @@
 }
 
 /*
-  Compare view field's name with item's name before call to referenced
-  item's eq()
+  Compare two view column references for equality.
 
   SYNOPSIS
     Item_direct_view_ref::eq()
@@ -4952,12 +4951,13 @@
     binary_cmp  make binary comparison
 
   DESCRIPTION
-    Consider queries:
-    create view v1 as select t1.f1 as f2, t1.f2 as f1 from t1;
-    select * from v1 order by f1;
-    In order to choose right field for sorting we need to compare
-    given item's name (f1) to view field's name prior to calling
-    referenced item's eq().
+    A view column reference is considered equal to another column
+    reference if the second one is a view column and if both column
+    references point to the same field. For views 'same field' means
+    the same Item_field object in the view translation table, where
+    the view translation table contains all result columns of the
+    view. This definition ensures that view columns are resolved
+    in the same manner as table columns.
 
   RETURN
     TRUE    Referenced item is equal to given item
@@ -4967,9 +4967,18 @@
 
 bool Item_direct_view_ref::eq(const Item *item, bool binary_cmp) const
 {
-  Item *it= ((Item *) item)->real_item();
-  return (!it->name || !my_strcasecmp(system_charset_info, it->name,
-          field_name)) && ref && (*ref)->real_item()->eq(it, binary_cmp);
+  if (item->type() == REF_ITEM)
+  {
+    Item_ref *item_ref= (Item_ref*) item;
+    if (item_ref->ref_type() == VIEW_REF)
+    {
+      Item *item_ref_ref= *(item_ref->ref);
+      DBUG_ASSERT((*ref)->type() == FIELD_ITEM &&
+                  (item_ref_ref->type() == FIELD_ITEM));
+      return (*ref == item_ref_ref);
+    }
+  }
+  return FALSE;
 }
 
 void Item_null_helper::print(String *str)

--- 1.174/sql/log.cc	2005-11-07 16:24:41 +01:00
+++ 1.175/sql/log.cc	2005-11-18 16:37:56 +01:00
@@ -77,7 +77,7 @@
   NULL,                         /* Flush logs */
   NULL,                         /* Show status */
   NULL,                         /* Replication Report Sent Binlog */
-  HTON_NOT_USER_SELECTABLE
+  HTON_NOT_USER_SELECTABLE | HTON_HIDDEN
 };
 
 
@@ -368,8 +368,7 @@
 MYSQL_LOG::MYSQL_LOG()
   :bytes_written(0), last_time(0), query_start(0), name(0),
    prepared_xids(0), log_type(LOG_CLOSED), file_id(1), open_count(1),
-   readers_count(0), reset_pending(FALSE), write_error(FALSE), inited(FALSE),
-   need_start_event(TRUE),
+   write_error(FALSE), inited(FALSE), need_start_event(TRUE),
    description_event_for_exec(0), description_event_for_queue(0)
 {
   /*
@@ -396,9 +395,7 @@
     delete description_event_for_exec;
     (void) pthread_mutex_destroy(&LOCK_log);
     (void) pthread_mutex_destroy(&LOCK_index);
-    (void) pthread_mutex_destroy(&LOCK_readers);
     (void) pthread_cond_destroy(&update_cond);
-    (void) pthread_cond_destroy(&reset_cond);
   }
   DBUG_VOID_RETURN;
 }
@@ -443,9 +440,7 @@
   inited= 1;
   (void) pthread_mutex_init(&LOCK_log,MY_MUTEX_INIT_SLOW);
   (void) pthread_mutex_init(&LOCK_index, MY_MUTEX_INIT_SLOW);
-  (void) pthread_mutex_init(&LOCK_readers, MY_MUTEX_INIT_SLOW);
   (void) pthread_cond_init(&update_cond, 0);
-  (void) pthread_cond_init(&reset_cond, 0);
 }
 
 const char *MYSQL_LOG::generate_name(const char *log_name,
@@ -949,12 +944,6 @@
   pthread_mutex_lock(&LOCK_log);
   pthread_mutex_lock(&LOCK_index);
 
-  /* 
-    we need one more lock to block attempts to open a log while
-    we are waiting untill all log files will be closed
-  */
-  pthread_mutex_lock(&LOCK_readers);
-
   /*
     The following mutex is needed to ensure that no threads call
     'delete thd' as we would then risk missing a 'rollback' from this
@@ -977,19 +966,6 @@
     goto err;
   }
 
-  reset_pending= TRUE;
-  /* 
-    send update signal just in case so that all reader threads waiting
-    for log update will leave wait condition
-  */
-  signal_update();
-  /* 
-    if there are active readers wait until all of them will 
-    release opened files 
-  */
-  while (readers_count)
-    pthread_cond_wait(&reset_cond, &LOCK_log);
-
   for (;;)
   {
     my_delete(linfo.log_file_name, MYF(MY_WME));
@@ -1008,10 +984,7 @@
   my_free((gptr) save_name, MYF(0));
 
 err:
-  reset_pending= FALSE;
-
   (void) pthread_mutex_unlock(&LOCK_thread_count);
-  pthread_mutex_unlock(&LOCK_readers);
   pthread_mutex_unlock(&LOCK_index);
   pthread_mutex_unlock(&LOCK_log);
   DBUG_RETURN(error);
@@ -2085,12 +2058,6 @@
 {
   const char *old_msg;
   DBUG_ENTER("wait_for_update");
-  
-  if (reset_pending)
-  {
-    pthread_mutex_unlock(&LOCK_log);
-    DBUG_VOID_RETURN;
-  }
 
   old_msg= thd->enter_cond(&update_cond, &LOCK_log,
                            is_slave ?
@@ -2339,33 +2306,6 @@
 {
   DBUG_ENTER("MYSQL_LOG::signal_update");
   pthread_cond_broadcast(&update_cond);
-  DBUG_VOID_RETURN;
-}
-
-void MYSQL_LOG::readers_addref()
-{
-  /* 
-    There is no necessity for reference counting on *nix, since it allows to
-    delete opened files, however it is more clean way to wait
-    untill all files will be closed on *nix as well.
-  */
-  DBUG_ENTER("MYSQL_LOG::reader_addref");
-  pthread_mutex_lock(&LOCK_log);
-  pthread_mutex_lock(&LOCK_readers);
-  readers_count++;
-  pthread_mutex_unlock(&LOCK_readers);
-  pthread_mutex_unlock(&LOCK_log);
-  DBUG_VOID_RETURN;
-}
-
-void MYSQL_LOG::readers_release()
-{
-  DBUG_ENTER("MYSQL_LOG::reader_release");
-  pthread_mutex_lock(&LOCK_log);
-  readers_count--;
-  if (!readers_count)
-    pthread_cond_broadcast(&reset_cond);
-  pthread_mutex_unlock(&LOCK_log);
   DBUG_VOID_RETURN;
 }
 

--- 1.342/sql/mysql_priv.h	2005-11-10 18:42:30 +01:00
+++ 1.343/sql/mysql_priv.h	2005-11-18 16:06:32 +01:00
@@ -44,6 +44,12 @@
 typedef ulonglong table_map;          /* Used for table bits in join */
 typedef Bitmap<64> key_map;           /* Used for finding keys */
 typedef ulong key_part_map;           /* Used for finding key parts */
+/*
+  Used to identify NESTED_JOIN structures within a join (applicable only to
+  structures that have not been simplified away and embed more the one
+  element)
+*/
+typedef ulonglong nested_join_map;
 
 /* query_id */
 typedef ulonglong query_id_t;
@@ -519,8 +525,9 @@
 bool insert_precheck(THD *thd, TABLE_LIST *tables);
 bool create_table_precheck(THD *thd, TABLE_LIST *tables,
                            TABLE_LIST *create_table);
-bool default_view_definer(Security_context *sctx, st_lex_user *definer);
 
+bool get_default_definer(THD *thd, LEX_USER *definer);
+LEX_USER *create_definer(THD *thd, LEX_STRING *user_name, LEX_STRING *host_name);
 
 enum enum_mysql_completiontype {
   ROLLBACK_RELEASE=-2, ROLLBACK=1,  ROLLBACK_AND_CHAIN=7,
@@ -863,6 +870,10 @@
 bool mysqld_help (THD *thd, const char *text);
 void calc_sum_of_all_status(STATUS_VAR *to);
 
+void append_definer(THD *thd, String *buffer, const LEX_STRING *definer_user,
+                    const LEX_STRING *definer_host);
+
+
 /* information schema */
 extern LEX_STRING information_schema_name;
 LEX_STRING *make_lex_string(THD *thd, LEX_STRING *lex_str,
@@ -1199,7 +1210,7 @@
 extern my_bool opt_secure_auth;
 extern my_bool opt_log_slow_admin_statements;
 extern my_bool sp_automatic_privileges, opt_noacl;
-extern my_bool opt_old_style_user_limits, trust_routine_creators;
+extern my_bool opt_old_style_user_limits, trust_function_creators;
 extern uint opt_crash_binlog_innodb;
 extern char *shared_memory_base_name, *mysqld_unix_port;
 extern my_bool opt_enable_shared_memory;

--- 1.491/sql/mysqld.cc	2005-11-17 15:01:25 +01:00
+++ 1.492/sql/mysqld.cc	2005-11-18 16:06:33 +01:00
@@ -424,7 +424,7 @@
 my_bool lower_case_file_system= 0;
 my_bool opt_large_pages= 0;
 uint    opt_large_page_size= 0;
-my_bool opt_old_style_user_limits= 0, trust_routine_creators= 0;
+my_bool opt_old_style_user_limits= 0, trust_function_creators= 0;
 /*
   True if there is at least one per-hour limit for some user, so we should
   check them before each query (and possibly reset counters when hour is
@@ -615,7 +615,7 @@
 static const char* default_dbug_option;
 #endif
 #ifdef HAVE_LIBWRAP
-char *libwrapName= NULL;
+const char *libwrapName= NULL;
 #endif
 #ifdef HAVE_QUERY_CACHE
 static ulong query_cache_limit= 0;
@@ -4501,7 +4501,7 @@
   OPT_INNODB_FAST_SHUTDOWN,
   OPT_INNODB_FILE_PER_TABLE, OPT_CRASH_BINLOG_INNODB,
   OPT_INNODB_LOCKS_UNSAFE_FOR_BINLOG,
-  OPT_LOG_BIN_TRUST_ROUTINE_CREATORS,
+  OPT_LOG_BIN_TRUST_FUNCTION_CREATORS,
   OPT_SAFE_SHOW_DB, OPT_INNODB_SAFE_BINLOG,
   OPT_INNODB, OPT_ISAM,
   OPT_ENGINE_CONDITION_PUSHDOWN,
@@ -4933,16 +4933,27 @@
    "File that holds the names for last binary log files.",
    (gptr*) &opt_binlog_index_name, (gptr*) &opt_binlog_index_name, 0, GET_STR,
    REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+#ifndef TO_BE_REMOVED_IN_5_1_OR_6_0
+  /*
+    In 5.0.6 we introduced the below option, then in 5.0.16 we renamed it to
+    log-bin-trust-function-creators but kept also the old name for
+    compatibility; the behaviour was also changed to apply only to functions
+    (and triggers). In a future release this old name could be removed.
+  */
+  {"log-bin-trust-routine-creators", OPT_LOG_BIN_TRUST_FUNCTION_CREATORS,
+   "(deprecated) Use log-bin-trust-function-creators.",
+   (gptr*) &trust_function_creators, (gptr*) &trust_function_creators, 0,
+   GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+#endif
   /*
     This option starts with "log-bin" to emphasize that it is specific of
-    binary logging. Hopefully in 5.1 nobody will need it anymore, when we have
-    row-level binlog.
+    binary logging.
   */
-  {"log-bin-trust-routine-creators", OPT_LOG_BIN_TRUST_ROUTINE_CREATORS,
+  {"log-bin-trust-function-creators", OPT_LOG_BIN_TRUST_FUNCTION_CREATORS,
    "If equal to 0 (the default), then when --log-bin is used, creation of "
-   "a routine is allowed only to users having the SUPER privilege and only"
-   "if this routine may not break binary logging",
-   (gptr*) &trust_routine_creators, (gptr*) &trust_routine_creators, 0,
+   "a function is allowed only to users having the SUPER privilege and only "
+   "if this function may not break binary logging.",
+   (gptr*) &trust_function_creators, (gptr*) &trust_function_creators, 0,
    GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
   {"log-error", OPT_ERROR_LOG_FILE, "Error log file.",
    (gptr*) &log_error_file_ptr, (gptr*) &log_error_file_ptr, 0, GET_STR,
@@ -5840,7 +5851,7 @@
    (gptr*) &max_system_variables.read_buff_size,0, GET_ULONG, REQUIRED_ARG,
    128*1024L, IO_SIZE*2+MALLOC_OVERHEAD, ~0L, MALLOC_OVERHEAD, IO_SIZE, 0},
   {"read_only", OPT_READONLY,
-   "Make all tables readonly, with the exception for replication (slave) threads and users with the SUPER privilege",
+   "Make all non-temporary tables read-only, with the exception for replication (slave) threads and users with the SUPER privilege",
    (gptr*) &opt_readonly,
    (gptr*) &opt_readonly,
    0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 1, 0},

--- 1.181/sql/opt_range.cc	2005-11-04 21:09:55 +01:00
+++ 1.182/sql/opt_range.cc	2005-11-18 16:06:33 +01:00
@@ -5764,10 +5764,17 @@
   MEM_ROOT *old_root= thd->mem_root;
   /* The following call may change thd->mem_root */
   QUICK_RANGE_SELECT *quick= new QUICK_RANGE_SELECT(thd, table, ref->key, 0);
+  /* save mem_root set by QUICK_RANGE_SELECT constructor */
+  MEM_ROOT *alloc= thd->mem_root;
   KEY *key_info = &table->key_info[ref->key];
   KEY_PART *key_part;
   QUICK_RANGE *range;
   uint part;
+  /*
+    return back default mem_root (thd->mem_root) changed by
+    QUICK_RANGE_SELECT constructor
+  */
+  thd->mem_root= old_root;
 
   if (!quick)
     return 0;			/* no ranges found */
@@ -5779,7 +5786,7 @@
   quick->records= records;
 
   if (cp_buffer_from_ref(thd,ref) && thd->is_fatal_error ||
-      !(range= new QUICK_RANGE()))
+      !(range= new(alloc) QUICK_RANGE()))
     goto err;                                   // out of memory
 
   range->min_key=range->max_key=(char*) ref->key_buff;
@@ -5814,20 +5821,20 @@
     QUICK_RANGE *null_range;
 
     *ref->null_ref_key= 1;		// Set null byte then create a range
-    if (!(null_range= new QUICK_RANGE((char*)ref->key_buff, ref->key_length,
-				      (char*)ref->key_buff, ref->key_length,
-				      EQ_RANGE)))
+    if (!(null_range= new (alloc) QUICK_RANGE((char*)ref->key_buff,
+                                              ref->key_length,
+                                              (char*)ref->key_buff,
+                                              ref->key_length,
+                                              EQ_RANGE)))
       goto err;
     *ref->null_ref_key= 0;		// Clear null byte
     if (insert_dynamic(&quick->ranges,(gptr)&null_range))
       goto err;
   }
 
-  thd->mem_root= old_root;
   return quick;
 
 err:
-  thd->mem_root= old_root;
   delete quick;
   return 0;
 }

--- 1.158/sql/sql_acl.cc	2005-11-04 21:09:56 +01:00
+++ 1.159/sql/sql_acl.cc	2005-11-18 16:06:33 +01:00
@@ -3532,7 +3532,7 @@
     of other queries). For simple queries first_not_own_table is 0.
   */
   for (i= 0, table= tables;
-       table != first_not_own_table && i < number;
+       table && table != first_not_own_table && i < number;
        table= table->next_global, i++)
   {
     /* Remove SHOW_VIEW_ACL, because it will be checked during making view */

--- 1.267/sql/sql_class.h	2005-11-07 16:24:42 +01:00
+++ 1.268/sql/sql_class.h	2005-11-18 16:06:33 +01:00
@@ -189,11 +189,10 @@
 {
  private:
   /* LOCK_log and LOCK_index are inited by init_pthread_objects() */
-  pthread_mutex_t LOCK_log, LOCK_index, LOCK_readers;
+  pthread_mutex_t LOCK_log, LOCK_index;
   pthread_mutex_t LOCK_prep_xids;
   pthread_cond_t  COND_prep_xids;
   pthread_cond_t update_cond;
-  pthread_cond_t reset_cond;
   ulonglong bytes_written;
   time_t last_time,query_start;
   IO_CACHE log_file;
@@ -335,9 +334,6 @@
   int purge_logs_before_date(time_t purge_time);
   int purge_first_log(struct st_relay_log_info* rli, bool included);
   bool reset_logs(THD* thd);
-  inline bool is_reset_pending() { return reset_pending; }
-  void readers_addref();
-  void readers_release();
   void close(uint exiting);
 
   // iterating through the log index file

--- 1.164/sql/sql_lex.cc	2005-11-06 01:36:18 +01:00
+++ 1.165/sql/sql_lex.cc	2005-11-18 16:06:34 +01:00
@@ -2040,6 +2040,35 @@
 
 
 /*
+  Do end-of-prepare fixup for list of tables and their merge-VIEWed tables
+
+  SYNOPSIS
+    fix_prepare_info_in_table_list()
+      thd  Thread handle
+      tbl  List of tables to process
+
+  DESCRIPTION
+    Perform end-end-of prepare fixup for list of tables, if any of the tables
+    is a merge-algorithm VIEW, recursively fix up its underlying tables as
+    well.
+
+*/
+
+static void fix_prepare_info_in_table_list(THD *thd, TABLE_LIST *tbl)
+{
+  for (; tbl; tbl= tbl->next_local)
+  {
+    if (tbl->on_expr)
+    {
+      tbl->prep_on_expr= tbl->on_expr;
+      tbl->on_expr= tbl->on_expr->copy_andor_structure(thd);
+    }
+    fix_prepare_info_in_table_list(thd, tbl->merge_underlying_list);
+  }
+}
+
+
+/*
   fix some structures at the end of preparation
 
   SYNOPSIS
@@ -2058,16 +2087,7 @@
       prep_where= *conds;
       *conds= where= prep_where->copy_andor_structure(thd);
     }
-    for (TABLE_LIST *tbl= (TABLE_LIST *)table_list.first;
-         tbl;
-         tbl= tbl->next_local)
-    {
-      if (tbl->on_expr)
-      {
-        tbl->prep_on_expr= tbl->on_expr;
-        tbl->on_expr= tbl->on_expr->copy_andor_structure(thd);
-      }
-    }
+    fix_prepare_info_in_table_list(thd, (TABLE_LIST *)table_list.first);
   }
 }
 

--- 1.204/sql/sql_lex.h	2005-11-10 18:42:31 +01:00
+++ 1.205/sql/sql_lex.h	2005-11-18 16:06:34 +01:00
@@ -753,12 +753,17 @@
   TABLE_LIST **query_tables_last;
   /* store original leaf_tables for INSERT SELECT and PS/SP */
   TABLE_LIST *leaf_tables_insert;
-  st_lex_user *create_view_definer;
   char *create_view_start;
   char *create_view_select_start;
   /* Partition info structure filled in by PARTITION BY parse part */
   partition_info *part_info;
 
+  /*
+    The definer of the object being created (view, trigger, stored routine).
+    I.e. the value of DEFINER clause.
+  */
+  LEX_USER *definer;
+
   List<key_part_spec> col_list;
   List<key_part_spec> ref_list;
   List<String>	      interval_list;
@@ -904,6 +909,14 @@
     being opened is probably enough).
   */
   SQL_LIST trg_table_fields;
+
+  /*
+    trigger_definition_begin points to the beginning of the word "TRIGGER" in
+    CREATE TRIGGER statement. This is used to add possibly omitted DEFINER
+    clause to the trigger definition statement before dumping it to the
+    binlog. 
+  */
+  const char *trigger_definition_begin;
 
   /*
     If non-0 then indicates that query requires prelocking and points to

--- 1.481/sql/sql_parse.cc	2005-11-10 18:42:32 +01:00
+++ 1.482/sql/sql_parse.cc	2005-11-18 16:06:34 +01:00
@@ -188,6 +188,18 @@
 #endif
 
 
+static bool some_non_temp_table_to_be_updated(THD *thd, TABLE_LIST *tables)
+{
+  for (TABLE_LIST *table= tables; table; table= table->next_global)
+  {
+    DBUG_ASSERT(table->db && table->table_name);
+    if (table->updating &&
+        !find_temporary_table(thd, table->db, table->table_name))
+      return 1;
+  }
+  return 0;
+}
+
 static HASH hash_user_connections;
 
 static int get_or_create_user_conn(THD *thd, const char *user,
@@ -2360,7 +2372,7 @@
     mysql_reset_errors(thd, 0);
 
 #ifdef HAVE_REPLICATION
-  if (thd->slave_thread)
+  if (unlikely(thd->slave_thread))
   {
     /*
       Check if statment should be skipped because of slave filtering
@@ -2399,16 +2411,20 @@
     }
 #endif
   }
+  else
 #endif /* HAVE_REPLICATION */
 
   /*
-    When option readonly is set deny operations which change tables.
-    Except for the replication thread and the 'super' users.
+    When option readonly is set deny operations which change non-temporary
+    tables. Except for the replication thread and the 'super' users.
   */
   if (opt_readonly &&
-      !(thd->slave_thread ||
-        (thd->security_ctx->master_access & SUPER_ACL)) &&
-      uc_update_queries[lex->sql_command])
+      !(thd->security_ctx->master_access & SUPER_ACL) &&
+      uc_update_queries[lex->sql_command] &&
+      !((lex->sql_command == SQLCOM_CREATE_TABLE) &&
+        (lex->create_info.options & HA_LEX_CREATE_TMP_TABLE)) &&
+      ((lex->sql_command != SQLCOM_UPDATE_MULTI) &&
+       some_non_temp_table_to_be_updated(thd, all_tables)))
   {
     my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only");
     DBUG_RETURN(-1);
@@ -3198,13 +3214,24 @@
 
 #ifdef HAVE_REPLICATION
     /* Check slave filtering rules */
-    if (thd->slave_thread && all_tables_not_ok(thd, all_tables))
+    if (unlikely(thd->slave_thread))
     {
-      /* we warn the slave SQL thread */
-      my_error(ER_SLAVE_IGNORED_TABLE, MYF(0));
-      break;
+      if (all_tables_not_ok(thd, all_tables))
+      {
+        /* we warn the slave SQL thread */
+        my_error(ER_SLAVE_IGNORED_TABLE, MYF(0));
+        break;
+      }
     }
+    else
 #endif /* HAVE_REPLICATION */
+    if (opt_readonly &&
+        !(thd->security_ctx->master_access & SUPER_ACL) &&
+        some_non_temp_table_to_be_updated(thd, all_tables))
+    {
+      my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only");
+      break;
+    }
 
     res= mysql_multi_update(thd, all_tables,
                             &select_lex->item_list,
@@ -4061,7 +4088,7 @@
 
     if (!lex->sphead->m_db.str || !lex->sphead->m_db.str[0])
     {
-      if (! thd->db)
+      if (!thd->db)
       {
         my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
         delete lex->sphead;
@@ -4280,18 +4307,6 @@
           So just execute the statement.
         */
 	res= sp->execute_procedure(thd, &lex->value_list);
-        if (mysql_bin_log.is_open() &&
-            (sp->m_chistics->daccess == SP_CONTAINS_SQL ||
-             sp->m_chistics->daccess == SP_MODIFIES_SQL_DATA))
-        {
-          if (res)
-            push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
-                         ER_FAILED_ROUTINE_BREAK_BINLOG,
-			 ER(ER_FAILED_ROUTINE_BREAK_BINLOG));
-          else
-            thd->clear_error();
-        }
-
 	/*
           If warnings have been cleared, we have to clear total_warn_count
           too, otherwise the clients get confused.
@@ -4350,7 +4365,8 @@
         if (end_active_trans(thd)) 
           goto error;
 	memcpy(&lex->sp_chistics, &chistics, sizeof(lex->sp_chistics));
-        if (!trust_routine_creators &&  mysql_bin_log.is_open() &&
+        if ((sp->m_type == TYPE_ENUM_FUNCTION) &&
+            !trust_function_creators &&  mysql_bin_log.is_open() &&
             !sp->m_chistics->detistic &&
             (chistics.daccess == SP_CONTAINS_SQL ||
              chistics.daccess == SP_MODIFIES_SQL_DATA))
@@ -4361,6 +4377,12 @@
         }
         else
         {
+          /*
+            Note that if you implement the capability of ALTER FUNCTION to
+            alter the body of the function, this command should be made to
+            follow the restrictions that log-bin-trust-function-creators=0
+            already puts on CREATE FUNCTION.
+          */
           if (lex->sql_command == SQLCOM_ALTER_PROCEDURE)
             result= sp_update_procedure(thd, lex->spname, &lex->sp_chistics);
           else
@@ -5033,7 +5055,7 @@
     the given table list refers to the list for prelocking (contains tables
     of other queries). For simple queries first_not_own_table is 0.
   */
-  for (; tables != first_not_own_table; tables= tables->next_global)
+  for (; tables && tables != first_not_own_table; tables= tables->next_global)
   {
     if (tables->schema_table && 
         (want_access & ~(SELECT_ACL | EXTRA_ACL | FILE_ACL)))
@@ -7437,32 +7459,81 @@
   return new Item_func_not(expr);
 }
 
+/*
+  Set the specified definer to the default value, which is the current user in
+  the thread. Also check that the current user satisfies to the definers
+  requirements.
+ 
+  SYNOPSIS
+    get_default_definer()
+    thd       [in] thread handler
+    definer   [out] definer
+ 
+  RETURN
+    error status, that is:
+      - FALSE -- on success;
+      - TRUE -- on error (current user can not be a definer).
+*/
+ 
+bool get_default_definer(THD *thd, LEX_USER *definer)
+{
+  /* Check that current user has non-empty host name. */
+
+  const Security_context *sctx= thd->security_ctx;
+
+  if (sctx->priv_host[0] == 0)
+  {
+    my_error(ER_MALFORMED_DEFINER, MYF(0));
+    return TRUE;
+  }
+
+  /* Fill in. */
+
+  definer->user.str= (char *) sctx->priv_user;
+  definer->user.length= strlen(definer->user.str);
+
+  definer->host.str= (char *) sctx->priv_host;
+  definer->host.length= strlen(definer->host.str);
+
+  return FALSE;
+}
+
 
 /*
-  Assign as view definer current user
+  Create definer with the given user and host names. Also check that the user
+  and host names satisfy definers requirements.
 
   SYNOPSIS
-    default_view_definer()
-    sctx		current security context
-    definer             structure where it should be assigned
+    create_definer()
+    thd         [in] thread handler
+    user_name   [in] user name
+    host_name   [in] host name
 
   RETURN
-    FALSE   OK
-    TRUE    Error
+    On success, return a valid pointer to the created and initialized
+    LEX_STRING, which contains definer information.
+    On error, return 0.
 */
 
-bool default_view_definer(Security_context *sctx, st_lex_user *definer)
+LEX_USER *create_definer(THD *thd, LEX_STRING *user_name, LEX_STRING *host_name)
 {
-  definer->user.str= sctx->priv_user;
-  definer->user.length= strlen(sctx->priv_user);
+  LEX_USER *definer;
+
+  /* Check that specified host name is valid. */
 
-  if (!*sctx->priv_host)
+  if (host_name->length == 0)
   {
-    my_error(ER_NO_VIEW_USER, MYF(0));
-    return TRUE;
+    my_error(ER_MALFORMED_DEFINER, MYF(0));
+    return 0;
   }
 
-  definer->host.str= sctx->priv_host;
-  definer->host.length= strlen(sctx->priv_host);
-  return FALSE;
+  /* Create and initialize. */
+
+  if (! (definer= (LEX_USER*) thd->alloc(sizeof (LEX_USER))))
+    return 0;
+
+  definer->user= *user_name;
+  definer->host= *host_name;
+
+  return definer;
 }

--- 1.367/sql/sql_select.cc	2005-11-06 08:28:50 +01:00
+++ 1.368/sql/sql_select.cc	2005-11-18 16:06:34 +01:00
@@ -98,6 +98,12 @@
                                              void *table_join_idx);
 static COND *simplify_joins(JOIN *join, List<TABLE_LIST> *join_list,
                             COND *conds, bool top);
+static bool check_interleaving_with_nj(JOIN_TAB *last, JOIN_TAB *next);
+static void restore_prev_nj_state(JOIN_TAB *last);
+static void reset_nj_counters(List<TABLE_LIST> *join_list);
+static uint build_bitmap_for_nested_joins(List<TABLE_LIST> *join_list,
+                                          uint first_unused);
+
 static COND *optimize_cond(JOIN *join, COND *conds,
                            List<TABLE_LIST> *join_list,
 			   Item::cond_result *cond_value);
@@ -520,12 +526,14 @@
   return 0;
 }
 
+
 /*
   global select optimisation.
   return 0 - success
          1 - error
   error code saved in field 'error'
 */
+
 int
 JOIN::optimize()
 {
@@ -588,6 +596,7 @@
 
     /* Convert all outer joins to inner joins if possible */
     conds= simplify_joins(this, join_list, conds, TRUE);
+    build_bitmap_for_nested_joins(join_list, 0);
 
     sel->prep_where= conds ? conds->copy_andor_structure(thd) : 0;
 
@@ -700,7 +709,8 @@
     DBUG_PRINT("error",("Error: make_select() failed"));
     DBUG_RETURN(1);
   }
-
+  
+  reset_nj_counters(join_list);
   make_outerjoin_info(this);
 
   /*
@@ -1980,14 +1990,19 @@
 	continue;
       }
       outer_join|= table->map;
+      s->embedding_map= 0;
+      for (;embedding; embedding= embedding->embedding)
+        s->embedding_map|= embedding->nested_join->nj_map;
       continue;
     }
     if (embedding)
     {
       /* s belongs to a nested join, maybe to several embedded joins */
+      s->embedding_map= 0;
       do
       {
         NESTED_JOIN *nested_join= embedding->nested_join;
+        s->embedding_map|=nested_join->nj_map;
         s->dependent|= embedding->dep_tables;
         embedding= embedding->embedding;
         outer_join|= nested_join->used_tables;
@@ -3561,6 +3576,8 @@
   bool straight_join= join->select_options & SELECT_STRAIGHT_JOIN;
   DBUG_ENTER("choose_plan");
 
+  join->cur_embedding_map= 0;
+  reset_nj_counters(join->join_list);
   /*
     if (SELECT_STRAIGHT_JOIN option is set)
       reorder tables so dependent tables come after tables they depend 
@@ -4041,7 +4058,9 @@
   for (JOIN_TAB **pos= join->best_ref + idx ; (s= *pos) ; pos++)
   {
     table_map real_table_bit= s->table->map;
-    if ((remaining_tables & real_table_bit) && !(remaining_tables & s->dependent))
+    if ((remaining_tables & real_table_bit) && 
+        !(remaining_tables & s->dependent) && 
+        (!idx || !check_interleaving_with_nj(join->positions[idx-1].table, s)))
     {
       double current_record_count, current_read_time;
 
@@ -4057,6 +4076,7 @@
       {
         DBUG_EXECUTE("opt", print_plan(join, read_time, record_count, idx,
                                        "prune_by_cost"););
+        restore_prev_nj_state(s);
         continue;
       }
 
@@ -4085,6 +4105,7 @@
         {
           DBUG_EXECUTE("opt", print_plan(join, read_time, record_count, idx,
                                          "pruned_by_heuristic"););
+          restore_prev_nj_state(s);
           continue;
         }
       }
@@ -4119,9 +4140,11 @@
                  sizeof(POSITION) * (idx + 1));
           join->best_read= current_read_time - 0.001;
         }
-        DBUG_EXECUTE("opt",
-                     print_plan(join, current_read_time, current_record_count, idx, "full_plan"););
+        DBUG_EXECUTE("opt", print_plan(join, current_read_time, 
+                                       current_record_count, idx, 
+                                       "full_plan"););
       }
+      restore_prev_nj_state(s);
     }
   }
   DBUG_VOID_RETURN;
@@ -4166,7 +4189,8 @@
   for (JOIN_TAB **pos=join->best_ref+idx ; (s=*pos) ; pos++)
   {
     table_map real_table_bit=s->table->map;
-    if ((rest_tables & real_table_bit) && !(rest_tables & s->dependent))
+    if ((rest_tables & real_table_bit) && !(rest_tables & s->dependent) &&
+        (!idx|| !check_interleaving_with_nj(join->positions[idx-1].table, s)))
     {
       double best,best_time,records;
       best=best_time=records=DBL_MAX;
@@ -4504,10 +4528,10 @@
 	  join->unit->select_limit_cnt >= records)
 	join->sort_by_table= (TABLE*) 1;	// Must use temporary table
 
-     /*
+      /*
 	Go to the next level only if there hasn't been a better key on
 	this level! This will cut down the search for a lot simple cases!
-       */
+      */
       double current_record_count=record_count*records;
       double current_read_time=read_time+best;
       if (best_record_count > current_record_count ||
@@ -4528,6 +4552,7 @@
           return;
 	swap_variables(JOIN_TAB*, join->best_ref[idx], *pos);
       }
+      restore_prev_nj_state(s);
       if (join->select_options & SELECT_STRAIGHT_JOIN)
 	break;				// Don't test all combinations
     }
@@ -5113,7 +5138,7 @@
     This function can be called only after the execution plan
     has been chosen.
 */
- 
+
 static void
 make_outerjoin_info(JOIN *join)
 {
@@ -7277,11 +7302,11 @@
     ascent all attributes are calculated, all outer joins that can be
     converted are replaced and then all unnecessary braces are removed.
     As join list contains join tables in the reverse order sequential
-    elimination of outer joins does not requite extra recursive calls.
+    elimination of outer joins does not require extra recursive calls.
 
   EXAMPLES
     Here is an example of a join query with invalid cross references:
-      SELECT * FROM t1 LEFT JOIN t2 ON t2.a=t3.a LEFT JOIN ON  t3.b=t1.b 
+      SELECT * FROM t1 LEFT JOIN t2 ON t2.a=t3.a LEFT JOIN t3 ON t3.b=t1.b 
      
   RETURN VALUE
     The new condition, if success
@@ -7438,7 +7463,257 @@
   }
   DBUG_RETURN(conds); 
 }
-        
+
+
+/*
+  Assign each nested join structure a bit in nested_join_map
+
+  SYNOPSIS
+    build_bitmap_for_nested_joins()
+      join          Join being processed
+      join_list     List of tables
+      first_unused  Number of first unused bit in nested_join_map before the
+                    call
+
+  DESCRIPTION
+    Assign each nested join structure (except "confluent" ones - those that
+    embed only one element) a bit in nested_join_map.
+
+  NOTE
+    This function is called after simplify_joins(), when there are no
+    redundant nested joins, #non_confluent_nested_joins <= #tables_in_join so
+    we will not run out of bits in nested_join_map.
+
+  RETURN
+    First unused bit in nested_join_map after the call.
+*/
+
+static uint build_bitmap_for_nested_joins(List<TABLE_LIST> *join_list, 
+                                          uint first_unused)
+{
+  List_iterator<TABLE_LIST> li(*join_list);
+  TABLE_LIST *table;
+  DBUG_ENTER("build_bitmap_for_nested_joins");
+  while ((table= li++))
+  {
+    NESTED_JOIN *nested_join;
+    if ((nested_join= table->nested_join))
+    {
+      /*
+        It is guaranteed by simplify_joins() function that a nested join
+        that has only one child represents a single table VIEW (and the child
+        is an underlying table). We don't assign bits to such nested join
+        structures because 
+        1. it is redundant (a "sequence" of one table cannot be interleaved 
+            with anything)
+        2. we could run out bits in nested_join_map otherwise.
+      */
+      if (nested_join->join_list.elements != 1)
+      {
+        nested_join->nj_map= 1 << first_unused++;
+        first_unused= build_bitmap_for_nested_joins(&nested_join->join_list,
+                                                    first_unused);
+      }
+    }
+  }
+  DBUG_RETURN(first_unused);
+}
+
+
+/*
+  Set NESTED_JOIN::counter=0 in all nested joins in passed list
+
+  SYNOPSIS
+    reset_nj_counters()
+      join_list  List of nested joins to process. It may also contain base
+                 tables which will be ignored.
+
+  DESCRIPTION
+    Recursively set NESTED_JOIN::counter=0 for all nested joins contained in
+    the passed join_list.
+*/
+
+static void reset_nj_counters(List<TABLE_LIST> *join_list)
+{
+  List_iterator<TABLE_LIST> li(*join_list);
+  TABLE_LIST *table;
+  DBUG_ENTER("reset_nj_counters");
+  while ((table= li++))
+  {
+    NESTED_JOIN *nested_join;
+    if ((nested_join= table->nested_join))
+    {
+      nested_join->counter= 0;
+      reset_nj_counters(&nested_join->join_list);
+    }
+  }
+  DBUG_VOID_RETURN;
+}
+
+
+/*
+  Check interleaving with an inner tables of an outer join for extension table 
+
+  SYNOPSIS
+    check_interleaving_with_nj()
+      join       Join being processed
+      last_tab   Last table in current partial join order (this function is
+                 not called for empty partial join orders)
+      next_tab   Table we're going to extend the current partial join with
+
+  DESCRIPTION
+    Check if table next_tab can be added to current partial join order, and 
+    if yes, record that it has been added.
+
+    The function assumes that both current partial join order and its
+    extension with next_tab are valid wrt table dependencies.
+
+  IMPLEMENTATION
+    LIMITATIONS ON JOIN ORDER
+      The nested [outer] joins executioner algorithm imposes these limitations
+      on join order:
+      1. "Outer tables first" -  any "outer" table must be before any 
+          corresponding "inner" table.
+      2. "No interleaving" - tables inside a nested join must form a continuous
+         sequence in join order (i.e. the sequence must not be interrupted by 
+         tables that are outside of this nested join).
+
+      #1 is checked elsewhere, this function checks #2 provided that #1 has
+      been already checked.
+
+    WHY NEED NON-INTERLEAVING
+      Consider an example: 
+       
+        select * from t0 join t1 left join (t2 join t3) on cond1
+      
+      The join order "t1 t2 t0 t3" is invalid:
+
+      table t0 is outside of the nested join, so WHERE condition for t0 is
+      attached directly to t0 (without triggers, and it may be used to access
+      t0). Applying WHERE(t0) to (t2,t0,t3) record is invalid as we may miss
+      combinations of (t1, t2, t3) that satisfy condition cond1, and produce a
+      null-complemented (t1, t2.NULLs, t3.NULLs) row, which should not have
+      been produced.
+      
+      If table t0 is not between t2 and t3, the problem doesn't exist:
+      * If t0 is located after (t2,t3), WHERE(t0) is applied after nested join
+        processing has finished.
+      * If t0 is located before (t2,t3), predicates like WHERE_cond(t0, t2) are
+        wrapped into condition triggers, which takes care of correct nested
+        join processing.
+      
+    HOW IT IS IMPLEMENTED
+      The limitations on join order can be rephrased as follows: for valid
+      join order one must be able to:
+        1. write down the used tables in the join order on one line.
+        2. for each nested join, put one '(' and one ')' on the said line        
+        3. write "LEFT JOIN" and "ON (...)" where appropriate
+        4. get a query equivalent to the query we're trying to execute.
+      
+      Calls to check_interleaving_with_nj() are equivalent to writing the
+      above described line from left to right. 
+      A single check_interleaving_with_nj(A,B) call is equivalent to writing 
+      table B and appropriate brackets on condition that table A and
+      appropriate brackets is the last what was written. Graphically the
+      transition is as follows:
+
+                           +---- current position
+                           |
+          ... last_tab ))) | ( next_tab )  )..) | ...
+                             X          Y   Z   |
+                                                +- need to move to this
+                                                   position.
+
+      Notes about the position:
+        The caller guarantees that there is no more then one X-bracket by 
+        checking "!(remaining_tables & s->dependent)" before calling this 
+        function. X-bracket may have a pair in Y-bracket.
+       
+      When "writing" we store/update this auxilary info about the current
+      position:
+       1. join->cur_embedding_map - bitmap of pairs of brackets (aka nested
+          joins) we've opened but didn't close.
+       2. {each NESTED_JOIN structure not simplified away}->counter - number
+          of this nested join's children that have already been added to to
+          the partial join order.
+      
+  RETURN
+    FALSE  Join order extended, nested joins info about current join order
+           (see NOTE section) updated.
+    TRUE   Requested join order extension not allowed.
+*/
+
+static bool check_interleaving_with_nj(JOIN_TAB *last_tab, JOIN_TAB *next_tab)
+{
+  TABLE_LIST *next_emb= next_tab->table->pos_in_table_list->embedding;
+  JOIN *join= last_tab->join;
+
+  if (join->cur_embedding_map & ~next_tab->embedding_map)
+  {
+    /* 
+      next_tab is outside of the "pair of brackets" we're currently in.
+      Cannot add it.
+    */
+    return TRUE;
+  }
+   
+  /*
+    Do update counters for "pairs of brackets" that we've left (marked as
+    X,Y,Z in the above picture)
+  */
+  for (;next_emb; next_emb= next_emb->embedding)
+  {
+    next_emb->nested_join->counter++;
+    if (next_emb->nested_join->counter == 1)
+    {
+      /* 
+        next_emb is the first table inside a nested join we've "entered". In
+        the picture above, we're looking at the 'X' bracket. Don't exit yet as
+        X bracket might have Y pair bracket.
+      */
+      join->cur_embedding_map |= next_emb->nested_join->nj_map;
+    }
+    
+    if (next_emb->nested_join->join_list.elements !=
+        next_emb->nested_join->counter)
+      break;
+
+    /*
+      We're currently at Y or Z-bracket as depicted in the above picture.
+      Mark that we've left it and continue walking up the brackets hierarchy.
+    */
+    join->cur_embedding_map &= ~next_emb->nested_join->nj_map;
+  }
+  return FALSE;
+}
+
+
+/*
+  Nested joins perspective: Remove the last table from the join order
+
+  SYNOPSIS
+    restore_prev_nj_state()
+      last  join table to remove, it is assumed to be the last in current 
+            partial join order.
+     
+  DESCRIPTION
+    Remove the last table from the partial join order and update the nested
+    joins counters and join->cur_embedding_map. It is ok to call this 
+    function for the first table in join order (for which 
+    check_interleaving_with_nj has not been called)
+*/
+
+static void restore_prev_nj_state(JOIN_TAB *last)
+{
+  TABLE_LIST *last_emb= last->table->pos_in_table_list->embedding;
+  JOIN *join= last->join;
+  while (last_emb && !(--last_emb->nested_join->counter))
+  {
+    join->cur_embedding_map &= last_emb->nested_join->nj_map;
+    last_emb= last_emb->embedding;
+  }
+}
+
 
 static COND *
 optimize_cond(JOIN *join, COND *conds, List<TABLE_LIST> *join_list,

--- 1.99/sql/sql_select.h	2005-11-04 21:09:57 +01:00
+++ 1.100/sql/sql_select.h	2005-11-18 16:06:35 +01:00
@@ -137,7 +137,9 @@
   TABLE_REF	ref;
   JOIN_CACHE	cache;
   JOIN		*join;
-
+  /* Bitmap of nested joins this table is part of */
+  nested_join_map embedding_map;
+  
   void cleanup();
 } JOIN_TAB;
 
@@ -194,6 +196,13 @@
   */
   ha_rows  fetch_limit;
   POSITION positions[MAX_TABLES+1],best_positions[MAX_TABLES+1];
+  
+  /* 
+    Bitmap of nested joins embedding the position at the end of the current 
+    partial join (valid only during join optimizer run).
+  */
+  nested_join_map cur_embedding_map;
+
   double   best_read;
   List<Item> *fields;
   List<Cached_item> group_fields, group_fields_cache;

--- 1.277/sql/sql_show.cc	2005-11-11 00:42:49 +01:00
+++ 1.278/sql/sql_show.cc	2005-11-18 16:37:56 +01:00
@@ -71,20 +71,23 @@
   handlerton **types;
   for (types= sys_table_types; *types; types++)
   {
-    protocol->prepare_for_resend();
-    protocol->store((*types)->name, system_charset_info);
-    const char *option_name= show_comp_option_name[(int) (*types)->state];
-
-    if ((*types)->state == SHOW_OPTION_YES &&
-	!my_strcasecmp(system_charset_info, default_type_name, (*types)->name))
-      option_name= "DEFAULT";
-    protocol->store(option_name, system_charset_info);
-    protocol->store((*types)->comment, system_charset_info);
-    protocol->store((*types)->commit ? "YES" : "NO", system_charset_info);
-    protocol->store((*types)->prepare ? "YES" : "NO", system_charset_info);
-    protocol->store((*types)->savepoint_set ? "YES" : "NO", system_charset_info);
-    if (protocol->write())
-      DBUG_RETURN(TRUE);
+    if (!((*types)->flags & HTON_HIDDEN))
+    {
+      protocol->prepare_for_resend();
+      protocol->store((*types)->name, system_charset_info);
+      const char *option_name= show_comp_option_name[(int) (*types)->state];
+
+      if ((*types)->state == SHOW_OPTION_YES &&
+          !my_strcasecmp(system_charset_info, default_type_name, (*types)->name))
+        option_name= "DEFAULT";
+      protocol->store(option_name, system_charset_info);
+      protocol->store((*types)->comment, system_charset_info);
+      if (protocol->write())
+        DBUG_RETURN(TRUE);
+    }
+  move  protocol->store((*types)->commit ? "YES" : "NO", system_charset_info);
+  move  protocol->store((*types)->prepare ? "YES" : "NO", system_charset_info);
+  move  protocol->store((*types)->savepoint_set ? "YES" : "NO", system_charset_info);
   }
   send_eof(thd);
   DBUG_RETURN(FALSE);
@@ -395,7 +398,21 @@
 
   /* Only one table for now, but VIEW can involve several tables */
   if (open_normal_and_derived_tables(thd, table_list, 0))
-    DBUG_RETURN(TRUE);
+  {
+    if (!table_list->view || thd->net.last_errno != ER_VIEW_INVALID)
+      DBUG_RETURN(TRUE);
+    /*
+      Clear all messages with 'error' level status and
+      issue a warning with 'warning' level status in 
+      case of invalid view and last error is ER_VIEW_INVALID
+    */
+    mysql_reset_errors(thd, true);
+    push_warning_printf(thd,MYSQL_ERROR::WARN_LEVEL_WARN,
+                        ER_VIEW_INVALID,
+                        ER(ER_VIEW_INVALID),
+                        table_list->view_db.str,
+                        table_list->view_name.str);
+  }
 
   /* TODO: add environment variables show when it become possible */
   if (thd->lex->only_view && !table_list->view)
@@ -1104,18 +1121,36 @@
   default:
     DBUG_ASSERT(0); // never should happen
   }
-  buff->append("DEFINER=", 8);
-  append_identifier(thd, buff,
-                    table->definer.user.str, table->definer.user.length);
-  buff->append('@');
-  append_identifier(thd, buff,
-                    table->definer.host.str, table->definer.host.length);
+  append_definer(thd, buff, &table->definer.user, &table->definer.host);
   if (table->view_suid)
-    buff->append(" SQL SECURITY DEFINER ", 22);
+    buff->append("SQL SECURITY DEFINER ", 21);
   else
-    buff->append(" SQL SECURITY INVOKER ", 22);
+    buff->append("SQL SECURITY INVOKER ", 21);
 }
 
+
+/*
+  Append DEFINER clause to the given buffer.
+  
+  SYNOPSIS
+    append_definer()
+    thd           [in] thread handle
+    buffer        [inout] buffer to hold DEFINER clause
+    definer_user  [in] user name part of definer
+    definer_host  [in] host name part of definer
+*/
+
+void append_definer(THD *thd, String *buffer, const LEX_STRING *definer_user,
+                    const LEX_STRING *definer_host)
+{
+  buffer->append(STRING_WITH_LEN("DEFINER="));
+  append_identifier(thd, buffer, definer_user->str, definer_user->length);
+  buffer->append('@');
+  append_identifier(thd, buffer, definer_host->str, definer_host->length);
+  buffer->append(' ');
+}
+
+
 static int
 view_store_create_info(THD *thd, TABLE_LIST *table, String *buff)
 {
@@ -3015,47 +3050,44 @@
   DBUG_ENTER("get_schema_views_record");
   char definer[HOSTNAME_LENGTH + USERNAME_LENGTH + 2];
   uint definer_len;
-  if (!res)
-  {
-    if (tables->view)
-    {
-      restore_record(table, s->default_values);
-      table->field[1]->store(tables->view_db.str, tables->view_db.length, cs);
-      table->field[2]->store(tables->view_name.str, tables->view_name.length,
-                             cs);
-      table->field[3]->store(tables->query.str, tables->query.length, cs);
 
-      if (tables->with_check != VIEW_CHECK_NONE)
-      {
-        if (tables->with_check == VIEW_CHECK_LOCAL)
-          table->field[4]->store(STRING_WITH_LEN("LOCAL"), cs);
-        else
-          table->field[4]->store(STRING_WITH_LEN("CASCADED"), cs);
-      }
-      else
-        table->field[4]->store(STRING_WITH_LEN("NONE"), cs);
+  if (tables->view)
+  {
+    restore_record(table, s->default_values);
+    table->field[1]->store(tables->view_db.str, tables->view_db.length, cs);
+    table->field[2]->store(tables->view_name.str, tables->view_name.length,
+                           cs);
+    table->field[3]->store(tables->query.str, tables->query.length, cs);
 
-      if (tables->updatable_view)
-        table->field[5]->store(STRING_WITH_LEN("YES"), cs);
-      else
-        table->field[5]->store(STRING_WITH_LEN("NO"), cs);
-      definer_len= (strxmov(definer, tables->definer.user.str, "@",
-                            tables->definer.host.str, NullS) - definer);
-      table->field[6]->store(definer, definer_len, cs);
-      if (tables->view_suid)
-        table->field[7]->store(STRING_WITH_LEN("DEFINER"), cs);
+    if (tables->with_check != VIEW_CHECK_NONE)
+    {
+      if (tables->with_check == VIEW_CHECK_LOCAL)
+        table->field[4]->store(STRING_WITH_LEN("LOCAL"), cs);
       else
-        table->field[7]->store(STRING_WITH_LEN("INVOKER"), cs);
-      DBUG_RETURN(schema_table_store_record(thd, table));
+        table->field[4]->store(STRING_WITH_LEN("CASCADED"), cs);
     }
-  }
-  else
-  {
-    if (tables->view)
+    else
+      table->field[4]->store(STRING_WITH_LEN("NONE"), cs);
+
+    if (tables->updatable_view)
+      table->field[5]->store(STRING_WITH_LEN("YES"), cs);
+    else
+      table->field[5]->store(STRING_WITH_LEN("NO"), cs);
+    definer_len= (strxmov(definer, tables->definer.user.str, "@",
+                          tables->definer.host.str, NullS) - definer);
+    table->field[6]->store(definer, definer_len, cs);
+    if (tables->view_suid)
+      table->field[7]->store(STRING_WITH_LEN("DEFINER"), cs);
+    else
+      table->field[7]->store(STRING_WITH_LEN("INVOKER"), cs);
+    if (schema_table_store_record(thd, table))
+      DBUG_RETURN(1);
+    if (res)
       push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 
                    thd->net.last_errno, thd->net.last_error);
-    thd->clear_error();
   }
+  if (res) 
+    thd->clear_error();
   DBUG_RETURN(0);
 }
 
@@ -3138,7 +3170,8 @@
                           enum trg_event_type event,
                           enum trg_action_time_type timing,
                           LEX_STRING *trigger_stmt,
-                          ulong sql_mode)
+                          ulong sql_mode,
+                          LEX_STRING *definer_buffer)
 {
   CHARSET_INFO *cs= system_charset_info;
   byte *sql_mode_str;
@@ -3163,6 +3196,7 @@
                                                        sql_mode,
                                                        &sql_mode_len);
   table->field[17]->store((const char*)sql_mode_str, sql_mode_len, cs);
+  table->field[18]->store((const char *)definer_buffer->str, definer_buffer->length, cs);
   return schema_table_store_record(thd, table);
 }
 
@@ -3196,15 +3230,21 @@
         LEX_STRING trigger_name;
         LEX_STRING trigger_stmt;
         ulong sql_mode;
+        char definer_holder[HOSTNAME_LENGTH + USERNAME_LENGTH + 2];
+        LEX_STRING definer_buffer;
+        definer_buffer.str= definer_holder;
         if (triggers->get_trigger_info(thd, (enum trg_event_type) event,
                                        (enum trg_action_time_type)timing,
                                        &trigger_name, &trigger_stmt,
-                                       &sql_mode))
+                                       &sql_mode,
+                                       &definer_buffer))
           continue;
+
         if (store_trigger(thd, table, base_name, file_name, &trigger_name,
                          (enum trg_event_type) event,
                          (enum trg_action_time_type) timing, &trigger_stmt,
-                         sql_mode))
+                         sql_mode,
+                         &definer_buffer))
           DBUG_RETURN(1);
       }
     }
@@ -4108,6 +4148,7 @@
   {"ACTION_REFERENCE_NEW_ROW", 3, MYSQL_TYPE_STRING, 0, 0, 0},
   {"CREATED", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, "Created"},
   {"SQL_MODE", 65535, MYSQL_TYPE_STRING, 0, 0, "sql_mode"},
+  {"DEFINER", 65535, MYSQL_TYPE_STRING, 0, 0, "Definer"},
   {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
 };
 

--- 1.276/sql/sql_table.cc	2005-11-07 16:24:44 +01:00
+++ 1.277/sql/sql_table.cc	2005-11-18 16:06:35 +01:00
@@ -896,6 +896,7 @@
 	else
 	{
 	  /* Field redefined */
+	  sql_field->def=		dup_field->def;
 	  sql_field->sql_type=		dup_field->sql_type;
 	  sql_field->charset=		(dup_field->charset ?
 					 dup_field->charset :
@@ -905,8 +906,15 @@
           sql_field->key_length=	dup_field->key_length;
 	  sql_field->create_length_to_internal_length();
 	  sql_field->decimals=		dup_field->decimals;
-	  sql_field->flags=		dup_field->flags;
 	  sql_field->unireg_check=	dup_field->unireg_check;
+          /* 
+            We're making one field from two, the result field will have
+            dup_field->flags as flags. If we've incremented null_fields
+            because of sql_field->flags, decrement it back.
+          */
+          if (!(sql_field->flags & NOT_NULL_FLAG))
+            null_fields--;
+	  sql_field->flags=		dup_field->flags;
 	  it2.remove();			// Remove first (create) definition
 	  select_field_pos--;
 	  break;
@@ -2338,7 +2346,7 @@
     /* if view are unsupported */
     if (table->view && view_operator_func == NULL)
     {
-      result_code= HA_ADMIN_NOT_IMPLEMENTED;
+      result_code= HA_ADMIN_NOT_BASE_TABLE;
       goto send_result;
     }
     thd->open_options&= ~extra_open_options;
@@ -2473,6 +2481,16 @@
       }
       break;
 
+    case HA_ADMIN_NOT_BASE_TABLE:
+      {
+        char buf[ERRMSGSIZE+20];
+        uint length= my_snprintf(buf, ERRMSGSIZE,
+                                 ER(ER_BAD_TABLE_ERROR), table_name);
+        protocol->store("note", 4, system_charset_info);
+        protocol->store(buf, length, system_charset_info);
+      }
+      break;
+
     case HA_ADMIN_OK:
       protocol->store("status", 6, system_charset_info);
       protocol->store("OK",2, system_charset_info);
@@ -2573,16 +2591,19 @@
         break;
       }
     }
-    if (fatal_error)
-      table->table->s->version=0;               // Force close of table
-    else if (open_for_modify)
+    if (table->table)
     {
-      pthread_mutex_lock(&LOCK_open);
-      remove_table_from_cache(thd, table->table->s->db,
-			      table->table->s->table_name, RTFC_NO_FLAG);
-      pthread_mutex_unlock(&LOCK_open);
-      /* May be something modified consequently we have to invalidate cache */
-      query_cache_invalidate3(thd, table->table, 0);
+      if (fatal_error)
+        table->table->s->version=0;               // Force close of table
+      else if (open_for_modify)
+      {
+        pthread_mutex_lock(&LOCK_open);
+        remove_table_from_cache(thd, table->table->s->db,
+                                table->table->s->table_name, RTFC_NO_FLAG);
+        pthread_mutex_unlock(&LOCK_open);
+        /* Something may be modified, that's why we have to invalidate cache */
+        query_cache_invalidate3(thd, table->table, 0);
+      }
     }
     close_thread_tables(thd);
     table->table=0;				// For query cache

--- 1.420/sql/sql_yacc.yy	2005-11-10 18:42:33 +01:00
+++ 1.421/sql/sql_yacc.yy	2005-11-18 16:37:56 +01:00
@@ -795,7 +795,7 @@
 
 %type <symbol> FUNC_ARG0 FUNC_ARG1 FUNC_ARG2 FUNC_ARG3 keyword keyword_sp
 
-%type <lex_user> user grant_user
+%type <lex_user> user grant_user get_definer
 
 %type <charset>
 	opt_collate
@@ -846,11 +846,13 @@
 	subselect_end select_var_list select_var_list_init help opt_len
 	opt_extended_describe
         prepare prepare_src execute deallocate
-	statement sp_suid opt_view_list view_list or_replace algorithm
+	statement sp_suid
 	sp_c_chistics sp_a_chistics sp_chistic sp_c_chistic xa
         load_data opt_field_or_var_spec fields_or_vars opt_load_data_set_spec
-        install uninstall view_user view_suid
-        partition_entry
+        definer view_replace_or_algorithm view_replace view_algorithm_opt
+        view_algorithm view_or_trigger_tail view_suid view_tail view_list_opt
+        view_list view_select view_check_option trigger_tail
+        install uninstall partition_entry
 END_OF_INPUT
 
 %type <NONE> call sp_proc_stmts sp_proc_stmts1 sp_proc_stmt
@@ -1285,80 +1287,14 @@
 	      YYTHD->client_capabilities |= CLIENT_MULTI_QUERIES;
 	    sp->restore_thd_mem_root(YYTHD);
 	  }
-	| CREATE or_replace algorithm view_user view_suid VIEW_SYM table_ident
+	| CREATE
 	  {
-	    THD *thd= YYTHD;
-	    LEX *lex= thd->lex;
-	    lex->sql_command= SQLCOM_CREATE_VIEW;
-            lex->create_view_start= thd->query;
-	    /* first table in list is target VIEW name */
-	    if (!lex->select_lex.add_table_to_list(thd, $7, NULL, 0))
-              YYABORT;
+            Lex->create_view_mode= VIEW_CREATE_NEW;
+            Lex->create_view_algorithm= VIEW_ALGORITHM_UNDEFINED;
+            Lex->create_view_suid= TRUE;
 	  }
-	  opt_view_list AS select_view_init check_option
+	  view_or_trigger
 	  {}
-        | CREATE TRIGGER_SYM sp_name trg_action_time trg_event 
-          ON table_ident FOR_SYM EACH_SYM ROW_SYM
-          {
-            LEX *lex= Lex;
-            sp_head *sp;
-           
-            if (lex->sphead)
-            {
-              my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), "TRIGGER");
-              YYABORT;
-            }
-
-            if (!(sp= new sp_head()))
-              YYABORT;
-            sp->reset_thd_mem_root(YYTHD);
-            sp->init(lex);
-            
-            sp->m_type= TYPE_ENUM_TRIGGER;
-            lex->sphead= sp;
-            lex->spname= $3;
-            /*
-              We have to turn of CLIENT_MULTI_QUERIES while parsing a
-              stored procedure, otherwise yylex will chop it into pieces
-              at each ';'.
-            */
-            sp->m_old_cmq= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES;
-            YYTHD->client_capabilities &= ~CLIENT_MULTI_QUERIES;
-            
-            bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
-            lex->sphead->m_chistics= &lex->sp_chistics;
-            lex->sphead->m_body_begin= lex->ptr;
-          }
-          sp_proc_stmt
-          {
-            LEX *lex= Lex;
-            sp_head *sp= lex->sphead;
-            
-            lex->sql_command= SQLCOM_CREATE_TRIGGER;
-            sp->init_strings(YYTHD, lex, $3);
-            /* Restore flag if it was cleared above */
-            if (sp->m_old_cmq)
-              YYTHD->client_capabilities |= CLIENT_MULTI_QUERIES;
-            sp->restore_thd_mem_root(YYTHD);
-
-            if (sp->is_not_allowed_in_function("trigger"))
-                YYABORT;
-
-            /*
-              We have to do it after parsing trigger body, because some of
-              sp_proc_stmt alternatives are not saving/restoring LEX, so
-              lex->query_tables can be wiped out.
-              
-              QQ: What are other consequences of this?
-              
-              QQ: Could we loosen lock type in certain cases ?
-            */
-            if (!lex->select_lex.add_table_to_list(YYTHD, $7, 
-                                                   (LEX_STRING*) 0,
-                                                   TL_OPTION_UPDATING,
-                                                   TL_WRITE))
-              YYABORT;
-          }
 	| CREATE USER clear_privileges grant_list
 	  {
 	    Lex->sql_command = SQLCOM_CREATE_USER;
@@ -2598,7 +2534,7 @@
 /*
  This part of the parser is about handling of the partition information.
 
+ It's first version was written by Mikael Ronström with lots of answers to
  questions provided by Antony Curtis.
 
  The partition grammar can be called from three places.
@@ -3967,7 +3903,8 @@
 	    lex->sql_command= SQLCOM_ALTER_FUNCTION;
 	    lex->spname= $3;
 	  }
-	| ALTER algorithm view_user view_suid VIEW_SYM table_ident
+        | ALTER view_algorithm_opt definer view_suid
+          VIEW_SYM table_ident
 	  {
 	    THD *thd= YYTHD;
 	    LEX *lex= thd->lex;
@@ -3977,7 +3914,7 @@
 	    /* first table in list is target VIEW name */
 	    lex->select_lex.add_table_to_list(thd, $6, NULL, 0);
 	  }
-	  opt_view_list AS select_view_init check_option
+	  view_list_opt AS view_select view_check_option
 	  {}
 	;
 
@@ -3992,7 +3929,7 @@
         opt_partitioning
         | partitioning
 /*
+  This part was added for release 5.1 by Mikael Ronström.
   From here we insert a number of commands to manage the partitions of a
   partitioned table such as adding partitions, dropping partitions,
   reorganising partitions in various manners. In future releases the list
@@ -4636,18 +4573,6 @@
 	|
 	'(' select_paren ')' union_opt;
 
-select_view_init:
-        SELECT_SYM remember_name select_init2
-          {
-            Lex->create_view_select_start= $2;
-          }
-        |
-        '(' remember_name select_paren ')' union_opt
-          {
-            Lex->create_view_select_start= $2;
-          }
-        ;
-
 select_paren:
 	SELECT_SYM select_part2
 	  {
@@ -9612,8 +9537,119 @@
 	  lex->current_select = lex->current_select->return_after_parsing();
 	};
 
-opt_view_list:
-	/* empty */ {}
+definer:
+	get_definer
+	{
+	  THD *thd= YYTHD;
+	  
+	  if (! (thd->lex->definer= create_definer(thd, &$1->user, &$1->host)))
+	    YYABORT;
+	}
+	;
+
+get_definer:
+	opt_current_definer
+	{
+	  THD *thd= YYTHD;
+          
+	  if (!($$=(LEX_USER*) thd->alloc(sizeof(st_lex_user))))
+	    YYABORT;
+
+	  if (get_default_definer(thd, $$))
+	    YYABORT;
+	}
+	| DEFINER_SYM EQ ident_or_text '@' ident_or_text
+	{
+	  if (!($$=(LEX_USER*) YYTHD->alloc(sizeof(st_lex_user))))
+	    YYABORT;
+
+	  $$->user= $3;
+	  $$->host= $5;
+	}
+	;
+
+opt_current_definer:
+	/* empty */
+	| DEFINER_SYM EQ CURRENT_USER optional_braces
+	;
+
+/**************************************************************************
+
+ CREATE VIEW statement options.
+
+**************************************************************************/
+
+view_replace_or_algorithm:
+	view_replace
+	{}
+	| view_replace view_algorithm
+	{}
+	| view_algorithm
+	{}
+	;
+
+view_replace:
+	OR_SYM REPLACE
+	{ Lex->create_view_mode= VIEW_CREATE_OR_REPLACE; }
+	;
+
+view_algorithm:
+	ALGORITHM_SYM EQ UNDEFINED_SYM
+	{ Lex->create_view_algorithm= VIEW_ALGORITHM_UNDEFINED; }
+	| ALGORITHM_SYM EQ MERGE_SYM
+	{ Lex->create_view_algorithm= VIEW_ALGORITHM_MERGE; }
+	| ALGORITHM_SYM EQ TEMPTABLE_SYM
+	{ Lex->create_view_algorithm= VIEW_ALGORITHM_TMPTABLE; }
+	;
+
+view_algorithm_opt:
+	/* empty */
+	{ Lex->create_view_algorithm= VIEW_ALGORITHM_UNDEFINED; }
+	| view_algorithm
+	{}
+	;
+
+view_or_trigger:
+	definer view_or_trigger_tail
+	{}
+	| view_replace_or_algorithm definer view_tail
+	{}
+	;
+
+view_or_trigger_tail:
+	view_tail
+	{}
+	| trigger_tail
+	{}
+	;
+
+view_suid:
+	/* empty */
+	{ Lex->create_view_suid= TRUE; }
+	| SQL_SYM SECURITY_SYM DEFINER_SYM
+	{ Lex->create_view_suid= TRUE; }
+	| SQL_SYM SECURITY_SYM INVOKER_SYM
+	{ Lex->create_view_suid= FALSE; }
+	;
+
+view_tail:
+	view_suid VIEW_SYM table_ident
+	{
+	  THD *thd= YYTHD;
+	  LEX *lex= thd->lex;
+	  lex->sql_command= SQLCOM_CREATE_VIEW;
+	  lex->create_view_start= thd->query;
+	  /* first table in list is target VIEW name */
+	  if (!lex->select_lex.add_table_to_list(thd, $3, NULL, 0))
+	    YYABORT;
+	}
+	view_list_opt AS view_select view_check_option
+	{}
+	;
+
+view_list_opt:
+	/* empty */
+	{}
 	| '(' view_list ')'
 	;
 
@@ -9630,79 +9666,102 @@
 	  }
 	;
 
-or_replace:
-	/* empty */	 { Lex->create_view_mode= VIEW_CREATE_NEW; }
-	| OR_SYM REPLACE { Lex->create_view_mode= VIEW_CREATE_OR_REPLACE; }
+view_select:
+	SELECT_SYM remember_name select_init2
+	{
+	  Lex->create_view_select_start= $2;
+	}
+	| '(' remember_name select_paren ')' union_opt
+	{
+	  Lex->create_view_select_start= $2;
+	}
 	;
 
-algorithm:
+view_check_option:
 	/* empty */
-	  { Lex->create_view_algorithm= VIEW_ALGORITHM_UNDEFINED; }
-	| ALGORITHM_SYM EQ UNDEFINED_SYM
-	  { Lex->create_view_algorithm= VIEW_ALGORITHM_UNDEFINED; }
-	| ALGORITHM_SYM EQ MERGE_SYM
-	  { Lex->create_view_algorithm= VIEW_ALGORITHM_MERGE; }
-	| ALGORITHM_SYM EQ TEMPTABLE_SYM
-	  { Lex->create_view_algorithm= VIEW_ALGORITHM_TMPTABLE; }
+	{ Lex->create_view_check= VIEW_CHECK_NONE; }
+	| WITH CHECK_SYM OPTION
+	{ Lex->create_view_check= VIEW_CHECK_CASCADED; }
+	| WITH CASCADED CHECK_SYM OPTION
+	{ Lex->create_view_check= VIEW_CHECK_CASCADED; }
+	| WITH LOCAL_SYM CHECK_SYM OPTION
+	{ Lex->create_view_check= VIEW_CHECK_LOCAL; }
 	;
 
-view_user:
-        /* empty */
-          {
-            THD *thd= YYTHD;
-            if (!(thd->lex->create_view_definer=
-                  (LEX_USER*) thd->alloc(sizeof(st_lex_user))))
-              YYABORT;
-            if (default_view_definer(thd->security_ctx,
-                                     thd->lex->create_view_definer))
-              YYABORT;
-          }
-        | CURRENT_USER optional_braces
-          {
-            THD *thd= YYTHD;
-            if (!(thd->lex->create_view_definer=
-                  (LEX_USER*) thd->alloc(sizeof(st_lex_user))))
-              YYABORT;
-            if (default_view_definer(thd->security_ctx,
-                                     thd->lex->create_view_definer))
-              YYABORT;
-          }
-	| DEFINER_SYM EQ ident_or_text '@' ident_or_text
+/**************************************************************************
+
+ CREATE TRIGGER statement parts.
+
+**************************************************************************/
+
+trigger_tail:
+	TRIGGER_SYM remember_name sp_name trg_action_time trg_event 
+	ON table_ident FOR_SYM EACH_SYM ROW_SYM
+	{
+	  LEX *lex= Lex;
+	  sp_head *sp;
+	 
+	  if (lex->sphead)
 	  {
-	    THD *thd= YYTHD;
-            st_lex_user *view_user;
-	    if (!(thd->lex->create_view_definer= view_user=
-                  (LEX_USER*) thd->alloc(sizeof(st_lex_user))))
-	      YYABORT;
-	    view_user->user = $3; view_user->host=$5;
-            if (view_user->host.length == 0)
-            {
-              my_error(ER_NO_VIEW_USER, MYF(0));
-              YYABORT;
-            }
+	    my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), "TRIGGER");
+	    YYABORT;
 	  }
-        ;
-
-view_suid:
-        /* empty */
-	  { Lex->create_view_suid= TRUE; }
-        |
-	  SQL_SYM SECURITY_SYM DEFINER_SYM
-	  { Lex->create_view_suid= TRUE; }
-	| SQL_SYM SECURITY_SYM INVOKER_SYM
-	  { Lex->create_view_suid= FALSE; }
+	
+	  if (!(sp= new sp_head()))
+	    YYABORT;
+	  sp->reset_thd_mem_root(YYTHD);
+	  sp->init(lex);
+	
+	  lex->trigger_definition_begin= $2;
+	  
+	  sp->m_type= TYPE_ENUM_TRIGGER;
+	  lex->sphead= sp;
+	  lex->spname= $3;
+	  /*
+	    We have to turn of CLIENT_MULTI_QUERIES while parsing a
+	    stored procedure, otherwise yylex will chop it into pieces
+	    at each ';'.
+	  */
+	  sp->m_old_cmq= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES;
+	  YYTHD->client_capabilities &= ~CLIENT_MULTI_QUERIES;
+	  
+	  bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
+	  lex->sphead->m_chistics= &lex->sp_chistics;
+	  lex->sphead->m_body_begin= lex->ptr;
+	}
+	sp_proc_stmt
+	{
+	  LEX *lex= Lex;
+	  sp_head *sp= lex->sphead;
+	  
+	  lex->sql_command= SQLCOM_CREATE_TRIGGER;
+	  sp->init_strings(YYTHD, lex, $3);
+	  /* Restore flag if it was cleared above */
+	  if (sp->m_old_cmq)
+	    YYTHD->client_capabilities |= CLIENT_MULTI_QUERIES;
+	  sp->restore_thd_mem_root(YYTHD);
+	
+	  if (sp->is_not_allowed_in_function("trigger"))
+	      YYABORT;
+	
+	  /*
+	    We have to do it after parsing trigger body, because some of
+	    sp_proc_stmt alternatives are not saving/restoring LEX, so
+	    lex->query_tables can be wiped out.
+	    
+	    QQ: What are other consequences of this?
+	    
+	    QQ: Could we loosen lock type in certain cases ?
+	  */
+	  if (!lex->select_lex.add_table_to_list(YYTHD, $7, 
+	                                         (LEX_STRING*) 0,
+	                                         TL_OPTION_UPDATING,
+	                                         TL_WRITE))
+	    YYABORT;
+	}
 	;
 
-check_option:
-        /* empty */
-          { Lex->create_view_check= VIEW_CHECK_NONE; }
-        | WITH CHECK_SYM OPTION
-          { Lex->create_view_check= VIEW_CHECK_CASCADED; }
-        | WITH CASCADED CHECK_SYM OPTION
-          { Lex->create_view_check= VIEW_CHECK_CASCADED; }
-        | WITH LOCAL_SYM CHECK_SYM OPTION
-          { Lex->create_view_check= VIEW_CHECK_LOCAL; }
-        ;
+/*************************************************************************/
 
 xa: XA_SYM begin_or_start xid opt_join_or_resume
       {

--- 1.115/sql/table.h	2005-11-07 16:24:45 +01:00
+++ 1.116/sql/table.h	2005-11-18 16:06:35 +01:00
@@ -802,7 +802,15 @@
   table_map         used_tables;     /* bitmap of tables in the nested join */
   table_map         not_null_tables; /* tables that rejects nulls           */
   struct st_join_table *first_nested;/* the first nested table in the plan  */
-  uint              counter;         /* to count tables in the nested join  */
+  /* 
+    Used to count tables in the nested join in 2 isolated places:
+    1. In make_outerjoin_info(). 
+    2. check_interleaving_with_nj/restore_prev_nj_state (these are called
+       by the join optimizer. 
+    Before each use the counters are zeroed by reset_nj_counters.
+  */
+  uint              counter;
+  nested_join_map   nj_map;          /* Bit used to identify this nested join*/
 } NESTED_JOIN;
 
 

--- 1.115/support-files/mysql.spec.sh	2005-11-04 21:10:00 +01:00
+++ 1.116/support-files/mysql.spec.sh	2005-11-18 16:06:35 +01:00
@@ -361,8 +361,9 @@
 %if %{STATIC_BUILD}
 		--with-mysqld-ldflags='-all-static' \
 		--with-client-ldflags='-all-static' \
-		--with-zlib-dir=bundled \
 		$USE_OTHER_LIBC_DIR \
+%else
+		--with-zlib-dir=bundled \
 %endif
 		--with-comment=\"MySQL Community Edition - Standard (GPL)\" \
 		--with-server-suffix='%{server_suffix}' \

--- 1.122/mysql-test/t/view.test	2005-11-10 20:24:51 +01:00
+++ 1.123/mysql-test/t/view.test	2005-11-18 16:06:32 +01:00
@@ -1804,7 +1804,9 @@
 # underlying tables (BUG#6443)
 #
 set sql_mode='strict_all_tables';
+--disable_warnings
 CREATE TABLE t1 (col1 INT NOT NULL, col2 INT NOT NULL) ENGINE = INNODB;
+--enable_warnings
 CREATE VIEW v1 (vcol1) AS SELECT col1 FROM t1;
 CREATE VIEW v2 (vcol1) AS SELECT col1 FROM t1 WHERE col2 > 2;
 -- error 1364
@@ -1860,7 +1862,9 @@
 #
 # Test for bug #11771: wrong query_id in SELECT * FROM <view>
 #
+--disable_warnings
 CREATE TABLE t1 (f1 char) ENGINE = innodb;
+--enable_warnings
 INSERT INTO t1 VALUES ('A');
 CREATE VIEW  v1 AS SELECT * FROM t1;
 

--- 1.21/sql/examples/ha_tina.cc	2005-11-07 16:24:36 +01:00
+++ 1.22/sql/examples/ha_tina.cc	2005-11-18 16:37:55 +01:00
@@ -95,11 +95,15 @@
  *****************************************************************************/
 
 /*
-  Used for sorting  chains.
+  Used for sorting chains with qsort().
 */
 int sort_set (tina_set *a, tina_set *b)
 {
-  return ( a->begin > b->begin ? 1 : ( a->begin < b->begin ? -1 : 0 ) );
+  /*
+    We assume that intervals do not intersect. So, it is enought to compare
+    any two points. Here we take start of intervals for comparison.
+  */
+  return ( a->begin > b->begin ? -1 : ( a->begin < b->begin ? 1 : 0 ) );
 }
 
 static byte* tina_get_key(TINA_SHARE *share,uint *length,
@@ -200,7 +204,8 @@
     thr_lock_init(&share->lock);
     pthread_mutex_init(&share->mutex,MY_MUTEX_INIT_FAST);
 
-    if ((share->data_file= my_open(data_file_name, O_RDWR, MYF(0))) == -1)
+    if ((share->data_file= my_open(data_file_name, O_RDWR|O_APPEND,
+                                   MYF(0))) == -1)
       goto error2;
 
     /*
@@ -836,14 +841,8 @@
           (qsort_cmp)sort_set);
     for (ptr= chain; ptr < chain_ptr; ptr++)
     {
-      /* We peek a head to see if this is the last chain */
-      if (ptr+1 == chain_ptr)
-        memmove(share->mapped_file + ptr->begin, share->mapped_file + ptr->end,
-                length - (size_t)ptr->end);
-      else
-        memmove((caddr_t)share->mapped_file + ptr->begin,
-                (caddr_t)share->mapped_file + ptr->end,
-                (size_t)((ptr++)->begin - ptr->end));
+      memmove(share->mapped_file + ptr->begin, share->mapped_file + ptr->end,
+              length - (size_t)ptr->end);
       length= length - (size_t)(ptr->end - ptr->begin);
     }
 

--- 1.88/mysql-test/r/information_schema.result	2005-11-06 13:12:47 +01:00
+++ 1.89/mysql-test/r/information_schema.result	2005-11-18 16:06:32 +01:00
@@ -648,12 +648,16 @@
 select table_name from information_schema.views
 where table_schema='test';
 table_name
+v2
+v3
 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
 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
 select table_name from information_schema.views
 where table_schema='test';
 table_name
+v2
+v3
 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
 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
@@ -670,6 +674,16 @@
 select constraint_name from information_schema.table_constraints
 where table_schema='test';
 constraint_name
+show create view v2;
+View	Create View
+v2	CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v2` AS select `test`.`t1`.`f1` AS `c` from `t1`
+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 sql_no_cache `test`.`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;
 drop view v3;
 drop table t4;
@@ -723,6 +737,7 @@
 information_schema	TRIGGERS	ACTION_CONDITION
 information_schema	TRIGGERS	ACTION_STATEMENT
 information_schema	TRIGGERS	SQL_MODE
+information_schema	TRIGGERS	DEFINER
 information_schema	VIEWS	VIEW_DEFINITION
 select table_name, column_name, data_type from information_schema.columns
 where data_type = 'datetime';
@@ -801,45 +816,45 @@
 end if;
 end|
 show triggers;
-Trigger	Event	Table	Statement	Timing	Created	sql_mode
+Trigger	Event	Table	Statement	Timing	Created	sql_mode	Definer
 trg1	INSERT	t1	
 begin
 if new.j > 10 then
 set new.j := 10;
 end if;
-end	BEFORE	NULL	
+end	BEFORE	NULL		root@localhost
 trg2	UPDATE	t1	
 begin
 if old.i % 2 = 0 then
 set new.j := -1;
 end if;
-end	BEFORE	NULL	
+end	BEFORE	NULL		root@localhost
 trg3	UPDATE	t1	
 begin
 if new.j = -1 then
 set @fired:= "Yes";
 end if;
-end	AFTER	NULL	
+end	AFTER	NULL		root@localhost
 select * from information_schema.triggers;
-TRIGGER_CATALOG	TRIGGER_SCHEMA	TRIGGER_NAME	EVENT_MANIPULATION	EVENT_OBJECT_CATALOG	EVENT_OBJECT_SCHEMA	EVENT_OBJECT_TABLE	ACTION_ORDER	ACTION_CONDITION	ACTION_STATEMENT	ACTION_ORIENTATION	ACTION_TIMING	ACTION_REFERENCE_OLD_TABLE	ACTION_REFERENCE_NEW_TABLE	ACTION_REFERENCE_OLD_ROW	ACTION_REFERENCE_NEW_ROW	CREATED	SQL_MODE
+TRIGGER_CATALOG	TRIGGER_SCHEMA	TRIGGER_NAME	EVENT_MANIPULATION	EVENT_OBJECT_CATALOG	EVENT_OBJECT_SCHEMA	EVENT_OBJECT_TABLE	ACTION_ORDER	ACTION_CONDITION	ACTION_STATEMENT	ACTION_ORIENTATION	ACTION_TIMING	ACTION_REFERENCE_OLD_TABLE	ACTION_REFERENCE_NEW_TABLE	ACTION_REFERENCE_OLD_ROW	ACTION_REFERENCE_NEW_ROW	CREATED	SQL_MODE	DEFINER
 NULL	test	trg1	INSERT	NULL	test	t1	0	NULL	
 begin
 if new.j > 10 then
 set new.j := 10;
 end if;
-end	ROW	BEFORE	NULL	NULL	OLD	NEW	NULL	
+end	ROW	BEFORE	NULL	NULL	OLD	NEW	NULL		root@localhost
 NULL	test	trg2	UPDATE	NULL	test	t1	0	NULL	
 begin
 if old.i % 2 = 0 then
 set new.j := -1;
 end if;
-end	ROW	BEFORE	NULL	NULL	OLD	NEW	NULL	
+end	ROW	BEFORE	NULL	NULL	OLD	NEW	NULL		root@localhost
 NULL	test	trg3	UPDATE	NULL	test	t1	0	NULL	
 begin
 if new.j = -1 then
 set @fired:= "Yes";
 end if;
-end	ROW	AFTER	NULL	NULL	OLD	NEW	NULL	
+end	ROW	AFTER	NULL	NULL	OLD	NEW	NULL		root@localhost
 drop trigger trg1;
 drop trigger trg2;
 drop trigger trg3;

--- 1.40/mysql-test/mysql-test-run.pl	2005-11-04 21:09:53 +01:00
+++ 1.41/mysql-test/mysql-test-run.pl	2005-11-18 16:06:32 +01:00
@@ -930,7 +930,7 @@
     }
     $exe_mysqlcheck=     mtr_exe_exists("$path_client_bindir/mysqlcheck");
     $exe_mysqldump=      mtr_exe_exists("$path_client_bindir/mysqldump");
-    $exe_mysqlimport=      mtr_exe_exists("$path_client_bindir/mysqlimport");
+    $exe_mysqlimport=    mtr_exe_exists("$path_client_bindir/mysqlimport");
     $exe_mysqlshow=      mtr_exe_exists("$path_client_bindir/mysqlshow");
     $exe_mysqlbinlog=    mtr_exe_exists("$path_client_bindir/mysqlbinlog");
     $exe_mysqladmin=     mtr_exe_exists("$path_client_bindir/mysqladmin");
@@ -947,6 +947,7 @@
     $path_client_bindir= mtr_path_exists("$glob_basedir/bin");
     $exe_mysqlcheck=     mtr_exe_exists("$path_client_bindir/mysqlcheck");
     $exe_mysqldump=      mtr_exe_exists("$path_client_bindir/mysqldump");
+    $exe_mysqlimport=    mtr_exe_exists("$path_client_bindir/mysqlimport");
     $exe_mysqlshow=      mtr_exe_exists("$path_client_bindir/mysqlshow");
     $exe_mysqlbinlog=    mtr_exe_exists("$path_client_bindir/mysqlbinlog");
     $exe_mysqladmin=     mtr_exe_exists("$path_client_bindir/mysqladmin");
@@ -2008,7 +2009,7 @@
   mtr_add_arg($args, "%s--basedir=%s", $prefix, $path_my_basedir);
   mtr_add_arg($args, "%s--character-sets-dir=%s", $prefix, $path_charsetsdir);
   mtr_add_arg($args, "%s--core", $prefix);
-  mtr_add_arg($args, "%s--log-bin-trust-routine-creators", $prefix);
+  mtr_add_arg($args, "%s--log-bin-trust-function-creators", $prefix);
   mtr_add_arg($args, "%s--default-character-set=latin1", $prefix);
   mtr_add_arg($args, "%s--language=%s", $prefix, $path_language);
   mtr_add_arg($args, "%s--tmpdir=$opt_tmpdir", $prefix);
@@ -2131,7 +2132,7 @@
   mtr_add_arg($args, "%s--key_buffer_size=1M", $prefix);
   mtr_add_arg($args, "%s--sort_buffer=256K", $prefix);
   mtr_add_arg($args, "%s--max_heap_table_size=1M", $prefix);
-  mtr_add_arg($args, "%s--log-bin-trust-routine-creators", $prefix);
+  mtr_add_arg($args, "%s--log-bin-trust-function-creators", $prefix);
 
   if ( $opt_ssl_supported )
   {

--- 1.73.11.2/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp	2005-10-27 17:21:57 +02:00
+++ 1.94/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp	2005-11-18 16:06:35 +01:00
@@ -340,7 +340,7 @@
   tabptr.p->noOfKeyAttr = desc->noOfKeyAttr;
   tabptr.p->hasCharAttr = desc->hasCharAttr;
   tabptr.p->noOfDistrKeys = desc->noOfDistrKeys;
-  
+  tabptr.p->hasVarKeys = desc->noOfVarKeys > 0;
   signal->theData[0] = tabptr.i;
   signal->theData[1] = retPtr;
   sendSignal(retRef, GSN_TC_SCHVERCONF, signal, 2, JBB);
@@ -2302,14 +2302,15 @@
 {
   Uint64 Tmp[MAX_KEY_SIZE_IN_WORDS * MAX_XFRM_MULTIPLY];
   const TableRecord* tabPtrP = &tableRecord[tabPtrI];
+  const bool hasVarKeys = tabPtrP->hasVarKeys;
   const bool hasCharAttr = tabPtrP->hasCharAttr;
-  const bool hasDistKeys = tabPtrP->noOfDistrKeys > 0;
+  const bool compute_distkey = distr && (tabPtrP->noOfDistrKeys > 0);
   
   Uint32 *dst = (Uint32*)Tmp;
   Uint32 dstPos = 0;
   Uint32 keyPartLen[MAX_ATTRIBUTES_IN_INDEX];
   Uint32 * keyPartLenPtr;
-  if(hasCharAttr)
+  if(hasCharAttr || (compute_distkey && hasVarKeys))
   {
     keyPartLenPtr = keyPartLen;
     dstPos = xfrm_key(tabPtrI, src, dst, sizeof(Tmp) >> 2, keyPartLenPtr);
@@ -2324,7 +2325,7 @@
   
   md5_hash(dstHash, (Uint64*)dst, dstPos);
   
-  if(distr && hasDistKeys)
+  if(compute_distkey)
   {
     jam();
     
@@ -2728,12 +2729,14 @@
   Uint8 TDirtyFlag          = tcKeyReq->getDirtyFlag(Treqinfo);
   Uint8 TInterpretedFlag    = tcKeyReq->getInterpretedFlag(Treqinfo);
   Uint8 TDistrKeyFlag       = tcKeyReq->getDistributionKeyFlag(Treqinfo);
+  Uint8 TNoDiskFlag         = TcKeyReq::getNoDiskFlag(Treqinfo);
   Uint8 TexecuteFlag        = TexecFlag;
   
   regCachePtr->opSimple = TSimpleFlag;
   regCachePtr->opExec   = TInterpretedFlag;
   regTcPtr->dirtyOp  = TDirtyFlag;
   regCachePtr->distributionKeyIndicator = TDistrKeyFlag;
+  regCachePtr->m_no_disk_flag = TNoDiskFlag;
 
   //-------------------------------------------------------------
   // The next step is to read the upto three conditional words.
@@ -3198,6 +3201,8 @@
   LqhKeyReq::setInterpretedFlag(Tdata10, regCachePtr->opExec);
   LqhKeyReq::setSimpleFlag(Tdata10, regCachePtr->opSimple);
   LqhKeyReq::setOperation(Tdata10, regTcPtr->operation);
+  LqhKeyReq::setNoDiskFlag(Tdata10, regCachePtr->m_no_disk_flag);
+
   /* ----------------------------------------------------------------------- 
    * Sequential Number of first LQH = 0, bit 22-23                           
    * IF ATTRIBUTE INFORMATION IS SENT IN TCKEYREQ,
@@ -3910,7 +3915,7 @@
   const UintR TopWords = (UintR)regApiPtr->tckeyrec;
   localHostptr.i = refToNode(regApiPtr->ndbapiBlockref);
   const Uint32 type = getNodeInfo(localHostptr.i).m_type;
-  const bool is_api = (type >= NodeInfo::API && type <= NodeInfo::REP);
+  const bool is_api = (type >= NodeInfo::API && type <= NodeInfo::MGM);
   const BlockNumber TblockNum = refToBlock(regApiPtr->ndbapiBlockref);
   const Uint32 Tmarker = (regApiPtr->commitAckMarker == RNIL) ? 0 : 1;
   ptrAss(localHostptr, hostRecord);
@@ -4592,7 +4597,8 @@
     commitConf->transId1 = regApiPtr->transid[0];
     commitConf->transId2 = regApiPtr->transid[1];
     commitConf->gci = regApiPtr->globalcheckpointid;
-    sendSignal(regApiPtr->ndbapiBlockref, GSN_TC_COMMITCONF, signal, 
+
+    sendSignal(regApiPtr->ndbapiBlockref, GSN_TC_COMMITCONF, signal,
 	       TcCommitConf::SignalLength, JBB);
   } else if (regApiPtr->returnsignal == RS_NO_RETURN) {
     jam();
@@ -5130,6 +5136,19 @@
 	return;
       }
       
+      /* Only ref in certain situations */
+      {
+	const Uint32 opType = regTcPtr->operation;
+	if (   (opType == ZDELETE && errCode != ZNOT_FOUND)
+	    || (opType == ZINSERT && errCode != ZALREADYEXIST)
+	    || (opType == ZUPDATE && errCode != ZNOT_FOUND)
+	    || (opType == ZWRITE  && errCode != 839 && errCode != 840))
+	{
+	  TCKEY_abort(signal, 49);
+	  return;
+	}
+      }
+
       /* *************** */
       /*    TCKEYREF   < */
       /* *************** */
@@ -8749,6 +8768,7 @@
   ScanFragReq::setDescendingFlag(tmp, ScanTabReq::getDescendingFlag(ri));
   ScanFragReq::setTupScanFlag(tmp, ScanTabReq::getTupScanFlag(ri));
   ScanFragReq::setAttrLen(tmp, scanTabReq->attrLenKeyLen & 0xFFFF);
+  ScanFragReq::setNoDiskFlag(tmp, ScanTabReq::getNoDiskFlag(ri));
   
   scanptr.p->scanRequestInfo = tmp;
   scanptr.p->scanStoredProcId = scanTabReq->storedProcId;
@@ -10106,6 +10126,7 @@
     tabptr.p->noOfKeyAttr = 0;
     tabptr.p->hasCharAttr = 0;
     tabptr.p->noOfDistrKeys = 0;
+    tabptr.p->hasVarKeys = 0;
   }//for
 }//Dbtc::initTable()
 
@@ -11140,7 +11161,6 @@
   ApiConnectRecordPtr transPtr;
   TcConnectRecord *localTcConnectRecord = tcConnectRecord;
   TcConnectRecordPtr opPtr;
-
   /**
    * TODO
    * Check transid,
@@ -11154,6 +11174,7 @@
     
     c_firedTriggerHash.remove(trigPtr);
 
+    trigPtr.p->fragId= fireOrd->fragId;
     bool ok = trigPtr.p->keyValues.getSize() == fireOrd->m_noPrimKeyWords;
     ok &= trigPtr.p->afterValues.getSize() == fireOrd->m_noAfterValueWords;
     ok &= trigPtr.p->beforeValues.getSize() == fireOrd->m_noBeforeValueWords;
@@ -11365,7 +11386,7 @@
   const UintR TopWords = (UintR)regApiPtr->tcindxrec;
   localHostptr.i = refToNode(regApiPtr->ndbapiBlockref);
   const Uint32 type = getNodeInfo(localHostptr.i).m_type;
-  const bool is_api = (type >= NodeInfo::API && type <= NodeInfo::REP);
+  const bool is_api = (type >= NodeInfo::API && type <= NodeInfo::MGM);
   const BlockNumber TblockNum = refToBlock(regApiPtr->ndbapiBlockref);
   const Uint32 Tmarker = (regApiPtr->commitAckMarker == RNIL ? 0 : 1);
   ptrAss(localHostptr, hostRecord);
@@ -12053,7 +12074,11 @@
   Uint32 dataPos = 0;
   TcKeyReq * const tcIndxReq = &indexOp->tcIndxReq;
   TcKeyReq * const tcKeyReq = (TcKeyReq *)signal->getDataPtrSend();
-  Uint32 * dataPtr = &tcKeyReq->scanInfo;
+  /*
+    Data points to distrGroupHashValue since scanInfo is used to send
+    fragment id of receiving fragment
+  */
+  Uint32 * dataPtr = &tcKeyReq->distrGroupHashValue;
   Uint32 tcKeyLength = TcKeyReq::StaticLength;
   Uint32 tcKeyRequestInfo = tcIndxReq->requestInfo;
   TcIndexData* indexData;
@@ -12092,11 +12117,16 @@
   regApiPtr->executingIndexOp = indexOp->indexOpId;;
   regApiPtr->noIndexOp++; // Increase count
 
-  // Filter out AttributeHeader:s since this should not be in key
+  /*
+    Filter out AttributeHeader:s since this should not be in key.
+    Also filter out fragment id from primary key and handle that
+    separately by setting it as Distribution Key and set indicator.
+  */
+
   AttributeHeader* attrHeader = (AttributeHeader *) aiIter.data;
     
   Uint32 headerSize = attrHeader->getHeaderSize();
-  Uint32 keySize = attrHeader->getDataSize();
+  Uint32 keySize = attrHeader->getDataSize() - 1;
   TcKeyReq::setKeyLength(tcKeyRequestInfo, keySize);
   // Skip header
   if (headerSize == 1) {
@@ -12106,6 +12136,9 @@
     jam();
     moreKeyData = indexOp->transIdAI.next(aiIter, headerSize - 1);
   }//if
+  tcKeyReq->scanInfo = *aiIter.data; //Fragment Id
+  moreKeyData = indexOp->transIdAI.next(aiIter);
+  TcKeyReq::setDistributionKeyFlag(tcKeyRequestInfo, 1U);
   while(// If we have not read complete key
 	(keySize != 0) &&
 	(dataPos < keyBufSize)) {
@@ -12461,7 +12494,7 @@
   AttributeBuffer::DataBufferIterator iter;
   Uint32 attrId = 0;
   Uint32 keyLength = 0;
-  Uint32 totalPrimaryKeyLength = 0;
+  Uint32 totalPrimaryKeyLength = 1; // fragment length
   Uint32 hops;
 
   indexTabPtr.i = indexData->indexId;
@@ -12514,11 +12547,12 @@
     hops = attrHeader->getHeaderSize() + attrHeader->getDataSize();
     moreAttrData = keyValues.next(iter, hops);
   }
-  AttributeHeader pkAttrHeader(attrId, totalPrimaryKeyLength);
+  AttributeHeader pkAttrHeader(attrId, totalPrimaryKeyLength << 2);
+  Uint32 attributesLength = afterValues.getSize() + 
+    pkAttrHeader.getHeaderSize() + pkAttrHeader.getDataSize();
   
   TcKeyReq::setKeyLength(tcKeyRequestInfo, keyLength);
-  tcKeyReq->attrLen = afterValues.getSize() + 
-    pkAttrHeader.getHeaderSize() + pkAttrHeader.getDataSize();
+  tcKeyReq->attrLen = attributesLength;
   tcKeyReq->tableId = indexData->indexId;
   TcKeyReq::setOperationType(tcKeyRequestInfo, ZINSERT);
   TcKeyReq::setExecutingTrigger(tcKeyRequestInfo, true);
@@ -12568,8 +12602,11 @@
   }
 
   tcKeyLength += dataPos;
-  Uint32 attributesLength = afterValues.getSize() + 
-    pkAttrHeader.getHeaderSize() + pkAttrHeader.getDataSize();
+  /*
+    Size of attrinfo is unique index attributes one by one, header for each
+    of them (all contained in the afterValues data structure), plus a header,
+    the primary key (compacted) and the fragment id before the primary key
+  */
   if (attributesLength <= attrBufSize) {
     jam();
     // ATTRINFO fits in TCKEYREQ
@@ -12586,6 +12623,10 @@
     // as one attribute
     pkAttrHeader.insertHeader(dataPtr);
     dataPtr += pkAttrHeader.getHeaderSize();
+    /*
+      Insert fragment id before primary key as part of reference to tuple
+    */
+    *dataPtr++ = firedTriggerData->fragId;
     moreAttrData = keyValues.first(iter);
     while(moreAttrData) {
       jam();
@@ -12750,6 +12791,29 @@
     pkAttrHeader.insertHeader(dataPtr);
     dataPtr += pkAttrHeader.getHeaderSize();
     attrInfoPos += pkAttrHeader.getHeaderSize();
+    /*
+      Add fragment id before primary key
+      TODO: This code really needs to be made into a long signal
+      to remove this messy code.
+    */
+    if (attrInfoPos == AttrInfo::DataLength)
+    {
+      jam();
+      // Flush ATTRINFO
+#if INTERNAL_TRIGGER_TCKEYREQ_JBA
+      sendSignal(reference(), GSN_ATTRINFO, signal, 
+                 AttrInfo::HeaderLength + AttrInfo::DataLength, JBA);
+#else
+      EXECUTE_DIRECT(DBTC, GSN_ATTRINFO, signal,
+                     AttrInfo::HeaderLength + AttrInfo::DataLength);
+      jamEntry();
+#endif
+      dataPtr = (Uint32 *) &attrInfo->attrData;	  
+      attrInfoPos = 0;
+    }
+    attrInfoPos++;
+    *dataPtr++ = firedTriggerData->fragId;
+
     moreAttrData = keyValues.first(iter);
     while(moreAttrData) {
       jam();

--- 1.8.5.1/ndb/src/ndbapi/NdbImpl.hpp	2005-10-27 17:17:59 +02:00
+++ 1.15/storage/ndb/src/ndbapi/NdbImpl.hpp	2005-11-18 16:06:35 +01:00
@@ -55,6 +55,10 @@
   NdbImpl(Ndb_cluster_connection *, Ndb&);
   ~NdbImpl();
 
+  int send_event_report(Uint32 *data, Uint32 length);
+
+  Ndb &m_ndb;
+
   Ndb_cluster_connection_impl &m_ndb_cluster_connection;
 
   NdbDictionaryImpl m_dictionary;
@@ -73,6 +77,8 @@
 
   NdbWaiter             theWaiter;
 
+  NdbEventOperationImpl *m_ev_op;
+
   int m_optimized_node_selection;
 
   BaseString m_dbname; // Database name
@@ -113,13 +119,13 @@
 #endif
 
 #define CHECK_STATUS_MACRO \
-   {if (checkInitState() == -1) { theError.code = 4100; return -1;}}
+   {if (checkInitState() == -1) { theError.code = 4100; DBUG_RETURN(-1);}}
 #define CHECK_STATUS_MACRO_VOID \
-   {if (checkInitState() == -1) { theError.code = 4100; return;}}
+   {if (checkInitState() == -1) { theError.code = 4100; DBUG_VOID_RETURN;}}
 #define CHECK_STATUS_MACRO_ZERO \
-   {if (checkInitState() == -1) { theError.code = 4100; return 0;}}
+   {if (checkInitState() == -1) { theError.code = 4100; DBUG_RETURN(0);}}
 #define CHECK_STATUS_MACRO_NULL \
-   {if (checkInitState() == -1) { theError.code = 4100; return NULL;}}
+   {if (checkInitState() == -1) { theError.code = 4100; DBUG_RETURN(NULL);}}
 
 inline
 void *

--- 1.20.3.1/ndb/src/ndbapi/NdbRecAttr.cpp	2005-10-27 17:14:42 +02:00
+++ 1.25/storage/ndb/src/ndbapi/NdbRecAttr.cpp	2005-11-18 16:37:56 +01:00
@@ -38,6 +38,7 @@
 {
   return setup(&(col->m_impl), aValue);
 }
+
 int
 NdbRecAttr::setup(const NdbColumnImpl* anAttrInfo, char* aValue)
 {
@@ -48,15 +49,12 @@
   m_column = anAttrInfo;
 
   theAttrId = anAttrInfo->m_attrId;
-  theAttrSize = tAttrSize;
-  theArraySize = tArraySize;
+  m_size_in_bytes = tAttrByteSize;
   theValue = aValue;
-  theNULLind = 0;
-  m_nullable = anAttrInfo->m_nullable;
 
   if (theStorageX)
     delete[] theStorageX;
-
+  
   // check alignment to signal data
   // a future version could check alignment per data type as well
   
@@ -93,7 +91,7 @@
   char* tRef = (char*)theRef;
   char* tValue = theValue;
   if (tRef != tValue && tRef != NULL && tValue != NULL) {
-    Uint32 n = theAttrSize * theArraySize;
+    Uint32 n = m_size_in_bytes;
     while (n-- > 0) {
       *tValue++ = *tRef++;
     }
@@ -105,12 +103,10 @@
   NdbRecAttr * ret = new NdbRecAttr(0);
 
   ret->theAttrId = theAttrId;
-  ret->theNULLind = theNULLind;
-  ret->theAttrSize = theAttrSize;
-  ret->theArraySize = theArraySize;
+  ret->m_size_in_bytes = m_size_in_bytes;
   ret->m_column = m_column;
   
-  Uint32 n = theAttrSize * theArraySize;  
+  Uint32 n = m_size_in_bytes;
   if(n <= 32){
     ret->theRef = (char*)&ret->theStorage[0];
     ret->theStorageX = 0;
@@ -126,17 +122,19 @@
 
 bool
 NdbRecAttr::receive_data(const Uint32 * data, Uint32 sz){
-  const Uint32 n = (theAttrSize * theArraySize + 3) >> 2;  
-  if(n == sz){
-    theNULLind = 0;
+  const Uint32 n = m_size_in_bytes;
+  if(sz)
+  {
     if(!copyoutRequired())
-      memcpy(theRef, data, 4 * sz);
+      memcpy(theRef, data, sz);
     else
-      memcpy(theValue, data, theAttrSize * theArraySize);
-    return true;
-  } else if(sz == 0){
-    setNULL();
+      memcpy(theValue, data, sz);
+    m_size_in_bytes= sz;
     return true;
+  } 
+  else 
+  {
+    return setNULL();
   }
   return false;
 }
@@ -182,7 +180,7 @@
     out << "[NULL]";
     return out;
   }
-
+  
   const NdbDictionary::Column* c = r.getColumn();
   uint length = c->getLength();
   if (length > 1)
@@ -193,196 +191,195 @@
     if (j > 0)
       out << " ";
 
-    switch(r.getType())
-      {
-      case NdbDictionary::Column::Bigunsigned:
-	out << r.u_64_value();
-	break;
-      case NdbDictionary::Column::Bit:
-	out << hex << "H'" << r.u_32_value() << dec;
-	break;
-      case NdbDictionary::Column::Unsigned:
-	out << r.u_32_value();
-	break;
-      case NdbDictionary::Column::Smallunsigned:
-	out << r.u_short_value();
-	break;
-      case NdbDictionary::Column::Tinyunsigned:
-	out << (unsigned) r.u_char_value();
-	break;
-      case NdbDictionary::Column::Bigint:
-	out << r.int64_value();
-	break;
-      case NdbDictionary::Column::Int:
-	out << r.int32_value();
-	break;
-      case NdbDictionary::Column::Smallint:
-	out << r.short_value();
-	break;
-      case NdbDictionary::Column::Tinyint:
-	out << (int) r.char_value();
-	break;
-      case NdbDictionary::Column::Binary:
-	ndbrecattr_print_string(out,"Binary",r.aRef(),r.arraySize());
-	j = r.arraySize();
-	break;
-      case NdbDictionary::Column::Char:
-	ndbrecattr_print_string(out,"Char",r.aRef(),r.arraySize());
-	j = length;
-	break;
-      case NdbDictionary::Column::Varchar:
-        {
-          unsigned len = *(const unsigned char*)r.aRef();
-          ndbrecattr_print_string(out,"Varchar", r.aRef()+1,len);
-          j = length;
-        }
-	break;
-      case NdbDictionary::Column::Varbinary:
-        {
-          unsigned len = *(const unsigned char*)r.aRef();
-          ndbrecattr_print_string(out,"Varbinary", r.aRef()+1,len);
-          j = length;
-        }
-	break;
-      case NdbDictionary::Column::Float:
-	out << r.float_value();
-	break;
-      case NdbDictionary::Column::Double:
-	out << r.double_value();
-	break;
-      case NdbDictionary::Column::Olddecimal:
-        {
-          short len = 1 + c->getPrecision() + (c->getScale() > 0);
-          out.print("%.*s", len, r.aRef());
-        }
-        break;
-      case NdbDictionary::Column::Olddecimalunsigned:
-        {
-          short len = 0 + c->getPrecision() + (c->getScale() > 0);
-          out.print("%.*s", len, r.aRef());
-        }
-	break;
-      case NdbDictionary::Column::Decimal:
-      case NdbDictionary::Column::Decimalunsigned:
-        goto unknown;   // TODO
-        break;
+    switch(r.getType()){
+    case NdbDictionary::Column::Bigunsigned:
+      out << r.u_64_value();
+      break;
+    case NdbDictionary::Column::Bit:
+      out << hex << "H'" << r.u_32_value() << dec;
+      break;
+    case NdbDictionary::Column::Unsigned:
+      out << r.u_32_value();
+      break;
+    case NdbDictionary::Column::Smallunsigned:
+      out << r.u_short_value();
+      break;
+    case NdbDictionary::Column::Tinyunsigned:
+      out << (unsigned) r.u_char_value();
+      break;
+    case NdbDictionary::Column::Bigint:
+      out << r.int64_value();
+      break;
+    case NdbDictionary::Column::Int:
+      out << r.int32_value();
+      break;
+    case NdbDictionary::Column::Smallint:
+      out << r.short_value();
+      break;
+    case NdbDictionary::Column::Tinyint:
+      out << (int) r.char_value();
+      break;
+    case NdbDictionary::Column::Binary:
+      j = r.get_size_in_bytes();
+      ndbrecattr_print_string(out,"Binary", r.aRef(), j);
+      break;
+    case NdbDictionary::Column::Char:
+      j = r.get_size_in_bytes();
+      ndbrecattr_print_string(out,"Char", r.aRef(), j);
+      break;
+    case NdbDictionary::Column::Varchar:
+    {
+      unsigned len = *(const unsigned char*)r.aRef();
+      ndbrecattr_print_string(out,"Varchar", r.aRef()+1,len);
+      j = length;
+    }
+    break;
+    case NdbDictionary::Column::Varbinary:
+    {
+      unsigned len = *(const unsigned char*)r.aRef();
+      ndbrecattr_print_string(out,"Varbinary", r.aRef()+1,len);
+      j = length;
+    }
+    break;
+    case NdbDictionary::Column::Float:
+      out << r.float_value();
+      break;
+    case NdbDictionary::Column::Double:
+      out << r.double_value();
+      break;
+    case NdbDictionary::Column::Olddecimal:
+    {
+      short len = 1 + c->getPrecision() + (c->getScale() > 0);
+      out.print("%.*s", len, r.aRef());
+    }
+    break;
+    case NdbDictionary::Column::Olddecimalunsigned:
+    {
+      short len = 0 + c->getPrecision() + (c->getScale() > 0);
+      out.print("%.*s", len, r.aRef());
+    }
+    break;
+    case NdbDictionary::Column::Decimal:
+    case NdbDictionary::Column::Decimalunsigned:
+      goto unknown;   // TODO
+      break;
       // for dates cut-and-paste from field.cc
-      case NdbDictionary::Column::Datetime:
-        {
-          ulonglong tmp=r.u_64_value();
-          long part1,part2,part3;
-          part1=(long) (tmp/LL(1000000));
-          part2=(long) (tmp - (ulonglong) part1*LL(1000000));
-          char buf[40];
-          char* pos=(char*) buf+19;
-          *pos--=0;
-          *pos--= (char) ('0'+(char) (part2%10)); part2/=10; 
-          *pos--= (char) ('0'+(char) (part2%10)); part3= (int) (part2 / 10);
-          *pos--= ':';
-          *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
-          *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
-          *pos--= ':';
-          *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
-          *pos--= (char) ('0'+(char) part3);
-          *pos--= '/';
-          *pos--= (char) ('0'+(char) (part1%10)); part1/=10;
-          *pos--= (char) ('0'+(char) (part1%10)); part1/=10;
-          *pos--= '-';
-          *pos--= (char) ('0'+(char) (part1%10)); part1/=10;
-          *pos--= (char) ('0'+(char) (part1%10)); part3= (int) (part1/10);
-          *pos--= '-';
-          *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
-          *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
-          *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
-          *pos=(char) ('0'+(char) part3);
-          out << buf;
-        }
-	break;
-      case NdbDictionary::Column::Date:
-        {
-          uint32 tmp=(uint32) uint3korr(r.aRef());
-          int part;
-          char buf[40];
-          char *pos=(char*) buf+10;
-          *pos--=0;
-          part=(int) (tmp & 31);
-          *pos--= (char) ('0'+part%10);
-          *pos--= (char) ('0'+part/10);
-          *pos--= '-';
-          part=(int) (tmp >> 5 & 15);
-          *pos--= (char) ('0'+part%10);
-          *pos--= (char) ('0'+part/10);
-          *pos--= '-';
-          part=(int) (tmp >> 9);
-          *pos--= (char) ('0'+part%10); part/=10;
-          *pos--= (char) ('0'+part%10); part/=10;
-          *pos--= (char) ('0'+part%10); part/=10;
-          *pos=   (char) ('0'+part);
-          out << buf;
-        }
-	break;
-      case NdbDictionary::Column::Time:
-        {
-          long tmp=(long) sint3korr(r.aRef());
-          int hour=(uint) (tmp/10000);
-          int minute=(uint) (tmp/100 % 100);
-          int second=(uint) (tmp % 100);
-          char buf[40];
-          sprintf(buf, "%02d:%02d:%02d", hour, minute, second);
-          out << buf;
-        }
-	break;
-      case NdbDictionary::Column::Year:
-        {
-          uint year = 1900 + r.u_char_value();
-          char buf[40];
-          sprintf(buf, "%04d", year);
-          out << buf;
-        }
-	break;
-      case NdbDictionary::Column::Timestamp:
-        {
-          time_t time = r.u_32_value();
-          out << (uint)time;
-        }
-	break;
-      case NdbDictionary::Column::Blob:
-        {
-          const NdbBlob::Head* h = (const NdbBlob::Head*)r.aRef();
-          out << h->length << ":";
-          const unsigned char* p = (const unsigned char*)(h + 1);
-          unsigned n = r.arraySize() - sizeof(*h);
-          for (unsigned k = 0; k < n && k < h->length; k++)
-            out.print("%02X", (int)p[k]);
-          j = length;
-        }
-        break;
-      case NdbDictionary::Column::Text:
-        {
-          const NdbBlob::Head* h = (const NdbBlob::Head*)r.aRef();
-          out << h->length << ":";
-          const unsigned char* p = (const unsigned char*)(h + 1);
-          unsigned n = r.arraySize() - sizeof(*h);
-          for (unsigned k = 0; k < n && k < h->length; k++)
-            out.print("%c", (int)p[k]);
-          j = length;
-        }
-        break;
-      case NdbDictionary::Column::Longvarchar:
-        {
-          unsigned len = uint2korr(r.aRef());
-          ndbrecattr_print_string(out,"Longvarchar", r.aRef()+2,len);
-          j = length;
-        }
-        break;
-      unknown:
-      default: /* no print functions for the rest, just print type */
-	out << (int) r.getType();
-	j = length;
-	if (j > 1)
-	  out << " " << j << " times";
-	break;
-      }
+    case NdbDictionary::Column::Datetime:
+    {
+      ulonglong tmp=r.u_64_value();
+      long part1,part2,part3;
+      part1=(long) (tmp/LL(1000000));
+      part2=(long) (tmp - (ulonglong) part1*LL(1000000));
+      char buf[40];
+      char* pos=(char*) buf+19;
+      *pos--=0;
+      *pos--= (char) ('0'+(char) (part2%10)); part2/=10; 
+      *pos--= (char) ('0'+(char) (part2%10)); part3= (int) (part2 / 10);
+      *pos--= ':';
+      *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
+      *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
+      *pos--= ':';
+      *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
+      *pos--= (char) ('0'+(char) part3);
+      *pos--= '/';
+      *pos--= (char) ('0'+(char) (part1%10)); part1/=10;
+      *pos--= (char) ('0'+(char) (part1%10)); part1/=10;
+      *pos--= '-';
+      *pos--= (char) ('0'+(char) (part1%10)); part1/=10;
+      *pos--= (char) ('0'+(char) (part1%10)); part3= (int) (part1/10);
+      *pos--= '-';
+      *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
+      *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
+      *pos--= (char) ('0'+(char) (part3%10)); part3/=10;
+      *pos=(char) ('0'+(char) part3);
+      out << buf;
+    }
+    break;
+    case NdbDictionary::Column::Date:
+    {
+      uint32 tmp=(uint32) uint3korr(r.aRef());
+      int part;
+      char buf[40];
+      char *pos=(char*) buf+10;
+      *pos--=0;
+      part=(int) (tmp & 31);
+      *pos--= (char) ('0'+part%10);
+      *pos--= (char) ('0'+part/10);
+      *pos--= '-';
+      part=(int) (tmp >> 5 & 15);
+      *pos--= (char) ('0'+part%10);
+      *pos--= (char) ('0'+part/10);
+      *pos--= '-';
+      part=(int) (tmp >> 9);
+      *pos--= (char) ('0'+part%10); part/=10;
+      *pos--= (char) ('0'+part%10); part/=10;
+      *pos--= (char) ('0'+part%10); part/=10;
+      *pos=   (char) ('0'+part);
+      out << buf;
+    }
+    break;
+    case NdbDictionary::Column::Time:
+    {
+      long tmp=(long) sint3korr(r.aRef());
+      int hour=(uint) (tmp/10000);
+      int minute=(uint) (tmp/100 % 100);
+      int second=(uint) (tmp % 100);
+      char buf[40];
+      sprintf(buf, "%02d:%02d:%02d", hour, minute, second);
+      out << buf;
+    }
+    break;
+    case NdbDictionary::Column::Year:
+    {
+      uint year = 1900 + r.u_char_value();
+      char buf[40];
+      sprintf(buf, "%04d", year);
+      out << buf;
+    }
+    break;
+    case NdbDictionary::Column::Timestamp:
+    {
+      time_t time = r.u_32_value();
+      out << (uint)time;
+    }
+    break;
+    case NdbDictionary::Column::Blob:
+    {
+      const NdbBlob::Head* h = (const NdbBlob::Head*)r.aRef();
+      out << h->length << ":";
+      const unsigned char* p = (const unsigned char*)(h + 1);
+      unsigned n = r.get_size_in_bytes() - sizeof(*h);
+      for (unsigned k = 0; k < n && k < h->length; k++)
+	out.print("%02X", (int)p[k]);
+      j = length;
+    }
+    break;
+    case NdbDictionary::Column::Text:
+    {
+      const NdbBlob::Head* h = (const NdbBlob::Head*)r.aRef();
+      out << h->length << ":";
+      const unsigned char* p = (const unsigned char*)(h + 1);
+      unsigned n = r.get_size_in_bytes() - sizeof(*h);
+      for (unsigned k = 0; k < n && k < h->length; k++)
+	out.print("%c", (int)p[k]);
+      j = length;
+    }
+    break;
+    case NdbDictionary::Column::Longvarchar:
+    {
+      unsigned len = uint2korr(r.aRef());
+      ndbrecattr_print_string(out,"Longvarchar", r.aRef()+2,len);
+      j = length;
+    }
+    break;
+  unknown:
+    //default: /* no print functions for the rest, just print type */
+    out << (int) r.getType();
+    j = length;
+    if (j > 1)
+      out << " " << j << " times";
+    break;
+    }
   }
 
   if (length > 1)

--- 1.235/sql/ha_innodb.cc	2005-11-07 17:14:55 +01:00
+++ 1.236/sql/ha_innodb.cc	2005-11-18 16:37:55 +01:00
@@ -3030,8 +3030,8 @@
 
 			if (key_part->length > 0 && cs->mbmaxlen > 1) {
 				len = (ulint) cs->cset->well_formed_len(cs, 
-					(const char*)src_start,
-					(const char*)(src_start + key_part->length),
+					(const char *) src_start,
+					(const char *) src_start + key_part->length,
 					key_part->length / cs->mbmaxlen, 
 					&error);
 			} else {

--- 1.113/include/my_global.h	2005-11-06 14:26:18 +01:00
+++ 1.114/include/my_global.h	2005-11-18 16:06:31 +01:00
@@ -641,6 +641,15 @@
 #define O_NOFOLLOW      0
 #endif
 
+/* additional file share flags for win32 */
+#ifdef __WIN__
+#define _SH_DENYRWD     0x110    /* deny read/write mode & delete */
+#define _SH_DENYWRD     0x120    /* deny write mode & delete      */
+#define _SH_DENYRDD     0x130    /* deny read mode & delete       */
+#define _SH_DENYDEL     0x140    /* deny delete only              */
+#endif /* __WIN__ */
+
+
 /* #define USE_RECORD_LOCK	*/
 
 	/* Unsigned types supported by the compiler */

--- 1.144/sql/set_var.cc	2005-11-16 18:43:00 +01:00
+++ 1.145/sql/set_var.cc	2005-11-18 16:37:56 +01:00
@@ -237,9 +237,12 @@
 							      param_age_threshold));
 sys_var_bool_ptr	sys_local_infile("local_infile",
 					 &opt_local_infile);
-sys_var_bool_ptr       
+sys_var_trust_routine_creators
 sys_trust_routine_creators("log_bin_trust_routine_creators",
-                           &trust_routine_creators);
+                           &trust_function_creators);
+sys_var_bool_ptr       
+sys_trust_function_creators("log_bin_trust_function_creators",
+                            &trust_function_creators);
 sys_var_thd_ulong	sys_log_warnings("log_warnings", &SV::log_warnings);
 sys_var_thd_ulong	sys_long_query_time("long_query_time",
 					     &SV::long_query_time);
@@ -585,7 +588,6 @@
 /* Read only variables */
 
 sys_var_const_str		sys_os("version_compile_os", SYSTEM_TYPE);
-
 sys_var_have_variable sys_have_archive_db("have_archive", &have_archive_db);
 sys_var_have_variable sys_have_berkeley_db("have_bdb", &have_berkeley_db);
 sys_var_have_variable sys_have_blackhole_db("have_blackhole_engine",
@@ -609,7 +611,6 @@
 sys_var_have_variable sys_have_raid("have_raid", &have_raid);
 sys_var_have_variable sys_have_rtree_keys("have_rtree_keys", &have_rtree_keys);
 sys_var_have_variable sys_have_symlink("have_symlink", &have_symlink);
-
 /* Global read-only variable describing server license */
 sys_var_const_str		sys_license("license", STRINGIFY_ARG(LICENSE));
 
@@ -742,7 +743,7 @@
 #endif
   {"log",                     (char*) &opt_log,                     SHOW_BOOL},
   {"log_bin",                 (char*) &opt_bin_log,                 SHOW_BOOL},
-  {sys_trust_routine_creators.name,(char*) &sys_trust_routine_creators, SHOW_SYS},
+  {sys_trust_function_creators.name,(char*) &sys_trust_function_creators, SHOW_SYS},
   {"log_error",               (char*) log_error_file,               SHOW_CHAR},
 #ifdef HAVE_REPLICATION
   {"log_slave_updates",       (char*) &opt_log_slave_updates,       SHOW_MY_BOOL},
@@ -3331,6 +3332,26 @@
   return 0;
 }
 
+
+void sys_var_trust_routine_creators::warn_deprecated(THD *thd)
+{
+  push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+		      ER_WARN_DEPRECATED_SYNTAX,
+		      ER(ER_WARN_DEPRECATED_SYNTAX), "log_bin_trust_routine_creators",
+                      "log_bin_trust_function_creators"); 
+}
+
+void sys_var_trust_routine_creators::set_default(THD *thd, enum_var_type type)
+{
+  warn_deprecated(thd);
+  sys_var_bool_ptr::set_default(thd, type);
+}
+
+bool sys_var_trust_routine_creators::update(THD *thd, set_var *var)
+{
+  warn_deprecated(thd);
+  return sys_var_bool_ptr::update(thd, var);
+}
 
 /****************************************************************************
   Used templates

--- 1.74/sql/set_var.h	2005-11-06 01:36:18 +01:00
+++ 1.75/sql/set_var.h	2005-11-18 16:06:33 +01:00
@@ -771,6 +771,17 @@
   byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
 };
 
+class sys_var_trust_routine_creators :public sys_var_bool_ptr
+{
+  /* We need a derived class only to have a warn_deprecated() */
+public:
+  sys_var_trust_routine_creators(const char *name_arg, my_bool *value_arg) :
+    sys_var_bool_ptr(name_arg, value_arg) {};
+  void warn_deprecated(THD *thd);
+  void set_default(THD *thd, enum_var_type type);
+  bool update(THD *thd, set_var *var);
+};
+
 /****************************************************************************
   Classes for parsing of the SET command
 ****************************************************************************/

--- 1.27/scripts/mysql_fix_privilege_tables.sql	2005-11-06 13:12:48 +01:00
+++ 1.28/scripts/mysql_fix_privilege_tables.sql	2005-11-18 16:06:32 +01:00
@@ -35,7 +35,7 @@
 ALTER TABLE host add Grant_priv enum('N','Y') NOT NULL,add References_priv enum('N','Y') COLLATE utf8_general_ci NOT NULL,add Index_priv enum('N','Y') COLLATE utf8_general_ci NOT NULL,add Alter_priv enum('N','Y') COLLATE utf8_general_ci NOT NULL;
 ALTER TABLE db add Grant_priv enum('N','Y') COLLATE utf8_general_ci NOT NULL,add References_priv enum('N','Y') COLLATE utf8_general_ci NOT NULL,add Index_priv enum('N','Y') COLLATE utf8_general_ci NOT NULL,add Alter_priv enum('N','Y') COLLATE utf8_general_ci NOT NULL;
 
---- Fix privileges for old tables
+-- Fix privileges for old tables
 UPDATE user SET Grant_priv=File_priv,References_priv=Create_priv,Index_priv=Create_priv,Alter_priv=Create_priv WHERE @hadGrantPriv = 0;
 UPDATE db SET References_priv=Create_priv,Index_priv=Create_priv,Alter_priv=Create_priv WHERE @hadGrantPriv = 0;
 UPDATE host SET References_priv=Create_priv,Index_priv=Create_priv,Alter_priv=Create_priv WHERE @hadGrantPriv = 0;

--- 1.93/sql/sp.cc	2005-11-04 21:09:55 +01:00
+++ 1.94/sql/sp.cc	2005-11-18 16:06:33 +01:00
@@ -441,8 +441,8 @@
       if (dbchanged && (ret= mysql_change_db(thd, olddb, 1)))
 	goto done;
       *sphp= thd->lex->sphead;
-      (*sphp)->set_info((char *)definer, (uint)strlen(definer),
-			created, modified, &chistics, sql_mode);
+      (*sphp)->set_definer((char*) definer, (uint) strlen(definer));
+      (*sphp)->set_info(created, modified, &chistics, sql_mode);
       (*sphp)->optimize();
     }
     thd->lex->sql_command= oldcmd;
@@ -551,12 +551,13 @@
 	store(sp->m_chistics->comment.str, sp->m_chistics->comment.length,
 	      system_charset_info);
 
-    if (!trust_routine_creators && mysql_bin_log.is_open())
+    if ((sp->m_type == TYPE_ENUM_FUNCTION) &&
+        !trust_function_creators && mysql_bin_log.is_open())
     {
       if (!sp->m_chistics->detistic)
       {
 	/*
-	  Note that for a _function_ this test is not enough; one could use
+	  Note that this test is not perfect; one could use
 	  a non-deterministic read-only function in an update statement.
 	*/
 	enum enum_sp_data_access access=

--- 1.194/sql/sp_head.cc	2005-11-07 16:24:42 +01:00
+++ 1.195/sql/sp_head.cc	2005-11-18 16:06:33 +01:00
@@ -1569,21 +1569,9 @@
 }
 
 void
-sp_head::set_info(char *definer, uint definerlen,
-		  longlong created, longlong modified,
+sp_head::set_info(longlong created, longlong modified,
 		  st_sp_chistics *chistics, ulong sql_mode)
 {
-  char *p= strchr(definer, '@');
-  uint len;
-
-  if (! p)
-    p= definer;		// Weird...
-  len= p-definer;
-  m_definer_user.str= strmake_root(mem_root, definer, len);
-  m_definer_user.length= len;
-  len= definerlen-len-1;
-  m_definer_host.str= strmake_root(mem_root, p+1, len);
-  m_definer_host.length= len;
   m_created= created;
   m_modified= modified;
   m_chistics= (st_sp_chistics *) memdup_root(mem_root, (char*) chistics,
@@ -1596,6 +1584,34 @@
 					  m_chistics->comment.length);
   m_sql_mode= sql_mode;
 }
+
+
+void
+sp_head::set_definer(char *definer, uint definerlen)
+{
+  char *p= strrchr(definer, '@');
+
+  if (!p)
+  {
+    m_definer_user.str= strmake_root(mem_root, "", 0);
+    m_definer_user.length= 0;
+    
+    m_definer_host.str= strmake_root(mem_root, "", 0);
+    m_definer_host.length= 0;
+  }
+  else
+  {
+    const uint user_name_len= p - definer;
+    const uint host_name_len= definerlen - user_name_len - 1;
+
+    m_definer_user.str= strmake_root(mem_root, definer, user_name_len);
+    m_definer_user.length= user_name_len;
+
+    m_definer_host.str= strmake_root(mem_root, p + 1, host_name_len);
+    m_definer_host.length= host_name_len;
+  }
+}
+
 
 void
 sp_head::reset_thd_mem_root(THD *thd)

--- 1.213/BitKeeper/etc/ignore	2005-11-08 01:39:16 +01:00
+++ 1.214/BitKeeper/etc/ignore	2005-11-18 16:06:24 +01:00
@@ -1,21 +1,39 @@
 *.a
 *.bb
 *.bbg
+*.bin
 *.core
 *.d
 *.da
+*.exe
 *.gcov
+*.idb
 *.la
+*.lib
 *.lo
+*.map
 *.o
+*.obj
+*.pch
+*.pdb
 *.reject
+*.res
+*.sbr
 *.so
 *.spec
 */*_pure_*warnings
 */.pure
 *~
 .*.swp
+./README.build-files
 ./config.h
+./copy_mysql_files.bat
+./fix-project-files
+./mysql*.ds?
+./mysql.ncb
+./mysql.sln
+./mysql.suo
+./prepare
 .defs.mk
 .depend
 .depend.mk
@@ -115,6 +133,8 @@
 autom4te.cache/output.0
 autom4te.cache/requests
 autom4te.cache/traces.0
+bdb/*.ds?
+bdb/*.vcproj
 bdb/README
 bdb/btree/btree_auto.c
 bdb/build_unix/*
@@ -256,6 +276,9 @@
 bkpush.log*
 build.log
 build_tags.sh
+client/*.ds?
+client/*.vcproj
+client/completion_hash.cpp
 client/decimal.c
 client/insert_test
 client/log_event.cc
@@ -265,9 +288,12 @@
 client/my_decimal.cc
 client/my_decimal.h
 client/mysql
+client/mysql.cpp
 client/mysqladmin
 client/mysqladmin.c
+client/mysqladmin.cpp
 client/mysqlbinlog
+client/mysqlbinlog.cpp
 client/mysqlcheck
 client/mysqldump
 client/mysqlimport
@@ -278,14 +304,20 @@
 client/mysqltestmanager-pwgen
 client/mysqltestmanagerc
 client/mysys_priv.h
+client/readline.cpp
 client/select_test
+client/sql_string.cpp
 client/ssl_test
 client/thimble
 client/thread_test
+client_debug/*
+client_release/*
 client_test
 cmd-line-utils/libedit/common.h
 cmd-line-utils/libedit/makelist
 comon.h
+comp_err/*.ds?
+comp_err/*.vcproj
 config.cache
 config.guess
 config.h
@@ -295,10 +327,14 @@
 config.sub
 configure
 configure.lineno
+contrib/*.ds?
+contrib/*.vcproj
 core
 core.*
 core.2430
 db-*.*.*
+dbug/*.ds?
+dbug/*.vcproj
 dbug/dbug_analyze
 dbug/example*.r
 dbug/factorial
@@ -309,6 +345,9 @@
 dbug/user.t
 depcomp
 emacs.h
+examples/*.ds?
+examples/*.vcproj
+examples/udf_example/udf_example.def
 extra/charset2html
 extra/comp_err
 extra/created_include_files
@@ -330,6 +369,8 @@
 gdbinit
 gmon.out
 hardcopy.0
+heap/*.ds?
+heap/*.vcproj
 heap/hp_test1
 heap/hp_test2
 help
@@ -345,6 +386,8 @@
 include/readline/readline.h
 include/sql_state.h
 include/widec.h
+innobase/*.ds?
+innobase/*.vcproj
 innobase/autom4te-2.53.cache/*
 innobase/autom4te-2.53.cache/output.0
 innobase/autom4te-2.53.cache/requests
@@ -363,18 +406,28 @@
 insert_test
 install
 install-sh
+isam/*.ds?
+isam/*.vcproj
 isam/isamchk
 isam/isamlog
 isam/pack_isam
 isam/test1
 isam/test2
 isam/test3
+isamchk/*.ds?
+isamchk/*.vcproj
+lib_debug/*
+lib_release/*
 libmysql/*.c
+libmysql/*.ds?
+libmysql/*.vcproj
 libmysql/conf_to_src
+libmysql/debug/libmysql.exp
 libmysql/my_static.h
 libmysql/my_time.c
 libmysql/mysys_priv.h
 libmysql/net.c
+libmysql/release/libmysql.exp
 libmysql/vio_priv.h
 libmysql_r/*.c
 libmysql_r/acconfig.h
@@ -382,12 +435,15 @@
 libmysql_r/my_static.h
 libmysql_r/mysys_priv.h
 libmysql_r/vio_priv.h
+libmysqld/*.ds?
+libmysqld/*.vcproj
 libmysqld/backup_dir
 libmysqld/client.c
 libmysqld/client_settings.h
 libmysqld/convert.cc
 libmysqld/derror.cc
 libmysqld/discover.cc
+libmysqld/emb_qcache.cpp
 libmysqld/errmsg.c
 libmysqld/examples/client_test.c
 libmysqld/examples/client_test.cc
@@ -443,6 +499,7 @@
 libmysqld/item_timefunc.cc
 libmysqld/item_uniq.cc
 libmysqld/key.cc
+libmysqld/lib_sql.cpp
 libmysqld/libmysql.c
 libmysqld/lock.cc
 libmysqld/log.cc
@@ -500,6 +557,7 @@
 libmysqld/sql_olap.cc
 libmysqld/sql_parse.cc
 libmysqld/sql_partition.cc
+libmysqld/sql_plugin.cc
 libmysqld/sql_prepare.cc
 libmysqld/sql_rename.cc
 libmysqld/sql_repl.cc
@@ -516,6 +574,8 @@
 libmysqld/sql_update.cc
 libmysqld/sql_view.cc
 libmysqld/sql_yacc.cc
+libmysqld/sql_yacc.cpp
+libmysqld/sql_yacc.h
 libmysqld/stacktrace.c
 libmysqld/strfunc.cc
 libmysqld/table.cc
@@ -524,6 +584,9 @@
 libmysqld/tztime.cc
 libmysqld/uniques.cc
 libmysqld/unireg.cc
+libmysqltest/*.ds?
+libmysqltest/*.vcproj
+libmysqltest/mytest.c
 libtool
 linked_client_sources
 linked_include_sources
@@ -536,6 +599,8 @@
 locked
 ltmain.sh
 man/*.1
+merge/*.ds?
+merge/*.vcproj
 missing
 mit-pthreads/config.flags
 mit-pthreads/include/bits
@@ -547,6 +612,10 @@
 mit-pthreads/pgcc
 mit-pthreads/syscall.S
 mkinstalldirs
+my_print_defaults/*.ds?
+my_print_defaults/*.vcproj
+myisam/*.ds?
+myisam/*.vcproj
 myisam/FT1.MYD
 myisam/FT1.MYI
 myisam/ft_dump
@@ -572,17 +641,31 @@
 myisam/test1.MYI
 myisam/test2.MYD
 myisam/test2.MYI
+myisam_ftdump/*.ds?
+myisam_ftdump/*.vcproj
+myisamchk/*.ds?
+myisamchk/*.vcproj
+myisamlog/*.ds?
+myisamlog/*.vcproj
+myisammrg/*.ds?
+myisammrg/*.vcproj
+myisampack/*.ds?
+myisampack/*.vcproj
 mysql-4.0.2-alpha-pc-linux-gnu-i686.tar.gz
 mysql-4.0.2-alpha.tar.gz
 mysql-4.1.8-win-src.zip
 mysql-5.0.2-alpha.tar.gz
 mysql-max-4.0.2-alpha-pc-linux-gnu-i686.tar.gz
+mysql-test/*.ds?
+mysql-test/*.vcproj
 mysql-test/gmon.out
 mysql-test/install_test_db
 mysql-test/mysql-test-run
 mysql-test/mysql-test-run.log
 mysql-test/mysql_test_run_new
 mysql-test/ndb/ndbcluster
+mysql-test/r/*.err
+mysql-test/r/*.out
 mysql-test/r/*.reject
 mysql-test/r/alter_table.err
 mysql-test/r/archive.err
@@ -654,13 +737,25 @@
 mysql.kdevprj
 mysql.proj
 mysql_priv.h
+mysqlbinlog/*.ds?
+mysqlbinlog/*.vcproj
+mysqlcheck/*.ds?
+mysqlcheck/*.vcproj
 mysqld.S
 mysqld.sym
+mysqldemb/*.ds?
+mysqldemb/*.vcproj
+mysqlserver/*.ds?
+mysqlserver/*.vcproj
 mysys/#mf_iocache.c#
+mysys/*.ds?
+mysys/*.vcproj
 mysys/charset2html
 mysys/getopt.c
 mysys/getopt1.c
 mysys/main.cc
+mysys/my_new.cpp
+mysys/raid.cpp
 mysys/ste5KbMa
 mysys/test_charset
 mysys/test_dir
@@ -924,13 +1019,20 @@
 ndbcluster-1186/ndb_3_cluster.log
 ndbcluster-1186/ndb_3_out.log
 ndbcluster-1186/ndbcluster.pid
+pack_isam/*.ds?
+perror/*.ds?
+perror/*.vcproj
 pull.log
+regex/*.ds?
+regex/*.vcproj
 regex/re
 repl-tests/test-repl-ts/repl-timestamp.master.reject
 repl-tests/test-repl/foo-dump-slave.master.
 repl-tests/test-repl/sum-wlen-slave.master.
 repl-tests/test-repl/sum-wlen-slave.master.re
 repl-tests/test-repl/sum-wlen-slave.master.reje
+replace/*.ds?
+replace/*.vcproj
 scripts/fill_func_tables
 scripts/fill_func_tables.sql
 scripts/fill_help_tables
@@ -961,11 +1063,31 @@
 scripts/mysqlhotcopy.sh.rej
 scripts/safe_mysqld
 select_test
+server-tools/instance-manager/buffer.cpp
 server-tools/instance-manager/client.c
 server-tools/instance-manager/client_settings.h
+server-tools/instance-manager/command.cpp
+server-tools/instance-manager/commands.cpp
 server-tools/instance-manager/errmsg.c
+server-tools/instance-manager/guardian.cpp
+server-tools/instance-manager/instance.cpp
+server-tools/instance-manager/instance_map.cpp
+server-tools/instance-manager/instance_options.cpp
+server-tools/instance-manager/listener.cpp
+server-tools/instance-manager/log.cpp
+server-tools/instance-manager/manager.cpp
+server-tools/instance-manager/messages.cpp
+server-tools/instance-manager/mysql_connection.cpp
 server-tools/instance-manager/mysqlmanager
+server-tools/instance-manager/mysqlmanager.cpp
+server-tools/instance-manager/options.cpp
+server-tools/instance-manager/parse.cpp
+server-tools/instance-manager/parse_output.cpp
+server-tools/instance-manager/priv.cpp
+server-tools/instance-manager/protocol.cpp
 server-tools/instance-manager/thr_alarm.c
+server-tools/instance-manager/thread_registry.cpp
+server-tools/instance-manager/user_map.cpp
 sql-bench/Results-linux/ATIS-mysql_bdb-Linux_2.2.14_my_SMP_i686
 sql-bench/bench-count-distinct
 sql-bench/bench-init.pl
@@ -994,12 +1116,19 @@
 sql-bench/test-select
 sql-bench/test-transactions
 sql-bench/test-wisconsin
+sql/*.cpp
+sql/*.ds?
+sql/*.vcproj
 sql/.gdbinit
 sql/client.c
 sql/gen_lex_hash
 sql/gmon.out
 sql/handlerton.cc
 sql/lex_hash.h
+sql/max/*
+sql/message.h
+sql/message.mc
+sql/message.rc
 sql/mini_client_errors.c
 sql/my_time.c
 sql/mysql_tzinfo_to_sql
@@ -1338,7 +1467,6 @@
 storage/ndb/src/common/util/libgeneral.dsp
 storage/ndb/src/cw/cpcd/ndb_cpcd
 storage/ndb/src/dummy.cpp
-storage/ndb/src/kernel/blocks/ndb_print_file
 storage/ndb/src/kernel/blocks/backup/libbackup.dsp
 storage/ndb/src/kernel/blocks/backup/ndb_print_backup_file
 storage/ndb/src/kernel/blocks/backup/restore/ndb_restore
@@ -1355,6 +1483,7 @@
 storage/ndb/src/kernel/blocks/dbtux/libdbtux.dsp
 storage/ndb/src/kernel/blocks/dbutil/libdbutil.dsp
 storage/ndb/src/kernel/blocks/grep/libgrep.dsp
+storage/ndb/src/kernel/blocks/ndb_print_file
 storage/ndb/src/kernel/blocks/ndbcntr/libndbcntr.dsp
 storage/ndb/src/kernel/blocks/ndbfs/libndbfs.dsp
 storage/ndb/src/kernel/blocks/qmgr/libqmgr.dsp
@@ -1449,6 +1578,8 @@
 storage/ndb/tools/ndb_test_platform
 storage/ndb/tools/ndb_waiter
 storage/ndb/tools/ndb_waiter.dsp
+strings/*.ds?
+strings/*.vcproj
 strings/conf_to_src
 strings/ctype_autoconf.c
 strings/ctype_extra_sources.c
@@ -1529,10 +1660,15 @@
 test/tools/ndb_cpcc
 test/tools/restart
 test/tools/verify_index
+test1/*
 test_xml
+tests/*.ds?
+tests/*.vcproj
 tests/client_test
 tests/connect_test
 tests/mysql_client_test
+thr_insert_test/*
+thr_test/*
 thread_test
 tmp/*
 tools/my_vsnprintf.c
@@ -1541,8 +1677,13 @@
 tools/mysqltestmanager
 tools/mysys_priv.h
 vi.h
+vio/*.ds?
+vio/*.vcproj
 vio/test-ssl
 vio/test-sslclient
 vio/test-sslserver
 vio/viotest-ssl
-libmysqld/sql_plugin.cc
+vio/viotest-sslconnect.cpp
+vio/viotest.cpp
+zlib/*.ds?
+zlib/*.vcproj

--- 1.143/sql/sql_repl.cc	2005-11-04 21:09:57 +01:00
+++ 1.144/sql/sql_repl.cc	2005-11-18 16:06:34 +01:00
@@ -373,11 +373,6 @@
     goto err;
   }
 
-  /*
-    Call readers_addref before opening log to track count 
-    of binlog readers
-  */
-  mysql_bin_log.readers_addref();
   if ((file=open_binlog(&log, log_file_name, &errmsg)) < 0)
   {
     my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG;
@@ -575,8 +570,7 @@
       goto err;
 
     if (!(flags & BINLOG_DUMP_NON_BLOCK) &&
-        mysql_bin_log.is_active(log_file_name) &&
-        !mysql_bin_log.is_reset_pending())
+        mysql_bin_log.is_active(log_file_name))
     {
       /*
 	Block until there is more data in the log
@@ -689,13 +683,7 @@
     else
     {
       bool loop_breaker = 0;
-      // need this to break out of the for loop from switch
-
-      // if we are going to switch log file anyway, close current log first
-      end_io_cache(&log);
-      (void) my_close(file, MYF(MY_WME));
-      // decrease reference count of binlog readers
-      mysql_bin_log.readers_release();
+      /* need this to break out of the for loop from switch */
 
       thd->proc_info = "Finished reading one binlog; switching to next binlog";
       switch (mysql_bin_log.find_next_log(&linfo, 1)) {
@@ -705,25 +693,16 @@
       case 0:
 	break;
       default:
-	// need following call to do release on err label
-	mysql_bin_log.readers_addref(); 
 	errmsg = "could not find next log";
 	my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG;
 	goto err;
       }
 
-	if (loop_breaker)
-	{
-	  // need following call to do release on end label
-	  mysql_bin_log.readers_addref();
-	  break;
-	}
-
-      /*
-        Call readers_addref before opening log to track count 
-        of binlog readers
-      */
-      mysql_bin_log.readers_addref();
+      if (loop_breaker)
+        break;
+      
+      end_io_cache(&log);
+      (void) my_close(file, MYF(MY_WME));
 
       /*
         Call fake_rotate_event() in case the previous log (the one which
@@ -756,8 +735,6 @@
 
   end_io_cache(&log);
   (void)my_close(file, MYF(MY_WME));
-  // decrease reference count of binlog readers
-  mysql_bin_log.readers_release();
 
   send_eof(thd);
   thd->proc_info = "Waiting to finalize termination";
@@ -784,8 +761,6 @@
   pthread_mutex_unlock(&LOCK_thread_count);
   if (file >= 0)
     (void) my_close(file, MYF(MY_WME));
-  // decrease reference count of binlog readers
-  mysql_bin_log.readers_release();
 
   my_message(my_errno, errmsg, MYF(0));
   DBUG_VOID_RETURN;

--- 1.29.3.1/ndb/src/ndbapi/ndb_cluster_connection.cpp	2005-10-27 17:17:59 +02:00
+++ 1.34/storage/ndb/src/ndbapi/ndb_cluster_connection.cpp	2005-11-18 16:06:35 +01:00
@@ -38,7 +38,6 @@
 static int g_run_connect_thread= 0;
 
 #include <NdbMutex.h>
-NdbMutex *ndb_global_event_buffer_mutex= NULL;
 #ifdef VM_TRACE
 NdbMutex *ndb_print_state_mutex= NULL;
 #endif
@@ -188,6 +187,28 @@
 }
 
 
+int Ndb_cluster_connection::get_no_ready()
+{
+  TransporterFacade *tp = TransporterFacade::instance();
+  if (tp == 0 || tp->ownId() == 0)
+    return -1;
+
+  unsigned int foundAliveNode = 0;
+  tp->lock_mutex();
+  for(unsigned i= 0; i < no_db_nodes(); i++)
+  {
+    //************************************************
+    // If any node is answering, ndb is answering
+    //************************************************
+    if (tp->get_node_alive(m_impl.m_all_nodes[i].id) != 0) {
+      foundAliveNode++;
+    }
+  }
+  tp->unlock_mutex();
+
+  return foundAliveNode;
+}
+
 int
 Ndb_cluster_connection::wait_until_ready(int timeout,
 					 int timeout_after_first_alive)
@@ -206,18 +227,7 @@
   int milliCounter = 0;
   int noChecksSinceFirstAliveFound = 0;
   do {
-    unsigned int foundAliveNode = 0;
-    tp->lock_mutex();
-    for(unsigned i= 0; i < no_db_nodes(); i++)
-    {
-      //************************************************
-      // If any node is answering, ndb is answering
-      //************************************************
-      if (tp->get_node_alive(m_impl.m_all_nodes[i].id) != 0) {
-	foundAliveNode++;
-      }
-    }
-    tp->unlock_mutex();
+    unsigned int foundAliveNode = get_no_ready();
 
     if (foundAliveNode == no_db_nodes())
     {
@@ -264,9 +274,6 @@
   m_connect_thread= 0;
   m_connect_callback= 0;
 
-  if (ndb_global_event_buffer_mutex == NULL)
-    ndb_global_event_buffer_mutex= NdbMutex_Create();
-
 #ifdef VM_TRACE
   if (ndb_print_state_mutex == NULL)
     ndb_print_state_mutex= NdbMutex_Create();
@@ -275,7 +282,7 @@
     new ConfigRetriever(connect_string, NDB_VERSION, NODE_TYPE_API);
   if (m_config_retriever->hasError())
   {
-    printf("Could not connect initialize handle to management server: %s",
+    printf("Could not initialize handle to management server: %s\n",
 	   m_config_retriever->getErrorString());
     delete m_config_retriever;
     m_config_retriever= 0;
@@ -311,11 +318,6 @@
   {
     delete m_config_retriever;
     m_config_retriever= NULL;
-  }
-  if (ndb_global_event_buffer_mutex != NULL)
-  {
-    NdbMutex_Destroy(ndb_global_event_buffer_mutex);
-    ndb_global_event_buffer_mutex= NULL;
   }
 #ifdef VM_TRACE
   if (ndb_print_state_mutex != NULL)

--- 1.153/sql/sql_prepare.cc	2005-11-07 16:24:44 +01:00
+++ 1.154/sql/sql_prepare.cc	2005-11-18 16:06:34 +01:00
@@ -2111,8 +2111,6 @@
       were closed in the end of previous prepare or execute call.
     */
     tables->table= 0;
-    if (tables->nested_join)
-      tables->nested_join->counter= 0;
 
     if (tables->prep_on_expr)
     {
Thread
bk commit into 5.1 tree (guilhem:1.1961)guilhem19 Nov